@php // Node display titles handed to the canvas JS so every label stays server-side // translatable (the builder never hard-codes English in JS). $nodeLabels = [ 'trigger' => __('Trigger'), 'send_message' => __('Send message'), 'send_media' => __('Send media'), 'send_buttons' => __('Send buttons'), 'send_gallery' => __('Send gallery'), 'ask_question' => __('Ask a question'), 'condition' => __('Condition'), 'branch' => __('Branch'), 'add_label' => __('Add label'), 'remove_label' => __('Remove label'), 'set_status' => __('Set status'), 'assign_staff' => __('Assign staff'), 'assign_ai_agent' => __('Assign AI agent'), 'pause_bot' => __('Pause bot'), 'resume_bot' => __('Resume bot'), 'call_webhook' => __('Call webhook'), 'wait' => __('Wait'), 'drip' => __('Drip follow-up'), 'create_client_account' => __('Create client account'), 'welcome_tour' => __('Welcome tour'), '_empty' => __('(empty)'), '_items' => __('items'), '_paths' => __('paths'), '_unsupported' => __('Not supported by the selected channels'), '_fullscreen' => __('Full screen'), '_exit_fullscreen' => __('Exit full screen'), // Multi-output port row labels (CRM-4 fix — see automation-canvas.js // portRowLabel()). `_case` is the fallback prefix for a still-blank // branch path ("Case 1", "Case 2", ...); the `_port_*` keys are the // fixed outcomes of ask_question / condition / create_client_account, // matched 1:1 against NODE_TYPES[type].ports in the canvas JS. '_case' => __('Case'), '_port_captured' => __('Captured'), '_port_gave_up' => __('Gave up'), '_port_yes' => __('Yes'), '_port_no' => __('No'), '_port_created' => __('Created'), '_port_failed' => __('Failed'), ]; // Palette groups (trigger is auto-seeded as the entry node, so it is omitted). $palette = [ __('Messaging') => ['send_message', 'send_media', 'send_gallery', 'send_buttons', 'ask_question'], __('Flow') => ['condition', 'branch', 'wait', 'drip'], __('Actions') => ['add_label', 'remove_label', 'set_status', 'assign_ai_agent', 'assign_staff', 'pause_bot', 'resume_bot', 'create_client_account', 'call_webhook'], ]; // Interpolation tokens must live in PHP, NOT inside a Blade {{ }} echo — a // literal {{ }} nested in an echo breaks the compiler (documented pitfall). $tokenContactName = '{{contact.name|there}}'; $tokenAnswersEmail = '{{answers.email}}'; $phSendMessage = __('Hi :token!', ['token' => $tokenContactName]); $phAskHint = __('Use it later with :token', ['token' => $tokenAnswersEmail]); // Trigger-event catalogue for the Trigger node's event picker + list badge // (six events; the three "event" kinds fire from UI actions, §8). $rfTriggers = []; foreach ((array) config('crm.automation_triggers', []) as $val => $meta) { $rfTriggers[] = ['value' => $val, 'label' => __($meta['label']), 'needs_keyword' => (bool) ($meta['needs_keyword'] ?? false)]; } // Merge-tag catalogue → the clickable chips rendered in every text panel. The // token strings carry literal {{ }} and MUST stay in PHP (see pitfall above); // they reach the canvas only through @js(), never a Blade echo. $rfVariables = array_map( fn ($v) => ['token' => $v['token'], 'label' => __($v['label']), 'example' => $v['example']], (array) config('crm.automation_variables', []), ); // Targetable channels (no support) for the Trigger node's channel scope boxes. $rfChannelMeta = []; foreach ((array) config('crm.channels', []) as $type => $meta) { if ($type !== 'support') { $rfChannelMeta[] = ['type' => $type, 'label' => $meta['label'], 'color' => $meta['color']]; } } // Static help text (safe to echo — echoing a variable whose VALUE contains // {{ }} is fine; only literal {{ }} in template text breaks the compiler). $rfVarHelp = __(config('crm.automation_personalization_example', '')); $rfCapNote = __(config('crm.automation_channel_note', '')); @endphp
{{ __('Build visual flows that welcome, capture and convert on every channel.') }}
| {{ __('Automation') }} | {{ __('Trigger') }} | {{ __('Channels') }} | {{ __('Runs') }} | {{ __('Status') }} | {{ __('Actions') }} |
|---|---|---|---|---|---|
| {{ $a->name }} | {{ __(config("crm.automation_triggers.{$a->trigger_type}.label", ucfirst(str_replace('_', ' ', $a->trigger_type)))) }} |
@if (empty($aChannels))
{{ __('All channels') }}
@else
@foreach (array_slice($aChannels, 0, 5) as $ch)
|
{{ $a->runs_count }} |
|
{{ __('Browse ready-made flows by the network they run on. Flows that use interactive buttons only appear under networks that support them.') }}
{{ $message }}
@enderror{{ __('Select the Trigger node on the canvas to set the event, keyword and channels.') }}
{{ $message }}
@enderror @error('keyword'){{ $message }}
@enderror @error('flowData'){{ $message }}
@enderror{{ __('Select a node to edit it, or drag one from the palette.') }}
{{ __('Comma-separate keywords; the flow starts when an inbound message contains any of them.') }}
{{ $rfCapNote }}
{{ $rfVarHelp }}
{{ __('1-3 options show as reply buttons, 4-10 as a menu list on chat channels; Instagram and Email get a numbered list.') }}
{{ $phAskHint }}
{{ __('One output port per path. Comma-separate keywords; the reply routes to the first match.') }}
{{ __('This node has no settings — just connect it in the flow.') }}