mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-17 03:53:06 +00:00
feat(automation): add composer
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# Automation UI Foundation and Global Composer Tasks
|
||||
|
||||
## PR 1 — automation UI foundation
|
||||
|
||||
### Completed implementation
|
||||
|
||||
- [x] Start from clean `master` and retain the mixed branch as reference only.
|
||||
- [x] Keep automation create/edit payloads definition-only.
|
||||
- [x] Preserve global and event trigger references when definitions are edited.
|
||||
- [x] Refuse deletion of definitions referenced by global triggers or rundown events.
|
||||
- [x] Reject trigger bindings submitted to definition CRUD.
|
||||
- [x] Persist normalized output values returned by server validation.
|
||||
- [x] Support the full filter-operator contract, including `not_contains`.
|
||||
- [x] Extract focused OSC, HTTP, Ontime, and output-card form components.
|
||||
- [x] Add honest per-output test success/error feedback and failed-save retry behavior.
|
||||
- [x] Add shared lifecycle labels and output summaries.
|
||||
- [x] Clarify global trigger scope, duplicate behavior, and missing references.
|
||||
- [x] Improve event trigger lifecycle labels and output visibility.
|
||||
- [x] Keep recipes, composer code, and lifecycle-on-definition state out of the PR.
|
||||
- [x] Cover shared lifecycle labels, the full filter-operator contract, controller rejection of trigger fields, and
|
||||
definition output replacement with focused regression tests.
|
||||
|
||||
### Required before merge
|
||||
|
||||
- [x] Accept IPv6 OSC targets as well as IPv4 and hostnames.
|
||||
- [x] Add a parser regression test using an IPv6 target such as `::1`.
|
||||
- [x] Keep runtime-template hostname support and normalized persistence intact.
|
||||
- [x] Remove stale output-form styles that no rendered component references.
|
||||
- `oscSection`
|
||||
- `httpSection`
|
||||
- `actionSection`
|
||||
- `outputCard`
|
||||
- nested `test`
|
||||
- [x] Run the browser smoke check:
|
||||
- create and edit a definition;
|
||||
- add, remove, and test OSC, HTTP, and Ontime outputs;
|
||||
- retry a save after a server error;
|
||||
- create/edit a global trigger;
|
||||
- attach the same definition to an event;
|
||||
- verify missing and duplicate states;
|
||||
- verify narrow-panel horizontal scrolling and sticky headers.
|
||||
- [x] Show the concise server validation message after a failed save instead of the full raw 422 response and submitted
|
||||
definition; keep the form open and retryable.
|
||||
- [x] Re-run final verification and inspect the final diff for temporary code, stale comments, generated files, and
|
||||
recipe/composer leakage.
|
||||
|
||||
### Verification already observed
|
||||
|
||||
- [x] Server test pipeline: 51 files passed; 778 tests passed; 6 todo.
|
||||
- [x] Client test pipeline: 34 files passed; 276 tests passed.
|
||||
- [x] Client and server type checks passed.
|
||||
- [x] Client and server lint passed.
|
||||
- [x] Format check passed.
|
||||
- [x] Client and server builds passed with only existing Vite warnings.
|
||||
- [x] `git diff --check master...HEAD` passed.
|
||||
|
||||
### PR 1 checkpoint
|
||||
|
||||
- [x] IPv6 compatibility and stale-style cleanup are committed to their owning commits.
|
||||
- [x] Added PR 1 regression coverage is committed separately from production behavior.
|
||||
- [x] Browser smoke check is recorded.
|
||||
- [x] PR 1 is self-sufficient and ready for human review.
|
||||
|
||||
## PR 2 — global automation composer and recipes
|
||||
|
||||
### Task 1: Define the composition contract
|
||||
|
||||
- [ ] Add a create-only command containing a definition plus zero or more global lifecycles.
|
||||
- [ ] Return the created definition and trigger bindings.
|
||||
- [ ] Keep persisted `Automation` and `Trigger` entities and ordinary CRUD unchanged.
|
||||
- [ ] Document that zero lifecycles saves a reusable definition only.
|
||||
|
||||
### Task 2: Add atomic global composition creation
|
||||
|
||||
- [ ] Validate the definition and every lifecycle before writing.
|
||||
- [ ] Normalize or reject duplicate lifecycle inputs consistently.
|
||||
- [ ] Assign IDs and persist the definition and bindings in one settings write.
|
||||
- [ ] Test success, invalid input, duplicate inputs, and no-partial-write failure behavior.
|
||||
|
||||
### Task 3: Build the manual composer
|
||||
|
||||
- [ ] Present separate Global trigger, Conditions, and Actions sections.
|
||||
- [ ] Reuse the PR 1 output editor components where their contracts fit.
|
||||
- [ ] Support multiple global lifecycles and definition-only save.
|
||||
- [ ] Test failed-save retry and refresh of both definitions and triggers.
|
||||
|
||||
### Task 4: Move recipes onto the composer
|
||||
|
||||
- [ ] Restore the recipe catalog and parameter setup without restoring trigger ownership to definitions.
|
||||
- [ ] Make every recipe declare global lifecycle defaults explicitly.
|
||||
- [ ] Submit manual and recipe flows through the same composition command.
|
||||
- [ ] Test representative OSC, HTTP, and Ontime recipes.
|
||||
|
||||
### Task 5: Evaluate complete usage counts
|
||||
|
||||
- [ ] Implement a pure aggregation over global triggers and all project rundowns.
|
||||
- [ ] Test zero usage, both scopes, multiple rundowns, duplicates, and missing references.
|
||||
- [ ] Confirm the read path performs no repeated per-definition scans or persisted counting.
|
||||
- [ ] Ship the UI count only if both global and event usage are complete and cheap; otherwise record the decision to
|
||||
defer it.
|
||||
|
||||
### Task 6: Integrate and verify
|
||||
|
||||
- [ ] Keep event-scoped recipes and event-composer navigation absent.
|
||||
- [ ] Verify disabled automations, errors, modal keyboard behavior, and narrow layouts.
|
||||
- [ ] Run full tests, type checks, lint, formatting, and builds.
|
||||
- [ ] Review the final diff for stale compatibility code and scope leakage.
|
||||
|
||||
### PR 2 checkpoint
|
||||
|
||||
- [ ] Manual and recipe flows create global compositions atomically.
|
||||
- [ ] Reusable definitions remain independently editable and attachable in both scopes.
|
||||
- [ ] Usage information is complete or intentionally omitted.
|
||||
- [ ] PR 2 is ready for human review.
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
# Automation UI Foundation and Global Composer Plan
|
||||
|
||||
## Decision
|
||||
|
||||
Keep the work split into two pull requests:
|
||||
|
||||
1. **PR 1 — automation UI foundation:** reusable definition editing, clearer global/event trigger surfaces, output
|
||||
editing, and validation hardening.
|
||||
2. **PR 2 — global automation composer and recipes:** one create flow that produces a reusable definition and zero or
|
||||
more global trigger bindings.
|
||||
|
||||
The implementation confirms that this boundary is workable. PR 1 is useful without recipes and does not move lifecycle
|
||||
ownership into automation definitions. PR 2 can therefore build on a stable definition/trigger model instead of
|
||||
repairing the old mixed branch.
|
||||
|
||||
## Architecture decisions
|
||||
|
||||
- An automation definition owns its title, filters, and outputs.
|
||||
- A trigger owns lifecycle, scope, and the reference to a definition.
|
||||
- The composer is a create-time orchestration over those two existing resources; it is not a new persisted entity.
|
||||
- The first composer creates global bindings only. Event-scoped recipes remain out of scope.
|
||||
- Users may continue editing definitions and triggers independently after creation.
|
||||
- Recipes use the same composition command as the manual composer.
|
||||
- Usage is derived, not persisted. Show it only if complete global and event counts can be obtained with one bounded
|
||||
aggregation; otherwise omit it.
|
||||
|
||||
## Current PR 1 assessment
|
||||
|
||||
Branch: `automation-ui`
|
||||
|
||||
Commits:
|
||||
|
||||
- `b38e5de9` — template-aware output validation and normalized persistence.
|
||||
- `1732c7cc` — definition/output editing, clearer global/event trigger presentation, and regression coverage for the
|
||||
definition/trigger boundary and shared presentation helpers.
|
||||
|
||||
The two commits can remain in one PR. Although the total diff is slightly above the normal review target, much of it is
|
||||
the extraction of the existing output form into focused components, and the final behavior is one coherent foundation.
|
||||
Do not create a third PR solely for the validation commit.
|
||||
|
||||
### Review result
|
||||
|
||||
The code-review findings are resolved:
|
||||
|
||||
- IPv6 support is restored in OSC target validation with a `::1` regression test while IPv4, hostname, and runtime
|
||||
template handling remain covered.
|
||||
- The obsolete `oscSection`, `httpSection`, `actionSection`, `outputCard`, and nested `test` styles left behind by the
|
||||
output-card extraction have been removed.
|
||||
|
||||
The browser smoke check passed for definition creation/editing, all output types, failed-save retry, global trigger
|
||||
editing, event attachment, duplicate and missing-reference states, and narrow-panel scrolling with sticky headers. It
|
||||
revealed one small UX issue which is now fixed: server-side validation failures show the concise validation message (for
|
||||
example, `Invalid OSC target`) instead of the complete raw 422 response and submitted definition.
|
||||
|
||||
No recipe, composer, lifecycle-on-definition, or event-scoped recipe work should be added while closing these items.
|
||||
|
||||
## PR 2 sequence
|
||||
|
||||
1. Define a create-only global composition request and response without changing definition CRUD.
|
||||
2. Implement atomic server creation of one definition plus distinct global lifecycle bindings.
|
||||
3. Build a manual `When -> If -> Then` composer using the PR 1 output editors.
|
||||
4. Move recipes onto the same composition command and label their global scope explicitly.
|
||||
5. Spike complete usage aggregation across global triggers and all project rundowns; ship the count only if the bounded
|
||||
scan is cheap and does not widen persisted state.
|
||||
6. Verify refresh, error recovery, disabled-automation behavior, responsive layout, and representative recipes.
|
||||
|
||||
## Pull request boundaries
|
||||
|
||||
### PR 1 includes
|
||||
|
||||
- Definition-only create/edit behavior and rejection of trigger fields at that boundary.
|
||||
- Reference-safe deletion behavior and tests for global/event usages.
|
||||
- Output cards, output summaries, test feedback, shared lifecycle labels, and trigger clarity.
|
||||
- Template-aware OSC/HTTP validation.
|
||||
- The minimum shared scrolling changes required by these screens.
|
||||
|
||||
### PR 1 excludes
|
||||
|
||||
- Recipe catalog or recipe picker.
|
||||
- Composer API or UI.
|
||||
- Lifecycle fields on automation definitions.
|
||||
- Trigger reconciliation in definition CRUD.
|
||||
- Usage counts.
|
||||
- Event-scoped recipes.
|
||||
|
||||
### PR 2 includes
|
||||
|
||||
- A dedicated composition contract and atomic global creation path.
|
||||
- Manual and recipe-driven composition using the same path.
|
||||
- Definition-only save as an explicit composer option.
|
||||
- Complete usage counts only if the aggregation spike meets the cost constraint.
|
||||
|
||||
### PR 2 excludes
|
||||
|
||||
- Event-scoped recipes or an event composer.
|
||||
- Persisted usage counters.
|
||||
- Trigger schema/title migration.
|
||||
- Editing shared definitions through trigger rows.
|
||||
- A general workflow engine.
|
||||
|
||||
## Verification gates
|
||||
|
||||
PR 1 must pass focused and full client/server automation tests, client/server type checks and lint, formatting, builds,
|
||||
diff hygiene, and the browser smoke check. PR 2 repeats those gates and adds tests for atomicity, duplicate lifecycle
|
||||
inputs, manual creation, recipe creation, failed-save retry, and any usage aggregation that ships.
|
||||
|
||||
Detailed progress is tracked in `tasks/automation-composer-todo.md`; the unrelated teleprompter plan in
|
||||
`tasks/todo.md` remains untouched.
|
||||
Reference in New Issue
Block a user