Skip to content

feat(app): edit automations inline and add full list row actions#1270

Merged
Astro-Han merged 5 commits into
devfrom
claude/automation-edit
Jun 11, 2026
Merged

feat(app): edit automations inline and add full list row actions#1270
Astro-Han merged 5 commits into
devfrom
claude/automation-edit

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

The Automations panel was read-only after creation: detail fields (title, prompt, schedule, model) were static text, and list rows only offered a pause toggle — even though the server has long shipped a full PUT /automation/:id update route. This PR makes the panel editable in place and gives list rows the same three actions as the detail header.

Related: complements #1249 (conversation-side automate_manage), which explicitly scopes panel UI out; #1249's v1 design defers edit to "a panel action" — this is that panel action. No dependency between the two: both wrap the same existing Automation service.

Changes

Detail page — inline editing, one field per patch, no edit mode

  • Title and instructions are transparent always-editable inputs: blur commits, Escape or an empty value reverts.
  • The Repeats row opens the create card's schedule controls (AutomationScheduleControls) in a popover. The kind is fixed by the server (no oneshot↔recurring conversion), so the frequency switch only offers what the kind supports; an arbitrary cron (hourly, day-of-month…) keeps its rhythm until the user explicitly picks a picker frequency.
  • The Model row reuses the composer's ModelSelectorPopover. Switching models clears the variant; picking a thinking level patches the variant alone.
  • The Project row moves the automation to another open project. There is no server-side move (per-project instances; update rejects a foreign projectID) and none is needed — moving only has to affect future runs: the row reuses the create card's folder picker (new "row" trigger variant) and performs create-in-target + delete-from-source. Create-first so a failure loses nothing; if the source delete fails the fresh copy is rolled back. The id changes, the run list starts empty, past runs' sessions survive, paused state is re-applied. A continue automation stays read-only (bound to a conversation in its source project), as does everything when no other project is open.

List rows — delete (shared confirm dialog), pause/resume, and run-now ghost icon buttons fade in on hover where the schedule summary fades out, replacing the lone text-styled pause button.

PlumbingglobalSync.automation.update wrapper (revision-gated apply, same pattern as pause/delete); scheduleDraftFromDefinition inverse mapping with unit tests; the surface's capture-phase Escape handler now yields to open popovers/pickers and focused inputs so Escape closes the top layer instead of unwinding the detail view.

No new i18n keys — all labels reuse existing automations.* strings. The create dialog is untouched.

Verification

  • bun test src/pages/automations — 15 pass (new automation-schedule-form.test.ts covers cron↔draft round-trips and non-mapping crons)
  • bun run typecheck (packages/app) and eslint on touched files — clean
  • E2E e2e/automations/automations-panel.spec.ts — 15 pass locally, including three new user-path tests: cross-project move (definition lands in the target SDK, vanishes from the source, detail stays open on the recreated automation), detail inline edit (title/prompt/schedule/model committed through the real UI, asserted via SDK polls; recurring popover offers no "Once") and list row hover actions (run now / pause / delete through the confirm dialog)
  • Visual check: bun run snap automations-surface with two new shots (detail-schedule, detail-model); reviewed the grid — list-hover shows the three ghost icons, the schedule popover renders Daily | Weekdays | Weekly + time token, the model picker opens anchored to the Model row

Residual risk

  • Per-knob schedule commits mean switching frequency then time issues two small PUTs; each intermediate state is a valid schedule and the store applies the authoritative response, so no torn state.
  • Real-window (Electron) walk of the new popovers not done in this PR; the same popover stack is already exercised inside the create dialog in production.

Summary by CodeRabbit

  • New Features

    • Inline editing for automation title, prompt, schedule, model, and project (move between projects) in the detail view.
    • Hover-visible row actions: Run Now, Pause/Resume, and Delete; Run Now and pause state preserved when moving.
    • Updated schedule editor to show/read unsupported rhythms and improved model picker; restyled folder trigger variant.
  • Tests

    • New e2e coverage validating inline edits, project moves (including rollback cases), row actions, and updated UI snapshots.

The Automations panel was read-only after creation: detail fields
(title, prompt, schedule, model) were static text and list rows only
offered a pause toggle, even though the server has long shipped a full
PUT /automation/:id update route.

