Skip to content

feat(settings): edit scheduled action triggers in a modal - #1521

Merged
harshithmohan merged 4 commits into
masterfrom
feat/scheduled-action-triggers-modal
Oct 26, 2026
Merged

harshithmohan merged 4 commits into
masterfrom
feat/scheduled-action-triggers-modal

Conversation

@harshithmohan

@harshithmohan harshithmohan commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Summary

Moving scheduled-action trigger editing out of each action's accordion and into a modal. The row was holding an unsaved draft (keyed triggers, validation errors, save/reset/discard) inside a list that polls every 2s while an action is running, and it was doing two unrelated jobs: reporting an action's state and editing its triggers.

Relates to #1484.

Changes

  • ScheduledActionItem.tsx — now read-only: name (truncated with a tooltip), state badge, summary line, run-now, cancel-run, an edit-triggers button and a chevron accordion of details (last run, last run by a trigger, next run, minimum interval, and the per-action note on whether a manual run counts toward the schedule). The state badge shrank and dimmed (text-sm → text-xs opacity-65) so it reads as a status next to the name rather than competing with it.
  • TriggersModal.tsx (new) — the whole editor: add/remove/edit triggers, validation, save, reset to defaults and cancel. Draft is synced from the action with useSyncedState, keyed so an editor keeps its inputs when one above it is removed. Save is disabled while a reset is in flight, and the modal refuses to close mid-save or mid-reset. Validation errors clear as soon as the draft changes.
  • ScheduledActionsSettings.tsx — owns the selected action and renders the modal; primary hotkey scope handed off while it is open. The header gained a line explaining that a manual run usually counts toward the schedule, and each category's divider moved from after the category to before it.
  • helpers.ts — triggerTypes is keyed by type instead of searched, and getTriggerType/getTriggerLabel are gone; lookups fall back to the raw type for a trigger the WebUI does not know, which is kept as-is on save.
  • TriggerEditor.tsx — follows the triggerTypes change.
  • scheduled-action.ts — doc comments: "by hand" → "manual".

@hidden4003 hidden4003 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review of #1521

The PR matches its description and follows the repo's patterns. I have one question and a few small items. None of them block it.

Question: modal mount model

Every other modal in the repo (EditEpisodeTitleModal, HashTypesModal, ReleaseManagementSettingsModal and so on) is always mounted. Each takes a show prop and calls both useToggleModalKeybinds(show, 'modal') and useToggleModalKeybinds(!show, 'primary').

TriggersModal is instead mounted conditionally with show hard-coded to true. It calls useToggleModalKeybinds(true, 'modal') itself, and the page hands primary back through useToggleModalKeybinds(!selectedActionID, 'primary'). As a result:

  • ModalPanel's 150ms closeTimeoutMS exit animation never plays, because the modal unmounts immediately.
  • Keybind ownership is split between the page and the modal.

Conditional mounting does give a fresh draft and cleared errors on every open. Is this an intentional change to our modal pattern, or should it be refactored to the show-prop convention?

Description

Two changes in ScheduledActionsSettings.tsx aren't mentioned in the PR description:

  • a new explanatory line under the header about manual runs counting toward the schedule;
  • each divider moved from after a category to before it.

Nitpicks

  • ScheduledActionItem.tsx: the info wrapper still has text-left, left over from when it was a <button>.
  • ScheduledActionItem.tsx: the Run button's inline if/else in onClick could be a named handleRun, like handleCancel.
  • The badge style changed from text-sm to text-xs opacity-65. Please mention it in the description if it's intentional.

The trigger editor lived inside each action's accordion, so the row
carried the whole draft state: keyed triggers, validation errors, save,
reset and discard. A row in a polling list is a bad place for an
unsaved draft, and the row was doing two unrelated jobs.

The row is now read-only: state, runs, run now, cancel, an edit-triggers
button and an accordion of details. The editor moved to TriggersModal,
rendered once by the settings page for the selected action, so the
trigger list UI exists in exactly one place.

- Draft synced from the action via useSyncedState, keyed so an editor
  keeps its inputs when one above it is removed.
- Save is disabled while a reset is in flight, and the modal cannot be
  closed mid-save or mid-reset.
- Validation errors clear as soon as the draft changes.
- The per-action note on whether a manual run counts toward the
  schedule is kept, now in the details accordion.
- triggerTypes is keyed by type instead of searched; lookups fall back
  to the raw type for a trigger the WebUI does not know.
Name the run handler like the cancel one instead of branching inline in
onClick, and drop the text-left that only made sense while the row's
info block was a button.
…action

Drive ModalPanel through a `show` prop and hand both keybind lines to the
modal, so the page no longer toggles scopes and the modal reclaims `modal`
on every reopen instead of only at mount.

Key the modal by action ID so switching actions drops the previous action's
draft and validation errors, which `useSyncedState` alone would not clear.
@harshithmohan
harshithmohan force-pushed the feat/scheduled-action-triggers-modal branch from 48bbf7e to cdbcff0 Compare October 26, 2026 12:40
@harshithmohan
harshithmohan merged commit b9e3406 into master Oct 26, 2026
3 checks passed
@harshithmohan
harshithmohan deleted the feat/scheduled-action-triggers-modal branch October 26, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants