From b9697cc8b11bce806887d6e7a29098a308b0846a Mon Sep 17 00:00:00 2001 From: Victor Wiebe Date: Sat, 18 Jul 2026 12:08:17 -0400 Subject: [PATCH] Complete Slice 1 MVP GUI components --- BASELINE.md | 15 +- CODEX.md | 39 +++--- SLICE1.md | 55 ++++---- TASKS.md | 12 +- .../valid-mvp-components.json | 51 +++++++ frontend/src/components/Preview/Preview.tsx | 1 + .../Preview/PreviewComponent.module.css | 11 ++ .../components/Preview/PreviewComponent.tsx | 131 +++++++++++++++++- .../components/Preview/bindingUtils.test.ts | 10 ++ .../src/components/Preview/bindingUtils.ts | 13 +- .../components/Preview/mvpComponents.test.tsx | 67 +++++++++ .../components/Preview/usePreviewRuntime.ts | 20 ++- .../Canvas/CanvasComponent.module.css | 11 ++ .../VisualEditor/Canvas/CanvasComponent.tsx | 76 +++++++++- .../VisualEditor/Palette/Palette.tsx | 5 + .../components/VisualEditor/VisualEditor.tsx | 62 ++++++++- frontend/src/store/useProjectStore.ts | 25 +++- frontend/src/types/project.ts | 16 +-- 18 files changed, 547 insertions(+), 73 deletions(-) create mode 100644 examples/project-definitions/valid-mvp-components.json create mode 100644 frontend/src/components/Preview/mvpComponents.test.tsx diff --git a/BASELINE.md b/BASELINE.md index 513bdf7..c884bb9 100644 --- a/BASELINE.md +++ b/BASELINE.md @@ -32,8 +32,8 @@ npx --yes --package=node@20 --package=npm@10 npm test -- --watchAll=false --runI Result: Passed. -- Test suites: 6 passed, 6 total -- Tests: 420 passed, 420 total +- Test suites: 7 passed, 7 total +- Tests: 433 passed, 433 total - Snapshots: 0 ### Frontend production build @@ -58,7 +58,7 @@ Result: Passed. ## Schema Matrix -Eleven `valid-*.json` project definitions passed validation against `shared/schemas/conductor-project.schema.json`. +Twelve `valid-*.json` project definitions pass validation against `shared/schemas/conductor-project.schema.json`, including the Slice 1 all-components fixture. Two schema-invalid fixtures failed validation as expected: @@ -69,6 +69,15 @@ Two diagnostic-invalid fixtures passed structural schema validation as designed - `invalid-template-malformed.json` - `invalid-template-missing-component.json` +## Slice 1 Manual Acceptance + +User validation completed successfully on 2026-07-18: + +- All five new components can be configured and manipulated in the Visual Editor. +- Preview interaction, disabled and hidden behavior, and Status Panel tones work as expected. +- Visual Editor and JSON Editor synchronization works. +- Save/load persistence and existing-component regression checks pass. + ## Runtime Startup diff --git a/CODEX.md b/CODEX.md index e2ac0d9..14830cc 100644 --- a/CODEX.md +++ b/CODEX.md @@ -65,22 +65,19 @@ Some root-level documentation duplicates files under `docs/`. The `docs/` copies ### Active GUI components -The following components are available in the palette and have canvas, property-editor, and Preview support: +All eleven schema-supported MVP components are available in the palette and have canvas, property-editor, and Preview support: - Label - Button - Text Input - Dropdown - Table -- JSON Viewer - -The following MVP component types are accepted by the schema but are not active in the Visual Editor or Preview: - - Text Area - Checkbox - Radio Group - Status/Message Panel -- Container/Card +- Container/Card (flat presentational title and body; nesting deferred) +- JSON Viewer ### REST and Preview runtime @@ -106,7 +103,6 @@ The following MVP component types are accepted by the schema but are not active - Sanitized execution history and troubleshooting views are not implemented. - Visual REST action, event, and binding configuration workflows are incomplete; advanced configuration still relies on JSON editing. - Project documents are validated in the JSON Editor, but save operations still need an unconditional validation gate. -- The schema accepts five component types that the editor and runtime cannot render. - Backend and end-to-end automated test coverage remains incomplete. - IBM Bob/watsonx will not be used; AI is provider-neutral and post-MVP. - All five modeled authentication modes are required for MVP. @@ -121,23 +117,23 @@ The initial repository push was completed on 2026-07-18. - The working tree was clean immediately after the push. - All `:Zone.Identifier` sidecar files were removed before the initial commit. - Node 20/npm 10 clean installs pass after repairing the frontend lockfile. -- Frontend validation passes: 6 suites and 420 tests, plus the production build. +- Frontend validation passes: 7 suites and 433 tests, plus the production build. - Backend build and the schema fixture matrix pass. - Docker Compose builds and starts both services. - Health, CRUD, cleanup, and restart persistence pass. - See `BASELINE.md` for exact evidence and remaining release work. +- Manual Slice 1 acceptance passes for component configuration, Preview interaction, JSON synchronization, save/load persistence, and existing-component regressions. ## Immediate Priorities Unless the user chooses a different priority, proceed in this order: -1. Implement the five missing MVP GUI components individually, with tests. -2. Add visual REST action, event, and binding configuration. -3. Add validation to every project save path. -4. Implement authentication and secure secret handling. -5. Harden the REST proxy and add sanitized execution logging. -6. Add backend, end-to-end, and security regression tests. -7. Reconcile and consolidate project documentation. +1. Add visual REST action, event, and binding configuration. +2. Add validation to every project save path. +3. Implement authentication and secure secret handling. +4. Harden the REST proxy and add sanitized execution logging. +5. Add backend, end-to-end, and security regression tests. +6. Reconcile and consolidate project documentation. See `TASKS.md` for the complete actionable checklist. @@ -178,9 +174,10 @@ After material work: Date: 2026-07-18 -- Reviewed the documentation and current source implementation. -- Created `TASKS.md` with completed work and remaining MVP tasks. -- Removed 99 Windows `:Zone.Identifier` sidecar files. -- Initialized the fork as a new Git repository and pushed `main` to Gitea. -- Created this cross-session state file. -- Next recommended action: install dependencies and establish a clean validation baseline before implementing the next MVP feature. +- Completed Slice 1 by implementing Text Area, Checkbox, Radio Group, Status Panel, and Container/Card across the palette, canvas, property editor, and Preview. +- Added runtime value and response-binding support while keeping ephemeral values out of canonical JSON. +- Scoped Container/Card to a flat presentational title/body contract for MVP; nesting remains post-MVP. +- Added `valid-mvp-components.json` and focused renderer/binding tests. +- Validation passes: 7 frontend suites / 433 tests, frontend production build, backend TypeScript build, and the new schema fixture. +- User completed the full manual Slice 1 checklist successfully. +- Next recommended action: begin `SLICE2.md`. diff --git a/SLICE1.md b/SLICE1.md index 96b7026..16b9f45 100644 --- a/SLICE1.md +++ b/SLICE1.md @@ -2,7 +2,7 @@ ## Status -Not started +Complete ## Objective @@ -25,31 +25,31 @@ Implement every GUI component required by the MVP so each schema-supported compo ## Tasks -- [ ] Define shared acceptance criteria and test patterns for component implementation. -- [ ] Implement Text Area end-to-end. -- [ ] Implement Checkbox end-to-end. -- [ ] Implement Radio Group end-to-end. -- [ ] Implement Status/Message Panel end-to-end. -- [ ] Define and implement the minimum MVP Container/Card behavior and nesting rules. -- [ ] Add component-specific binding support and diagnostics. -- [ ] Add or update example projects for all five components. -- [ ] Remove the schema/runtime mismatch for supported component types. -- [ ] Update `TASKS.md`, `CODEX.md`, and relevant documentation. +- [x] Define shared acceptance criteria and test patterns for component implementation. +- [x] Implement Text Area end-to-end. +- [x] Implement Checkbox end-to-end. +- [x] Implement Radio Group end-to-end. +- [x] Implement Status/Message Panel end-to-end. +- [x] Define and implement the minimum MVP Container/Card behavior and nesting rules. +- [x] Add component-specific binding support and diagnostics. +- [x] Add or update example projects for all five components. +- [x] Remove the schema/runtime mismatch for supported component types. +- [x] Update `TASKS.md`, `CODEX.md`, and relevant documentation. ## Acceptance Criteria -- [ ] All eleven MVP types can be added through the palette and render on the canvas and in Preview. -- [ ] Properties survive JSON editing and save/load round trips. -- [ ] Interactive values remain in runtime state, not canonical JSON. -- [ ] Invalid configurations produce useful diagnostics. -- [ ] Existing components and bindings continue to work. +- [x] All eleven MVP types can be added through the palette and render on the canvas and in Preview. +- [x] Properties use the canonical document and therefore survive JSON editing and persistence round trips. +- [x] Interactive values remain in runtime state, not canonical JSON. +- [x] Invalid option and binding configurations produce useful diagnostics. +- [x] Existing components and bindings continue to work. ## Validation -- [ ] Frontend TypeScript check and production build pass. -- [ ] Component and renderer tests pass. -- [ ] Schema examples validate as expected. -- [ ] Manual canvas, Preview, and save/load checks pass for each component. +- [x] Frontend TypeScript check and production build pass. +- [x] Component and renderer tests pass. +- [x] Schema examples validate as expected. +- [x] Manual canvas, Preview, JSON synchronization, save/load, and regression checks pass for all components. ## Risks and Open Questions @@ -59,10 +59,17 @@ Implement every GUI component required by the MVP so each schema-supported compo ## Progress Log -No work recorded yet. +- Added Text Area, Checkbox, Radio Group, Status Panel, and Container/Card to the shared type model, palette, canvas, defaults, property editor, and Preview. +- Kept all interactive input values in ephemeral Preview runtime state. +- Added response-mapped `.value` support for Text Area, Checkbox, Radio Group, and Status Panel. +- Defined Container/Card as a flat presentational card with title and body; nested component ownership is deferred beyond MVP. +- Added a representative schema fixture covering all five components. +- Added focused renderer and binding regression tests. +- Validation passed: 7 suites / 433 tests, frontend production build, backend TypeScript build, and the new schema fixture. +- User manual acceptance passed: startup, all five new component controls, Preview behavior, JSON synchronization, save/load persistence, and existing-component regression checks. ## Handoff -- Last completed: Slice plan created. -- Next action: Define component contracts and implement Text Area as the reference pattern. -- Known blockers: Container/Card nesting behavior requires a scoped decision. +- Last completed: All Slice 1 GUI components and validation. +- Next action: Begin Slice 2 visual REST action, event, and binding configuration. +- Known blockers: None for Slice 1. diff --git a/TASKS.md b/TASKS.md index be2467f..3970786 100644 --- a/TASKS.md +++ b/TASKS.md @@ -61,12 +61,12 @@ This document summarizes the current implementation and the remaining work requi ### Missing MVP GUI components -- [ ] Implement the Text Area component in the palette, canvas, property editor, Preview runtime, and tests. -- [ ] Implement the Checkbox component in the palette, canvas, property editor, Preview runtime, and tests. -- [ ] Implement the Radio Group component in the palette, canvas, property editor, Preview runtime, and tests. -- [ ] Implement the Status/Message Panel component in the palette, canvas, property editor, Preview runtime, response bindings, and tests. -- [ ] Implement the Container/Card component in the palette, canvas, property editor, Preview runtime, and tests. -- [ ] Add a clear validation diagnostic until every schema-supported component type is supported by both the Visual Editor and Preview runtime. +- [x] Implement the Text Area component in the palette, canvas, property editor, Preview runtime, and tests. +- [x] Implement the Checkbox component in the palette, canvas, property editor, Preview runtime, and tests. +- [x] Implement the Radio Group component in the palette, canvas, property editor, Preview runtime, and tests. +- [x] Implement the Status/Message Panel component in the palette, canvas, property editor, Preview runtime, response bindings, and tests. +- [x] Implement the Container/Card component in the palette, canvas, property editor, Preview runtime, and tests. +- [x] Remove the schema/runtime component-type mismatch; all eleven schema-supported types now render in the editor and Preview. ### Visual configuration workflows diff --git a/examples/project-definitions/valid-mvp-components.json b/examples/project-definitions/valid-mvp-components.json new file mode 100644 index 0000000..e3a93a0 --- /dev/null +++ b/examples/project-definitions/valid-mvp-components.json @@ -0,0 +1,51 @@ +{ + "$schema": "../../shared/schemas/conductor-project.schema.json", + "schemaVersion": "0.1.0", + "project": { + "id": "proj_mvp_components", + "name": "MVP Components", + "description": "Representative configuration for the five Slice 1 components.", + "pages": [{ + "id": "page_main", + "name": "Main", + "order": 0, + "components": [ + { + "id": "notes", "type": "TextArea", "name": "notes", + "position": { "x": 24, "y": 24 }, "size": { "width": 320, "height": 120 }, + "properties": { "label": "Notes", "placeholder": "Enter notes", "defaultValue": "", "required": true, "visible": true, "disabled": false }, + "events": [] + }, + { + "id": "enabled", "type": "Checkbox", "name": "enabled", + "position": { "x": 24, "y": 168 }, "size": { "width": 220, "height": 40 }, + "properties": { "label": "Enabled", "defaultValue": true, "visible": true, "disabled": false }, + "events": [] + }, + { + "id": "region", "type": "RadioGroup", "name": "region", + "position": { "x": 24, "y": 232 }, "size": { "width": 280, "height": 120 }, + "properties": { "label": "Region", "options": [{ "label": "East", "value": "east" }, { "label": "West", "value": "west" }], "value": "east", "visible": true, "disabled": false }, + "events": [] + }, + { + "id": "status", "type": "StatusPanel", "name": "status", + "position": { "x": 376, "y": 24 }, "size": { "width": 360, "height": 96 }, + "properties": { "label": "Status", "defaultValue": "Ready", "status": "success", "visible": true, "disabled": false }, + "events": [] + }, + { + "id": "summary", "type": "Container", "name": "summary", + "position": { "x": 376, "y": 144 }, "size": { "width": 400, "height": 220 }, + "properties": { "label": "Summary", "defaultValue": "Card content", "visible": true, "disabled": false }, + "events": [] + } + ], + "events": [] + }], + "actions": [], + "bindings": [], + "variables": {}, + "settings": {} + } +} diff --git a/frontend/src/components/Preview/Preview.tsx b/frontend/src/components/Preview/Preview.tsx index df2fd2a..e12f096 100644 --- a/frontend/src/components/Preview/Preview.tsx +++ b/frontend/src/components/Preview/Preview.tsx @@ -86,6 +86,7 @@ function Preview(): React.ReactElement { onTextInputChange={runtime.handleTextInputChange} onDropdownChange={runtime.handleDropdownChange} onTableRowSelect={runtime.handleTableRowSelect} + onValueChange={runtime.handleValueChange} /> ))} diff --git a/frontend/src/components/Preview/PreviewComponent.module.css b/frontend/src/components/Preview/PreviewComponent.module.css index 3e530f5..3b4d619 100644 --- a/frontend/src/components/Preview/PreviewComponent.module.css +++ b/frontend/src/components/Preview/PreviewComponent.module.css @@ -324,6 +324,17 @@ border-right: 1px solid #f0f0f0; } +.textArea { width: 100%; min-height: 84px; box-sizing: border-box; resize: vertical; } +.choiceRow { display: flex; align-items: center; gap: 8px; width: 100%; font-size: 13px; } +.radioGroup { display: flex; flex-direction: column; gap: 6px; width: 100%; margin: 0; padding: 0; border: 0; } +.radioGroup legend { margin-bottom: 6px; font-size: 12px; font-weight: 600; } +.statusPanel { width: 100%; height: 100%; box-sizing: border-box; padding: 12px; border: 1px solid #93c5fd; border-radius: 6px; background: #eff6ff; color: #1e3a8a; overflow: auto; } +.statusPanel[data-status='success'] { background: #ecfdf5; border-color: #6ee7b7; color: #065f46; } +.statusPanel[data-status='warning'] { background: #fffbeb; border-color: #fcd34d; color: #92400e; } +.statusPanel[data-status='error'] { background: #fef2f2; border-color: #fca5a5; color: #991b1b; } +.card { width: 100%; height: 100%; box-sizing: border-box; padding: 16px; border: 1px solid #d0d7de; border-radius: 8px; background: #fff; box-shadow: 0 1px 3px rgba(31, 35, 40, 0.12); overflow: auto; } +.cardTitle { margin-bottom: 8px; font-weight: 600; } +.cardBody { color: #57606a; white-space: pre-wrap; } .tableTd:last-child { border-right: none; } diff --git a/frontend/src/components/Preview/PreviewComponent.tsx b/frontend/src/components/Preview/PreviewComponent.tsx index fd4c42d..4c638c8 100644 --- a/frontend/src/components/Preview/PreviewComponent.tsx +++ b/frontend/src/components/Preview/PreviewComponent.tsx @@ -81,6 +81,87 @@ function TextInputRenderer({ ); } +function TextAreaRenderer({ label, placeholder, value, disabled, onChange }: { + label: string; + placeholder: string; + value: string; + disabled: boolean; + onChange: (value: string) => void; +}): React.ReactElement { + return ( +
+ {label && } +