Skip to content

Commit 4b1bf66

Browse files
Add decision function UI: modal, PolicyForm integration, and stale ref fix
DecisionFunctionModal with CodeMirror editors (JS + JSON), autocomplete, templates, test panel, shared function warning, and optimistic concurrency. PolicyForm gains toggle-based decision function attachment (create/select/ edit/detach). Fixes stale reference dead-end where detaching a deleted function left no way to attach a new one.
1 parent af0e5ab commit 4b1bf66

12 files changed

Lines changed: 2253 additions & 429 deletions

admin-ui/CLAUDE.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Admin UI — React Frontend
22

33
## Key Versions
4-
React 19, Vite 6, Tailwind 4, TanStack Query 5, react-router-dom 7, Vitest 3, @testing-library/react 16
4+
React 19, Vite 7, Tailwind 4, TanStack Query 5, react-router-dom 7, Vitest 4, @testing-library/react 16, CodeMirror 6 (`@uiw/react-codemirror`)
55

66
## Key Files
77
- `vite.config.ts` — proxies `/api``http://localhost:5435`
@@ -17,16 +17,18 @@ React 19, Vite 6, Tailwind 4, TanStack Query 5, react-router-dom 7, Vitest 3, @t
1717
- `src/components/AuditTimeline.tsx` — Reusable admin audit timeline (used on role/user/policy/datasource detail pages)
1818
- `src/utils/auditBadge.ts` — Shared `actionBadgeClass()` for audit action badge styling (used by AuditTimeline + AdminAuditPage)
1919
- `src/components/PolicyAssignmentPanel.tsx` — Three components: `PolicyAssignmentsReadonly`, `PolicyAssignmentEditPanel` (with scope selector: all/user/role), `DatasourceAssignmentsReadonly`
20+
- `src/components/DecisionFunctionModal.tsx` — Modal for creating/editing decision functions with CodeMirror 6 editors (JS + JSON). Features: `ctx.*`/`config.*` autocomplete (activates on dot), templates (create mode), test panel with client-side pre-check → server WASM test, fire/skip/error badges, shared function warning, optimistic concurrency. Three linters: JS linter (executes function against mock context for syntax + runtime errors, highlights exact error line), JSON linter on config + test context editors (validates JSON.parse, highlights error position).
21+
- `src/components/PolicyForm.tsx` — Policy create/edit form with funnel-framed sections (Policy → Effect → Targets → Decision Function), toggle-based decision function attachment (create new / select existing / edit / detach)
2022
- `src/pages/RolesListPage.tsx` — Paginated list with search, member counts, active/inactive badges
2123
- `src/pages/RoleCreatePage.tsx` — Create form
2224
- `src/pages/RoleEditPage.tsx` — Tabbed view (Details, Members, Inheritance, Data Sources, Policies, Activity)
2325
- `src/pages/AdminAuditPage.tsx` — Centralized admin audit log with filters (resource type, actor, date range)
2426
- `src/types/policy.ts` — TypeScript interfaces for policies, assignments (`PolicyType`, `AssignmentScope`, `TargetEntry`)
2527
- `src/types/role.ts` — TypeScript interfaces for roles, members, audit entries
26-
- `src/types/decisionFunction.ts` — TypeScript interfaces for decision functions (`DecisionFunction`, `DecisionFunctionCreate`, `DecisionFunctionUpdate`)
27-
- `src/api/decisionFunctions.ts` — API client functions for decision function CRUD (`listDecisionFunctions`, `getDecisionFunction`, `createDecisionFunction`, `updateDecisionFunction`, `deleteDecisionFunction`)
28+
- `src/types/decisionFunction.ts` — TypeScript interfaces (`DecisionFunctionResponse`, `DecisionFunctionSummary`, `CreateDecisionFunctionPayload`, `UpdateDecisionFunctionPayload`, `TestDecisionFnPayload`, `TestDecisionFnResponse`, `EvaluateContext`, `OnErrorBehavior`, `LogLevel`)
29+
- `src/api/decisionFunctions.ts` — API client: `listDecisionFunctions`, `getDecisionFunction`, `createDecisionFunction`, `updateDecisionFunction`, `deleteDecisionFunction`, `testDecisionFn`
2830
- `src/test/test-utils.tsx``renderWithProviders` (QueryClient + AuthProvider + MemoryRouter)
29-
- `src/test/factories.ts``makeUser`, `makeDataSource`, `makeDataSourceType`, `makeDiscoveredSchema/Table/Column`
31+
- `src/test/factories.ts``makeUser`, `makeDataSource`, `makeDataSourceType`, `makeDiscoveredSchema/Table/Column`, `makeDecisionFunction`, `makePolicy`, `makePolicyAssignment`
3032

3133
## Running Tests
3234
```bash
@@ -70,6 +72,17 @@ Components use `<label>Text</label><input />` as siblings, not linked pairs. Use
7072
### CSS `uppercase` is visual-only
7173
`className="uppercase"` does not change DOM `textContent`. Search for lowercase `'public'`, not `'PUBLIC'`.
7274

75+
### CodeMirror 6 in tests
76+
CodeMirror 6 uses DOM APIs (Selection, Range) that jsdom doesn't support. Mock `@uiw/react-codemirror` as a simple textarea in tests:
77+
```tsx
78+
vi.mock('@uiw/react-codemirror', () => ({
79+
default: ({ value, onChange, placeholder }: { value: string; onChange?: (v: string) => void; placeholder?: string }) => (
80+
<textarea data-testid="codemirror" value={value} onChange={(e) => onChange?.(e.target.value)} placeholder={placeholder} />
81+
),
82+
}))
83+
```
84+
Use `fireEvent.change(editor, { target: { value: '...' } })` instead of `userEvent.type` for CodeMirror textareas — `userEvent.type` interprets `{` as keyboard modifier syntax.
85+
7386
### Text split by HTML tags
7487
Rich text like `<strong>1</strong> schema` cannot be matched by `getByText(/1.*schema/i)`. Use:
7588
```ts

admin-ui/package-lock.json

Lines changed: 263 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

admin-ui/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@
1212
"typecheck": "tsc -b"
1313
},
1414
"dependencies": {
15+
"@codemirror/autocomplete": "^6.20.1",
16+
"@codemirror/lang-javascript": "^6.2.5",
17+
"@codemirror/lang-json": "^6.0.2",
18+
"@codemirror/lint": "^6.9.5",
1519
"@microsoft/fetch-event-source": "^2.0.1",
1620
"@tanstack/react-query": "^5.66.0",
21+
"@uiw/react-codemirror": "^4.25.9",
1722
"axios": "^1.7.9",
1823
"react": "^19.0.0",
1924
"react-dom": "^19.0.0",

0 commit comments

Comments
 (0)