Detail page edits in place, one field per patch, no edit mode:
- Title and instructions render as transparent always-editable inputs;
  blur commits, Escape or an empty value reverts.
- The Repeats row opens the create card's schedule controls in a
  popover. The kind is fixed by the server (no oneshot<->recurring
  conversion), so the frequency switch only offers what the kind
  supports, and an arbitrary cron keeps its rhythm until the user
  explicitly picks a picker frequency (scheduleDraftFromDefinition
  returns undefined for it).
- The Model row reuses the composer's ModelSelectorPopover; switching
  models clears the variant, picking a thinking level patches it alone.
- Project stays read-only: update cannot move an automation across
  per-project server instances.

List rows surface the same three actions as the detail header (delete
via the shared confirm dialog, pause/resume, run now) as ghost icon
buttons fading in on hover where the schedule summary fades out,
replacing the lone text-styled pause button.

The surface's capture-phase Escape handler now also yields to open
popovers/pickers and to focused inputs, so Escape closes the top layer
instead of unwinding the detail view.

Verified: bun test automations (15 pass), app typecheck, eslint, e2e
automations-panel suite (15 pass, two new user-path tests for inline
edit and row actions), snap automations-surface with two new shots
(detail-schedule, detail-model) reviewed.
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 84f2c7b0-3ff0-4b11-9407-0148bf419d49

📥 Commits

Reviewing files that changed from the base of the PR and between 53201bc and 90d4f3f.

📒 Files selected for processing (6)
  • packages/app/e2e/automations/automations-panel.spec.ts
  • packages/app/src/pages/automations/automation-detail-editors.tsx
  • packages/app/src/pages/automations/automation-detail.tsx
  • packages/app/src/pages/automations/automation-folder-picker.tsx
  • packages/app/src/pages/automations/automation-list.tsx
  • packages/app/src/pages/automations/automations-surface.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/app/src/pages/automations/automation-list.tsx

📝 Walkthrough

Walkthrough

This PR adds inline editing for automation title, prompt, schedule, and model; schedule round-trip utilities; per-row hover actions (run-now, pause/resume, delete); a globalSync.automation.update helper; a folder-picker variant for detail rows; and E2E tests plus updated snapshots validating these flows.

Changes

Inline Automation Editing

Layer / File(s) Summary
Schedule form round-trip utilities
packages/app/src/pages/automations/automation-schedule-form.ts, packages/app/src/pages/automations/automation-schedule-form.test.ts, packages/app/src/pages/automations/automation-schedule-controls.tsx
scheduleDraftFromDefinition converts automation definitions back into schedule editor drafts for oneshot and supported cron rhythms; tests validate round-trips and timezone handling; AutomationScheduleControls accepts an optional frequencies prop to limit selector options.
Detail editor components
packages/app/src/pages/automations/automation-detail-editors.tsx
Adds EditableText, EditorRow, ProjectEditorRow, ScheduleEditorRow, and ModelEditorRow to derive UI state from definitions and commit patches.
Folder picker variant
packages/app/src/pages/automations/automation-folder-picker.tsx
Adds `variant?: "knob"
Global sync automation.update API
packages/app/src/context/global-sync.tsx
Adds updateAutomation helper that pins directory, calls SDK automation.update, applies authoritative definition to store, and exposes automation.update.
Detail page inline integration
packages/app/src/pages/automations/automation-detail.tsx
Replaces static title/prompt/schedule/model displays with EditableText, ProjectEditorRow, ScheduleEditorRow, and ModelEditorRow; adds commitPatch calling globalSync.automation.update, moveToProject recreate/pause/delete logic, and onMoved callback.
List row action buttons
packages/app/src/pages/automations/automation-list.tsx
Adds hover-only per-row action buttons (delete, pause/resume, run-now) and extends props with onRunNow and onDelete.
Surface orchestration
packages/app/src/pages/automations/automations-surface.tsx
Adds confirmDelete using DialogDeleteAutomation, runNow, and notifyFailure toast helper; refines Escape handling to ignore input/textarea and broader overlays; wires explicit handlers into AutomationList and updates detail to set selection on move.
E2E tests and visual snapshots
packages/app/e2e/automations/automations-panel.spec.ts, packages/app/e2e/snap/automations-surface.snap.ts
Switches title assertions to the inline editor control; adds tests for inline edits (title/prompt/schedule/model), moving automations (including pause/rollback cases), hover actions (run-now/pause/delete), and adds schedule/model detail screenshots to snapshots.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A rabbit nudges title, prompt, and cron,

Hops through editors from dusk till dawn;
Clicks and snapshots, tests that run true,
Hover to pause, resume, or bid adieu;
Tiny commits, a patch—then off I chew!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main changes: adding inline editing capabilities to automations and implementing full list row actions.
Description check ✅ Passed The description is comprehensive and covers all required template sections: summary, why, related issue, human review status, review focus, risk notes, verification steps with actual results, and screenshots/recordings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/automation-edit

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Astro-Han Astro-Han added enhancement New feature or request app Application behavior and product flows labels Jun 11, 2026
@github-actions github-actions Bot added the ui Design system and user interface label Jun 11, 2026
@Astro-Han Astro-Han added the P2 Medium priority label Jun 11, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested priority: P2 (includes user-path files (packages/app/src/context/global-sync.tsx, packages/app/src/pages/automations/automation-detail-editors.tsx, packages/app/src/pages/automations/automation-detail.tsx, packages/app/src/pages/automations/automation-list.tsx, packages/app/src/pages/automations/automation-schedule-controls.tsx, packages/app/src/pages/automations/automation-schedule-form.test.ts, packages/app/src/pages/automations/automation-schedule-form.ts, packages/app/src/pages/automations/automations-surface.tsx)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces inline editing for automation details (title, prompt, schedule, and model) and exposes quick actions (run, pause, delete) on hover for automation list rows, supported by new end-to-end and unit tests. Feedback highlights a potential issue in EditableText where a failed asynchronous commit could overwrite active user typing if they refocus the input, and suggests a cleaner payload structure when updating the model in ModelEditorRow by only passing the required providerID and modelID fields.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/app/src/pages/automations/automation-detail-editors.tsx
Comment thread packages/app/src/pages/automations/automation-detail-editors.tsx
The schedule trigger read as plain text next to the Model row's chevron,
hiding that it is clickable (real-window feedback on PR #1270).
The server has no cross-project move (per-project instances; update
rejects a foreign projectID), and one is not needed: moving only has to
affect future runs. The Project row becomes the create card's folder
picker (new "row" trigger variant) and moving recreates the definition
in the target project, then deletes the source. Create-first so a
failure loses nothing; if the source delete fails the fresh copy is
rolled back instead of leaving a duplicate. The id changes and the run
list starts empty; past runs' sessions survive. Paused state is
re-applied after the move. A continue automation stays read-only (it
loops inside a conversation that only exists in its source project), as
does everything when no other project is open.

E2E: real-path move test (pick target project in the detail row, assert
the definition lands in the target SDK, vanishes from the source, and
the detail stays open on the recreated automation).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/app/e2e/automations/automations-panel.spec.ts (1)

192-193: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replace fixed sleeps with observable waits in these test paths.

Line 192 and Line 333 use page.waitForTimeout(...). In this suite, that’s a reliability risk and violates the E2E rule to wait on observable state (locator assertions / expect.poll(...) / existing helpers) instead of arbitrary delays.

As per coding guidelines, “Never use page.waitForTimeout(...) to make a test pass; instead wait for observable state with locator assertions, expect.poll(...), or existing helpers.”

Also applies to: 333-334

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/e2e/automations/automations-panel.spec.ts` around lines 192 -
193, Replace the fixed sleep with an observable wait: remove
page.waitForTimeout(250) and instead wait until the expected state is observed
(for example use expect.poll(() => runListRequests).toBe(1) or, preferably,
assert a DOM change via a locator like await
expect(someRunListLocator).toHaveCount(...) / toBeVisible()). Update both
occurrences around the expect(runListRequests).toBe(1) so the test waits on
observable state (expect.poll or locator assertion) rather than a fixed timeout.

Source: Coding guidelines

packages/app/src/pages/automations/automation-list.tsx (1)

46-53: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Show the action buttons when the row itself has keyboard focus.

Line 46 hides the schedule summary on group focus, but Line 53 only reveals the action row on hover or when one of its own buttons is already focused. Tabbing onto the row leaves the right side blank and makes the next tab stop invisible.

Suggested fix
-              <div class="absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover/automation:opacity-100">
+              <div class="absolute right-2.5 top-1/2 flex -translate-y-1/2 items-center gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover/automation:opacity-100 group-focus-within/automation:opacity-100">
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/src/pages/automations/automation-list.tsx` around lines 46 - 53,
The action buttons container currently only becomes visible on hover or when its
own children are focused; update the div whose class includes "opacity-0
transition-opacity focus-within:opacity-100 group-hover/automation:opacity-100"
to also include "group-focus/automation:opacity-100" so the actions are revealed
when the row (the group trigger button) receives keyboard focus; adjust the
class string in the component in automation-list.tsx (the div next to
formatScheduleSummary(automation, language.t)) to include that token.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/app/e2e/automations/automations-panel.spec.ts`:
- Around line 192-193: Replace the fixed sleep with an observable wait: remove
page.waitForTimeout(250) and instead wait until the expected state is observed
(for example use expect.poll(() => runListRequests).toBe(1) or, preferably,
assert a DOM change via a locator like await
expect(someRunListLocator).toHaveCount(...) / toBeVisible()). Update both
occurrences around the expect(runListRequests).toBe(1) so the test waits on
observable state (expect.poll or locator assertion) rather than a fixed timeout.

In `@packages/app/src/pages/automations/automation-list.tsx`:
- Around line 46-53: The action buttons container currently only becomes visible
on hover or when its own children are focused; update the div whose class
includes "opacity-0 transition-opacity focus-within:opacity-100
group-hover/automation:opacity-100" to also include
"group-focus/automation:opacity-100" so the actions are revealed when the row
(the group trigger button) receives keyboard focus; adjust the class string in
the component in automation-list.tsx (the div next to
formatScheduleSummary(automation, language.t)) to include that token.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 39ef1e21-00b8-4844-9b4a-cbc741e49ea5

📥 Commits

Reviewing files that changed from the base of the PR and between fd8a5bd and 53201bc.

📒 Files selected for processing (10)
  • packages/app/e2e/automations/automations-panel.spec.ts
  • packages/app/e2e/snap/automations-surface.snap.ts
  • packages/app/src/context/global-sync.tsx
  • packages/app/src/pages/automations/automation-detail-editors.tsx
  • packages/app/src/pages/automations/automation-detail.tsx
  • packages/app/src/pages/automations/automation-list.tsx
  • packages/app/src/pages/automations/automation-schedule-controls.tsx
  • packages/app/src/pages/automations/automation-schedule-form.test.ts
  • packages/app/src/pages/automations/automation-schedule-form.ts
  • packages/app/src/pages/automations/automations-surface.tsx

The row variant inherited picker.css's pill hover via data-picker-trigger
while Repeats/Model use the sidebar's underline hover. Drop the attribute
for the row variant and use the same underline affordance.
…a11y)

Code review follow-ups on the inline editors:

- Schedule (P2): a rhythm the picker cannot express (hourly, interval,
  arbitrary cron) now renders the Repeats row read-only instead of
  pre-selecting DEFAULT_SCHEDULE behind a trigger, which let any knob
  change silently rewrite an hourly cron to daily/weekly.
- Move (P2): a paused source that fails to re-pause on the target now
  fails the whole move (copy rolled back, source kept) instead of
  swallowing the error and leaving a silenced automation live elsewhere.
- Inline text (P2): a failed save only rolls the control back if it still
  shows the failed value, so a retype while the request was in flight is
  no longer clobbered by the stale value.
- Model (P3): the update payload is built from providerID/modelID
  explicitly rather than spreading the picker item.
- List a11y (P3): the hover action cluster also reveals on row keyboard
  focus (group-focus-within), so a keyboard user does not face a blank
  slot where the schedule summary hid.

E2E: hourly-cron read-only row; paused move keeps paused; failed-pause
move rolls back with a visible error toast; row focus reveals actions.
@Astro-Han Astro-Han merged commit 6db4738 into dev Jun 11, 2026
34 of 36 checks passed
@Astro-Han Astro-Han deleted the claude/automation-edit branch June 11, 2026 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows enhancement New feature or request P2 Medium priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant