Skip to content

AI First Starting UX: Browse templates path - modal entry point, portability, and workflow creation #4870

Description

@lmac-1

Parent epic: #4848 AI-First Starting UX
Depends on: #4856

What this issue builds

Three concrete pieces:

  1. A portable template modal component — accepts a templates array as a prop and an
    onSelect callback; knows nothing about workflow creation logic
  2. Template data wiring — fetches templates (base + user-created) via the existing Phoenix
    Channel and passes them into the modal component
  3. Workflow creation on card click — selecting a template applies it to the canvas and
    saves the workflow to the DB, ending pink toolbar state

What is not changing: the template data source (list_templates channel message +
WorkflowTemplates.list_templates/0), the importWorkflow function in createWorkflowStore.ts,
the validate_workflow_name channel message, or the template YAML content itself.

TBC: The designs for the modal may change

User flow

  1. User clicks "Browse templates" on the landing screen
  2. A modal opens: "Browse Workflow Templates" — search bar, flat list of template cards
  3. User can search/filter the list
  4. Clicking a card:
    • Modal closes
    • Canvas is populated with the template's structure
    • Workflow is saved to the DB (first DB write, same as AI path auto-save)
    • Pink toolbar ends: URL updates to /projects/{id}/w/{workflow_id}, Save becomes enabled
    • Workflow is named after the template with uniqueness enforced (existing behaviour)
  5. Closing the modal via the X button returns the user to the landing screen — no navigation
  6. Pressing browser back while the modal is open navigates away from /new entirely (standard
    modal behaviour — the modal does not push a history entry)

After creation, pressing browser back goes to wherever the user came from (workflow list), not
back to /new. This is consistent with the AI path: replaceState swaps /new/w/{id}
without adding a history entry.

Implementation

Component design: portability first

The modal component should be a pure presentational component — it receives data as props
and fires callbacks. It has no knowledge of channels, workflow state, or creation logic.

interface WorkflowTemplateBrowserProps {
  templates: TemplateItem[]
  onSelect: (template: TemplateItem) => void
  onClose: () => void
}

Where TemplateItem is a minimal type:

interface TemplateItem {
  id: string
  name: string
  description?: string
  code: string  // raw YAML string
}

This matches the shape already returned by fetchTemplates in
assets/js/collaborative-editor/api/templates.ts (which calls 'list_templates' over the
channel) and the BaseTemplate type in
assets/js/collaborative-editor/constants/baseTemplates.ts.

Do not pass workflow store references, save functions, or creation callbacks into this
component.
The onSelect callback receives the raw template — the parent handles everything
else. This is the portability contract: the component can be dropped anywhere and only needs
a templates array and two callbacks.

Template data source (existing, reused)

Templates are already fetched via the Phoenix Channel:

  • fetchTemplates in assets/js/collaborative-editor/api/templates.ts sends
    'list_templates' over the channel
  • The channel handler in lib/lightning_web/channels/workflow_channel.ex:608 calls
    Lightning.WorkflowTemplates.list_templates/0 and returns rendered templates
  • Base templates (webhook + cron) live in
    assets/js/collaborative-editor/constants/baseTemplates.ts
  • TemplatePanel.tsx:36-277 shows the existing merge pattern: base templates are prepended
    to user templates before rendering

The parent of the new modal should fetch templates on mount using the same fetchTemplates
call and merge them with the base templates in the same order. No new channel messages or
backend changes are needed.

Workflow creation on card select

When onSelect fires with a template, the parent component should:

  1. Call parseWorkflowYAML(template.code) (from assets/js/yaml/util.ts:291) to parse YAML
    into a WorkflowSpec
  2. Call convertWorkflowSpecToState(spec) (assets/js/yaml/util.ts:157) to convert to a
    YAMLWorkflowState
  3. Call workflowStore.importWorkflow(workflowState) — this already:
    • Sends 'validate_workflow_name' over the channel (workflow_channel.ex:451) to enforce
      uniqueness (appending " 1", " 2" etc. if needed)
    • Calls YAMLStateToYDoc.applyToYDoc(ydoc, validatedState) to write into Y.Doc
    • Fires flowEvents.dispatch('fit-view') to frame the canvas
  4. After importWorkflow succeeds, call saveWorkflow({ silent: true }) — same auto-save
    pattern as the AI path (Issue 2, hooks/useAIWorkflowApplications.ts:171-228)

This is the same sequence the existing TemplatePanel.tsx uses for steps 1-3, and the same
auto-save pattern Issue 2 adds for step 4. No new logic is needed — only the wiring.

Naming behaviour

The workflow name comes from the YAML name: field in the template's code. The
validate_workflow_name channel message enforces uniqueness within the project (existing
behaviour). The modal component does not touch naming — it passes the raw template to
onSelect and the existing importWorkflow + channel validation handles the rest.

Do not add any rename event listeners, name-update callbacks, or name-watching logic to the
modal component. The name should not be connected to the modal in any observable way.

Modal open/close state

The modal is controlled by a boolean state variable in the landing screen component (Issue 1).

  • "Browse templates" card click → sets isTemplateBrowserOpen = true
  • X button in modal → sets isTemplateBrowserOpen = false (returns to landing screen)
  • Card click → triggers onSelect → after workflow creation, navigates to canvas (landing
    screen is no longer rendered)

The modal does not call pushState or add a history entry. Pressing browser back while
the modal is open will navigate away from /new by natural browser behaviour — this is
intentional and consistent with standard modal behaviour anywhere else in the app.

No canvas preview on hover

The existing TemplatePanel previews templates on the canvas as the user browses. This
behaviour is not being built.
Clicking a card is the only action. Do not wire up
uiStore.selectTemplate, TemplateDetailsCard, or any preview mechanism.

Files to modify / create

File Change
New: components/WorkflowTemplateBrowser.tsx Portable modal component — accepts templates, onSelect, onClose props
assets/js/collaborative-editor/api/templates.ts No change — reuse fetchTemplates as-is
assets/js/collaborative-editor/constants/baseTemplates.ts No change — reuse base templates as-is
Landing screen component (Issue 1) Fetch templates on mount; control modal open state; wire onSelect to importWorkflow + saveWorkflow
assets/js/yaml/util.ts No change — reuse parseWorkflowYAML (line 291) and convertWorkflowSpecToState (line 157)

Note: TemplatePanel.tsx, TemplateCard.tsx, TemplateSearchInput.tsx, and
TemplateDetailsCard.tsx are not modified. The new component is written fresh and is
intentionally not a fork of TemplatePanel.tsx — that component carries canvas preview
logic, selection state, and left-panel-specific concerns that do not belong here.

Out of scope

  • Template category filters (Event-based, Scheduled) — flat list only; categories may come later
  • Canvas preview on hover
  • "Build with AI" fallback from the search bar (present in TemplateSearchInput.tsx — not
    replicated here)
  • Any changes to the template data model or backend
  • TemplatePanel.tsx and the existing left-panel browsing flow — untouched

Acceptance Criteria

Modal opens from landing screen

  • Clicking "Browse templates" on the landing screen opens the template modal
  • The modal is visible over the landing screen
  • The user is still in pink toolbar state while the modal is open (URL /new, Save
    disabled, no DB record)
  • The modal renders a search bar and a flat list of template cards (base templates +
    user-created templates, same set as existing template browser)

Search

  • Typing in the search bar filters the visible template cards
  • Clearing the search bar restores the full list
  • Search is case-insensitive

Card selection creates the workflow

  • Clicking a template card closes the modal
  • The canvas is populated with the template's workflow structure
  • The workflow is saved to the DB automatically (no "Create" button, no manual save)
  • Pink toolbar ends: URL updates to /projects/{id}/w/{workflow_id} without a page reload
  • Save becomes enabled after creation
  • The workflow is named after the template (with uniqueness enforced — e.g. "Event-based
    workflow 1" if the name already exists in the project)
  • The workflow name is not updated or watched by the modal at any point

Closing the modal

  • Clicking the X button (or equivalent close action) closes the modal and returns the user
    to the landing screen
  • No workflow is created when the modal is closed without selecting a template
  • The user remains in pink toolbar state after closing

Back navigation

  • Pressing browser back while the modal is open navigates away from /new entirely —
    consistent with standard modal behaviour
  • After workflow creation, pressing browser back goes to wherever the user came from
    (e.g. workflow list) — not back to /new or the modal

Portability

  • The modal component receives templates as a prop array — it does not fetch data itself
  • The modal component has no direct dependency on workflow store, channel, or save logic
  • onSelect and onClose are the only callbacks — no other workflow-state coupling

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions