spine-framework 0.4.3 → 0.5.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +13 -3
- package/.framework/cli/commands/bootstrap.ts +392 -0
- package/.framework/cli/commands/dev.ts +91 -218
- package/.framework/cli/commands/doctor.ts +132 -26
- package/.framework/cli/commands/generate.ts +38 -298
- package/.framework/cli/commands/init.ts +20 -1
- package/.framework/cli/commands/migrate.ts +36 -30
- package/.framework/cli/commands/migrations.ts +16 -56
- package/.framework/cli/commands/upgrade.ts +35 -0
- package/.framework/cli/commands/validate-schema.ts +147 -0
- package/.framework/cli/context.ts +223 -110
- package/.framework/cli/index.ts +6 -0
- package/.framework/cli/lib/project-files.ts +241 -1
- package/.framework/functions/_shared/agent-runner.ts +1000 -81
- package/.framework/functions/_shared/cil.ts +2 -1
- package/.framework/functions/_shared/db.ts +3 -6
- package/.framework/functions/_shared/hash-api-key.ts +183 -79
- package/.framework/functions/_shared/kb.ts +61 -7
- package/.framework/functions/_shared/logging.ts +562 -224
- package/.framework/functions/_shared/message-sequence.ts +53 -0
- package/.framework/functions/_shared/middleware.ts +47 -44
- package/.framework/functions/_shared/pipeline-runner.ts +150 -37
- package/.framework/functions/_shared/principal.ts +9 -6
- package/.framework/functions/_shared/trigger-engine.ts +149 -40
- package/.framework/functions/admin-data.ts +48 -31
- package/.framework/functions/ai-agents.ts +103 -33
- package/.framework/functions/api-keys.ts +301 -122
- package/.framework/functions/apps.ts +43 -26
- package/.framework/functions/cil-ingest.ts +48 -15
- package/.framework/functions/debug-auth.ts +14 -8
- package/.framework/functions/deliveries.ts +39 -12
- package/.framework/functions/embeddings.ts +145 -76
- package/.framework/functions/integration-outbound.ts +67 -27
- package/.framework/functions/integrations.ts +254 -127
- package/.framework/functions/logs.ts +273 -133
- package/.framework/functions/observability.ts +277 -147
- package/.framework/functions/pipeline-executions.ts +1 -1
- package/.framework/functions/pipeline-runner-background.ts +120 -0
- package/.framework/functions/pipelines.ts +14 -9
- package/.framework/functions/prompt-configs.ts +7 -4
- package/.framework/functions/roles.ts +8 -5
- package/.framework/functions/security.ts +30 -17
- package/.framework/functions/system-cron.ts +250 -128
- package/.framework/functions/tests.ts +7 -6
- package/.framework/functions/timers.ts +310 -107
- package/.framework/functions/trigger-scheduler.ts +65 -5
- package/.framework/functions/triggers.ts +28 -13
- package/.framework/functions/types.ts +13 -10
- package/.framework/migrations/064_episode_leases.sql +196 -0
- package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
- package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
- package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
- package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
- package/.framework/migrations/069_log_stats_window.sql +54 -0
- package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
- package/.framework/migrations/071_timer_interval_keys.sql +96 -0
- package/.framework/migrations/072_slug_autofill.sql +77 -0
- package/.framework/migrations/073_seed_member_roles.sql +26 -0
- package/.framework/schemas/spine.config.schema.json +62 -0
- package/.framework/src/App.tsx +3 -1
- package/.framework/src/apps/admin/index.tsx +1141 -775
- package/.framework/src/components/ErrorBoundary.tsx +136 -0
- package/.framework/src/components/admin/AdminListPage.tsx +81 -73
- package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
- package/.framework/src/components/admin/EntitySelect.tsx +181 -0
- package/.framework/src/components/admin/PageInstructions.tsx +86 -127
- package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
- package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
- package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
- package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
- package/.framework/src/components/layout/Layout.tsx +4 -2
- package/.framework/src/components/layout/Sidebar.tsx +304 -179
- package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
- package/.framework/src/components/runtime/DataHeader.tsx +96 -48
- package/.framework/src/components/runtime/DataListPage.tsx +3 -26
- package/.framework/src/components/runtime/DataStats.tsx +10 -10
- package/.framework/src/components/runtime/DataTable.tsx +12 -10
- package/.framework/src/components/ui/sheet.tsx +24 -26
- package/.framework/src/components/ui/textarea.tsx +74 -48
- package/.framework/src/hooks/useBranding.ts +47 -0
- package/.framework/src/hooks/useEntityList.ts +12 -9
- package/.framework/src/hooks/useListSchema.ts +108 -58
- package/.framework/src/instructions/README.md +57 -0
- package/.framework/src/instructions/ai-agents.md +69 -0
- package/.framework/src/instructions/alerts.md +80 -0
- package/.framework/src/instructions/api-keys.md +87 -0
- package/.framework/src/instructions/apps.md +77 -0
- package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
- package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
- package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
- package/.framework/src/instructions/concepts/automation.md +186 -0
- package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
- package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
- package/.framework/src/instructions/concepts/design-schema.md +152 -0
- package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
- package/.framework/src/instructions/concepts/observability.md +116 -0
- package/.framework/src/instructions/concepts/permissions.md +150 -0
- package/.framework/src/instructions/concepts/runtime-records.md +111 -0
- package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
- package/.framework/src/instructions/concepts/spine-way.md +172 -0
- package/.framework/src/instructions/deliveries.md +59 -0
- package/.framework/src/instructions/guide/00-orientation.md +106 -0
- package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
- package/.framework/src/instructions/guide/02-project-map.md +147 -0
- package/.framework/src/instructions/guide/03-domain-model.md +223 -0
- package/.framework/src/instructions/guide/04-first-app.md +227 -0
- package/.framework/src/instructions/guide/05-glossary.md +183 -0
- package/.framework/src/instructions/integrations.md +96 -0
- package/.framework/src/instructions/internal/cil-markers.md +83 -0
- package/.framework/src/instructions/invites.md +60 -0
- package/.framework/src/instructions/kb.md +80 -0
- package/.framework/src/instructions/logs.md +77 -0
- package/.framework/src/instructions/observability.md +61 -0
- package/.framework/src/instructions/operations/deployment.md +115 -0
- package/.framework/src/instructions/operations/migrations.md +125 -0
- package/.framework/src/instructions/operations/security-checklist.md +148 -0
- package/.framework/src/instructions/operations/troubleshooting.md +170 -0
- package/.framework/src/instructions/operations/upgrade.md +116 -0
- package/.framework/src/instructions/pipeline-executions.md +62 -0
- package/.framework/src/instructions/pipelines.md +78 -0
- package/.framework/src/instructions/prompts.md +95 -0
- package/.framework/src/instructions/reference/api/admin-data.md +162 -0
- package/.framework/src/instructions/reference/api/auth.md +113 -0
- package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
- package/.framework/src/instructions/reference/app-manifest.md +150 -0
- package/.framework/src/instructions/reference/cli.md +124 -0
- package/.framework/src/instructions/reference/database.md +132 -0
- package/.framework/src/instructions/reference/design-schema.md +280 -0
- package/.framework/src/instructions/reference/env-vars.md +133 -0
- package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
- package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
- package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
- package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
- package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
- package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
- package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
- package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
- package/.framework/src/instructions/reference/functions/apps.md +140 -0
- package/.framework/src/instructions/reference/functions/auth.md +99 -0
- package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
- package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
- package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
- package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
- package/.framework/src/instructions/reference/functions/index.md +103 -0
- package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
- package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
- package/.framework/src/instructions/reference/functions/integrations.md +130 -0
- package/.framework/src/instructions/reference/functions/invites.md +182 -0
- package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
- package/.framework/src/instructions/reference/functions/kb.md +166 -0
- package/.framework/src/instructions/reference/functions/logs.md +141 -0
- package/.framework/src/instructions/reference/functions/observability.md +105 -0
- package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
- package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
- package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
- package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
- package/.framework/src/instructions/reference/functions/roles.md +121 -0
- package/.framework/src/instructions/reference/functions/security.md +140 -0
- package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
- package/.framework/src/instructions/reference/functions/system.md +106 -0
- package/.framework/src/instructions/reference/functions/tests.md +97 -0
- package/.framework/src/instructions/reference/functions/timers.md +117 -0
- package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
- package/.framework/src/instructions/reference/functions/triggers.md +140 -0
- package/.framework/src/instructions/reference/functions/types.md +146 -0
- package/.framework/src/instructions/reference/seeds.md +126 -0
- package/.framework/src/instructions/reference/shared-modules.md +127 -0
- package/.framework/src/instructions/reference/spine-config.md +114 -0
- package/.framework/src/instructions/roles.md +80 -0
- package/.framework/src/instructions/runtime-detail.md +70 -0
- package/.framework/src/instructions/runtime-list.md +77 -0
- package/.framework/src/instructions/security.md +67 -0
- package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
- package/.framework/src/instructions/tasks/add-a-role.md +96 -0
- package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
- package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
- package/.framework/src/instructions/tasks/add-a-type.md +151 -0
- package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
- package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
- package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
- package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
- package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
- package/.framework/src/instructions/tasks/test-your-code.md +108 -0
- package/.framework/src/instructions/tasks/write-a-function.md +132 -0
- package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
- package/.framework/src/instructions/testing.md +59 -0
- package/.framework/src/instructions/timers.md +82 -0
- package/.framework/src/instructions/triggers.md +69 -0
- package/.framework/src/instructions/types.md +93 -0
- package/.framework/src/lib/branding.ts +128 -0
- package/.framework/src/pages/NoAppPage.tsx +3 -1
- package/.framework/src/pages/NotFoundPage.tsx +62 -31
- package/.framework/src/pages/SetupPage.tsx +5 -2
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
- package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
- package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
- package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
- package/.framework/src/pages/admin/AppsPage.tsx +104 -66
- package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
- package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
- package/.framework/src/pages/admin/LogsPage.tsx +144 -76
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
- package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
- package/.framework/src/pages/admin/RolesPage.tsx +86 -43
- package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
- package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
- package/.framework/src/pages/admin/TimersPage.tsx +90 -62
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
- package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
- package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
- package/.framework/src/pages/admin/TypesPage.tsx +90 -48
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
- package/.framework/src/pages/auth/LoginPage.tsx +4 -2
- package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
- package/.framework/templates/agent/AGENTS.md +150 -0
- package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
- package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
- package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
- package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
- package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
- package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
- package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
- package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
- package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
- package/.framework/templates/project.json +5 -1
- package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
- package/.framework/tests/unit/agent-files.test.ts +355 -0
- package/.framework/tests/unit/agent-runner.test.ts +496 -47
- package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
- package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
- package/.framework/tests/unit/bootstrap.test.ts +242 -0
- package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
- package/.framework/tests/unit/debug-auth.test.ts +38 -0
- package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
- package/.framework/tests/unit/episode-lease.test.ts +695 -0
- package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
- package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
- package/.framework/tests/unit/logging-app-id.test.ts +75 -0
- package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
- package/.framework/tests/unit/principal-cache.test.ts +15 -0
- package/.framework/tests/unit/system-context-denial.test.ts +145 -0
- package/.framework/tests/unit/system-cron.test.ts +240 -0
- package/.framework/tests/unit/timers.test.ts +159 -0
- package/.framework/tests/unit/trigger-engine.test.ts +278 -91
- package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
- package/README.md +125 -166
- package/config/tsconfig.cli.json +2 -2
- package/netlify.toml +5 -0
- package/package.json +15 -4
- package/templates/project/package-lock.json +2 -2
- package/.framework/docs/admin-routes.md +0 -76
- package/.framework/docs/api-docs-progress.md +0 -38
- package/.framework/docs/api-governance.md +0 -146
- package/.framework/docs/api-testing-results.md +0 -212
- package/.framework/docs/assembly-launch-guide.md +0 -138
- package/.framework/docs/audit-results.md +0 -590
- package/.framework/docs/db-api-inventory.md +0 -95
- package/.framework/docs/gap-remediation-backlog.md +0 -103
- package/.framework/docs/ui-adoption-verification.md +0 -111
- package/.framework/docs/ui-api-coverage.md +0 -84
- package/.framework/docs/v2-compatibility-audit.md +0 -228
- package/.framework/mcp/index.ts +0 -133
- package/.framework/mcp/load-env.ts +0 -60
- package/.framework/mcp/shared/app-manifest.ts +0 -275
- package/.framework/mcp/shared/db.ts +0 -477
- package/.framework/mcp/shared/kb.ts +0 -118
- package/.framework/mcp/tools/architect.ts +0 -431
- package/.framework/mcp/tools/cil/context.ts +0 -345
- package/.framework/mcp/tools/cil/graph.ts +0 -242
- package/.framework/mcp/tools/cil/ingest.ts +0 -1217
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
- package/.framework/mcp/tools/cil/pipeline.ts +0 -767
- package/.framework/mcp/tools/cil/project.ts +0 -791
- package/.framework/mcp/tools/cil/retrieval.ts +0 -336
- package/.framework/mcp/tools/cil/search-core.ts +0 -454
- package/.framework/mcp/tools/cil/search.ts +0 -97
- package/.framework/mcp/tools/cil/suggest.ts +0 -186
- package/.framework/mcp/tools/cil/validate.ts +0 -1369
- package/.framework/mcp/tools/kb/delete.ts +0 -139
- package/.framework/mcp/tools/kb/index.ts +0 -52
- package/.framework/mcp/tools/kb/ingest.ts +0 -84
- package/.framework/mcp/tools/kb/list-types.ts +0 -102
- package/.framework/mcp/tools/kb/publish.ts +0 -100
- package/.framework/mcp/tools/kb/reindex.ts +0 -86
- package/.framework/mcp/tools/kb/revoke.ts +0 -85
- package/.framework/mcp/tools/kb/search.ts +0 -101
- package/.framework/mcp/tools/kb/upsert.ts +0 -125
- package/.framework/mcp/tools/observability.ts +0 -510
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
2
|
+
/**
|
|
3
|
+
* @module EntitySelect
|
|
4
|
+
* @audience both
|
|
5
|
+
* @layer shared-core
|
|
6
|
+
* @stability stable
|
|
7
|
+
*
|
|
8
|
+
* This module provides a React component for selecting entities within the admin interface, leveraging a native select dropdown. It fetches data from an API to populate the selection options, ensuring that the component reflects the current state of available entities.
|
|
9
|
+
* INVARIANT: The component must always receive valid API response data to function correctly.
|
|
10
|
+
*
|
|
11
|
+
* @seeAlso native-select (provides the UI component for selection).
|
|
12
|
+
* @seeAlso api (handles the data fetching required for populating the select options).
|
|
13
|
+
*
|
|
14
|
+
* @cil-generated
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import React, { useEffect, useState } from 'react'
|
|
18
|
+
import { NativeSelect } from '../ui/native-select'
|
|
19
|
+
import { apiFetch } from '../../lib/api'
|
|
20
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:module_header:module_header"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:Option:interface" type="interface" identity="Option" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
25
|
+
/**
|
|
26
|
+
* The Option interface defines the structure for an option item used in selection components. It provides a standardized way to represent selectable items with a value and a label.
|
|
27
|
+
*
|
|
28
|
+
* @sideEffects none
|
|
29
|
+
* @stability internal
|
|
30
|
+
* @cil-generated
|
|
31
|
+
*/
|
|
32
|
+
interface Option {
|
|
33
|
+
value: string
|
|
34
|
+
label: string
|
|
35
|
+
}
|
|
36
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:Option:interface"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelectProps:interface" type="interface" identity="EntitySelectProps" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
41
|
+
/**
|
|
42
|
+
* EntitySelectProps defines the properties required for the EntitySelect component, facilitating the selection of entities from a specified endpoint. It allows for customization of the selection behavior and appearance.
|
|
43
|
+
*
|
|
44
|
+
* @sideEffects none
|
|
45
|
+
* @stability internal
|
|
46
|
+
* @cil-generated
|
|
47
|
+
*/
|
|
48
|
+
interface EntitySelectProps {
|
|
49
|
+
endpoint: string
|
|
50
|
+
value: string
|
|
51
|
+
onChange: (value: string) => void
|
|
52
|
+
placeholder?: string
|
|
53
|
+
mapOption?: (row: any) => Option
|
|
54
|
+
className?: string
|
|
55
|
+
}
|
|
56
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelectProps:interface"]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:defaultMap:function" type="function" identity="defaultMap" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
61
|
+
/**
|
|
62
|
+
* The defaultMap function transforms a row object into an Option object, providing a standard way to represent entities with a value and label. This is useful for creating dropdowns or selection lists in the admin interface.
|
|
63
|
+
*
|
|
64
|
+
* @inputSpec
|
|
65
|
+
* row: any (required) — the row object containing entity data.
|
|
66
|
+
* @outputSpec Option — an object with 'value' and 'label' properties.
|
|
67
|
+
* @sideEffects none
|
|
68
|
+
* @stability internal
|
|
69
|
+
* @cil-generated
|
|
70
|
+
*/
|
|
71
|
+
const defaultMap = (row: any): Option => ({
|
|
72
|
+
value: row.id,
|
|
73
|
+
label: row.name || row.title || row.slug || row.id,
|
|
74
|
+
})
|
|
75
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:defaultMap:function"]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelect:component" type="component" identity="EntitySelect" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
80
|
+
/**
|
|
81
|
+
* EntitySelect is a component that allows users to select an entity from a dynamically fetched list of options. It handles API data retrieval and state management to provide a user-friendly interface for entity selection.
|
|
82
|
+
*
|
|
83
|
+
* @macro Dropdown component for selecting entities from an API-driven list.
|
|
84
|
+
* @micro Fetches options from a specified endpoint and maps them using a provided mapping function.
|
|
85
|
+
* @inputSpec
|
|
86
|
+
* endpoint: string (required) — the API endpoint to fetch options from.
|
|
87
|
+
* value: string (optional) — the currently selected value.
|
|
88
|
+
* onChange: function (required) — callback function to handle value changes.
|
|
89
|
+
* placeholder: string (optional) — placeholder text for the dropdown.
|
|
90
|
+
* mapOption: function (optional) — function to map API response items to dropdown options.
|
|
91
|
+
* className: string (optional) — additional CSS class names for styling.
|
|
92
|
+
* @outputSpec JSX.Element — renders a NativeSelect component with options.
|
|
93
|
+
* @sideEffects fetches data from an external API endpoint.
|
|
94
|
+
* @stability internal
|
|
95
|
+
* @calls apiFetch
|
|
96
|
+
* @errorHandling sets options to an empty array on fetch failure.
|
|
97
|
+
* @cil-generated
|
|
98
|
+
*/
|
|
99
|
+
export function EntitySelect({
|
|
100
|
+
endpoint,
|
|
101
|
+
value,
|
|
102
|
+
onChange,
|
|
103
|
+
placeholder = 'Select…',
|
|
104
|
+
mapOption = defaultMap,
|
|
105
|
+
className,
|
|
106
|
+
}: EntitySelectProps) {
|
|
107
|
+
const [options, setOptions] = useState<Option[]>([])
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
apiFetch(endpoint)
|
|
111
|
+
.then(r => r.json())
|
|
112
|
+
.then(data => {
|
|
113
|
+
const rows: any[] = data?.data || data?.items || data?.projects || data || []
|
|
114
|
+
setOptions(rows.map(mapOption))
|
|
115
|
+
})
|
|
116
|
+
.catch(() => setOptions([]))
|
|
117
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
118
|
+
}, [endpoint])
|
|
119
|
+
|
|
120
|
+
const known = options.some(o => o.value === value)
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<NativeSelect
|
|
124
|
+
value={value || ''}
|
|
125
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:EntitySelect:component"]
|
|
126
|
+
|
|
127
|
+
onChange={e => onChange(e.target.value)}
|
|
128
|
+
className={className}
|
|
129
|
+
>
|
|
130
|
+
<option value="">{placeholder}</option>
|
|
131
|
+
{value && !known && <option value={value}>{value}</option>}
|
|
132
|
+
{options.map(o => (
|
|
133
|
+
<option key={o.value} value={o.value}>
|
|
134
|
+
{o.label}
|
|
135
|
+
</option>
|
|
136
|
+
))}
|
|
137
|
+
</NativeSelect>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:AppSelect:component" type="component" identity="AppSelect" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
143
|
+
/**
|
|
144
|
+
* AppSelect is a specialized component for selecting applications in the admin interface, providing a predefined endpoint and placeholder to streamline the selection process.
|
|
145
|
+
*
|
|
146
|
+
* @macro Component that facilitates app selection in the admin panel.
|
|
147
|
+
* @micro Uses a fixed API endpoint to fetch a list of applications.
|
|
148
|
+
* @inputSpec
|
|
149
|
+
* props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'> — properties for the EntitySelect component.
|
|
150
|
+
* @outputSpec JSX.Element — renders the EntitySelect component.
|
|
151
|
+
* @sideEffects none
|
|
152
|
+
* @stability internal
|
|
153
|
+
* @calls EntitySelect
|
|
154
|
+
* @cil-generated
|
|
155
|
+
*/
|
|
156
|
+
export function AppSelect(props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'>) {
|
|
157
|
+
return <EntitySelect endpoint="/api/apps?action=list" placeholder="No app (global)" {...props} />
|
|
158
|
+
}
|
|
159
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:AppSelect:component"]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/EntitySelect.tsx:PipelineSelect:component" type="component" identity="PipelineSelect" parent="~/.framework/src/components/admin/EntitySelect.tsx"]
|
|
164
|
+
/**
|
|
165
|
+
* PipelineSelect is a component that provides a dropdown for selecting a pipeline from a predefined list. It simplifies the usage of the EntitySelect component by pre-configuring the endpoint and placeholder specific to pipelines.
|
|
166
|
+
*
|
|
167
|
+
* @macro Component that renders a selection interface for pipelines.
|
|
168
|
+
* @micro Uses the EntitySelect component with a fixed API endpoint for fetching pipeline data.
|
|
169
|
+
* @inputSpec
|
|
170
|
+
* props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'> — properties for the EntitySelect component excluding endpoint and placeholder.
|
|
171
|
+
* @outputSpec JSX.Element — renders the EntitySelect component.
|
|
172
|
+
* @sideEffects none
|
|
173
|
+
* @stability internal
|
|
174
|
+
* @calls EntitySelect
|
|
175
|
+
* @cil-generated
|
|
176
|
+
*/
|
|
177
|
+
export function PipelineSelect(props: Omit<EntitySelectProps, 'endpoint' | 'placeholder'>) {
|
|
178
|
+
return <EntitySelect endpoint="/api/pipelines?action=list" placeholder="Select a pipeline…" {...props} />
|
|
179
|
+
}
|
|
180
|
+
// CIL[END stable_id="~/.framework/src/components/admin/EntitySelect.tsx:PipelineSelect:component"]
|
|
181
|
+
|
|
@@ -1,145 +1,104 @@
|
|
|
1
|
-
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:module_header:module_header"]
|
|
2
|
-
// CIL[DOC-MACRO purpose="Top-level module header for the PageInstructions React component."]
|
|
3
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Declare imports, exports, and the public surface of this module."]
|
|
4
|
-
// CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
|
|
5
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="module exports" errors="none" side_effects="none"]
|
|
6
|
-
// CIL[DOC-MICRO logic_summary="Aggregates imports and exports for the collapsible page instructions UI component." notable_decisions="[]"]
|
|
7
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
9
|
-
// CIL[DOC-AUDIENCE audience="module authors and consumers"]
|
|
10
|
-
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
11
2
|
import * as React from 'react'
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
18
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
19
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
20
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
21
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
3
|
+
import { BookOpen } from 'lucide-react'
|
|
4
|
+
import ReactMarkdown from 'react-markdown'
|
|
5
|
+
import remarkGfm from 'remark-gfm'
|
|
6
|
+
import { Button } from '../ui/button'
|
|
7
|
+
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '../ui/sheet'
|
|
22
8
|
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:module_header:module_header"]
|
|
23
9
|
|
|
24
|
-
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// CIL[
|
|
31
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
10
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionModules:constant" type="constant" identity="instructionModules" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
11
|
+
const instructionModules = import.meta.glob('../../instructions/**/*.md', {
|
|
12
|
+
query: '?raw',
|
|
13
|
+
import: 'default',
|
|
14
|
+
eager: true,
|
|
15
|
+
}) as Record<string, string>
|
|
16
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionModules:constant"]
|
|
32
17
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
18
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionDocs:constant" type="constant" identity="instructionDocs" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
19
|
+
const instructionDocs: Record<string, string> = {}
|
|
20
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:instructionDocs:constant"]
|
|
21
|
+
for (const [path, content] of Object.entries(instructionModules)) {
|
|
22
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:key:constant" type="constant" identity="key" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
23
|
+
const key = path.replace(/^.*instructions\//, '').replace(/\.md$/, '')
|
|
24
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:key:constant"]
|
|
25
|
+
if (key) instructionDocs[key] = content
|
|
41
26
|
}
|
|
42
27
|
|
|
43
|
-
// CIL[
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
59
|
-
|
|
60
|
-
export interface PageInstructionsSection {
|
|
61
|
-
title: string
|
|
62
|
-
content: React.ReactNode
|
|
28
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PAGE_TITLES:constant" type="constant" identity="PAGE_TITLES" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
29
|
+
const PAGE_TITLES: Record<string, string> = {
|
|
30
|
+
types: 'Types',
|
|
31
|
+
apps: 'Apps',
|
|
32
|
+
pipelines: 'Pipelines',
|
|
33
|
+
triggers: 'Triggers',
|
|
34
|
+
'ai-agents': 'AI Agents',
|
|
35
|
+
timers: 'Timers',
|
|
36
|
+
integrations: 'Integrations',
|
|
37
|
+
roles: 'Roles',
|
|
38
|
+
prompts: 'Prompt Configs',
|
|
39
|
+
'api-keys': 'API Keys',
|
|
40
|
+
deliveries: 'Deliveries',
|
|
41
|
+
'runtime-list': 'Records',
|
|
42
|
+
'runtime-detail': 'Record',
|
|
63
43
|
}
|
|
44
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PAGE_TITLES:constant"]
|
|
64
45
|
|
|
65
|
-
// CIL[
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
46
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:displayTitle:function" type="function" identity="displayTitle" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
47
|
+
function displayTitle(pageKey: string): string {
|
|
48
|
+
return (
|
|
49
|
+
PAGE_TITLES[pageKey] ??
|
|
50
|
+
pageKey
|
|
51
|
+
.split(/[-_]/)
|
|
52
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
53
|
+
.join(' ')
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:displayTitle:function"]
|
|
72
57
|
|
|
73
|
-
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// CIL[
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
58
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:cleanMarkdown:function" type="function" identity="cleanMarkdown" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
59
|
+
function cleanMarkdown(markdown: string): string {
|
|
60
|
+
return markdown
|
|
61
|
+
.split('\n')
|
|
62
|
+
.filter((line) => !line.trim().startsWith('// CIL['))
|
|
63
|
+
.join('\n')
|
|
64
|
+
.trim()
|
|
65
|
+
}
|
|
66
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:cleanMarkdown:function"]
|
|
81
67
|
|
|
68
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructionsProps:interface" type="interface" identity="PageInstructionsProps" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
82
69
|
export interface PageInstructionsProps {
|
|
70
|
+
pageKey: string
|
|
83
71
|
title?: string
|
|
84
|
-
description?: React.ReactNode
|
|
85
|
-
sections?: PageInstructionsSection[]
|
|
86
72
|
}
|
|
73
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructionsProps:interface"]
|
|
87
74
|
|
|
88
|
-
// CIL[
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
93
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
94
|
-
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructionsprops:interface"]
|
|
95
|
-
|
|
96
|
-
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructions:function"]
|
|
97
|
-
// CIL[DOC-MACRO purpose="Render a collapsible card containing optional description and instruction sections."]
|
|
98
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Display page-level help or instructions in a collapsible UI widget."]
|
|
99
|
-
// CIL[DOC-CONTEXT module="admin" layer="components" related_files=".framework/src/components/admin/PageInstructions.tsx,.framework/src/components/ui/card.tsx,.framework/src/components/ui/collapsible.tsx"]
|
|
100
|
-
// CIL[DOC-CONTRACT inputs="props: PageInstructionsProps" outputs="JSX element or null" errors="none" side_effects="renders UI"]
|
|
101
|
-
// CIL[DOC-MICRO logic_summary="Returns null when no content is provided; otherwise renders a Card with a Collapsible trigger and filtered description/section content." notable_decisions="[]"]
|
|
102
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
103
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
104
|
-
|
|
105
|
-
export function PageInstructions({
|
|
106
|
-
title = 'Page instructions',
|
|
107
|
-
description,
|
|
108
|
-
sections,
|
|
109
|
-
}: PageInstructionsProps) {
|
|
110
|
-
if (!description && (!sections || sections.length === 0)) return null
|
|
75
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructions:component" type="component" identity="PageInstructions" parent="~/.framework/src/components/admin/PageInstructions.tsx"]
|
|
76
|
+
export function PageInstructions({ pageKey, title }: PageInstructionsProps) {
|
|
77
|
+
const markdown = instructionDocs[pageKey]
|
|
78
|
+
if (!markdown) return null
|
|
111
79
|
|
|
112
80
|
return (
|
|
113
|
-
<
|
|
114
|
-
<
|
|
115
|
-
<
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
</CardContent>
|
|
135
|
-
</Card>
|
|
81
|
+
<Sheet>
|
|
82
|
+
<SheetTrigger asChild>
|
|
83
|
+
<Button variant="ghost" size="sm" className="h-7 gap-1.5 px-2.5 text-xs text-muted-foreground hover:text-foreground">
|
|
84
|
+
<BookOpen className="h-3.5 w-3.5" />
|
|
85
|
+
Instructions
|
|
86
|
+
</Button>
|
|
87
|
+
</SheetTrigger>
|
|
88
|
+
<SheetContent side="right" className="w-full sm:max-w-xl">
|
|
89
|
+
<SheetHeader className="border-b pr-12">
|
|
90
|
+
<SheetTitle>{title ?? displayTitle(pageKey)}</SheetTitle>
|
|
91
|
+
<SheetDescription className="sr-only">
|
|
92
|
+
Instructions and reference for this page
|
|
93
|
+
</SheetDescription>
|
|
94
|
+
</SheetHeader>
|
|
95
|
+
<div className="min-h-0 flex-1 overflow-y-auto px-6 py-4">
|
|
96
|
+
<div className="prose prose-sm prose-slate max-w-none">
|
|
97
|
+
<ReactMarkdown remarkPlugins={[remarkGfm]}>{cleanMarkdown(markdown)}</ReactMarkdown>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</SheetContent>
|
|
101
|
+
</Sheet>
|
|
136
102
|
)
|
|
137
103
|
}
|
|
138
|
-
|
|
139
|
-
// CIL[DOC-VECTOR type="context" content="purpose='Render a collapsible card containing optional description and instruction sections.'; No verified external callers; imports: .framework/src/components/ui/collapsible.tsx,.framework/src/components/ui/card.tsx"]
|
|
140
|
-
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
141
|
-
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
142
|
-
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
143
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
144
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
145
|
-
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:pageinstructions:function"]
|
|
104
|
+
// CIL[END stable_id="~/.framework/src/components/admin/PageInstructions.tsx:PageInstructions:component"]
|
|
@@ -12,6 +12,7 @@ import { Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-
|
|
|
12
12
|
import { AppRecord } from '../../hooks/useApps'
|
|
13
13
|
import { GenericListPage } from './GenericListPage'
|
|
14
14
|
import { GenericDetailPage } from './GenericDetailPage'
|
|
15
|
+
import { useBranding } from '../../hooks/useBranding'
|
|
15
16
|
// CIL[DOC-VECTOR type="context" content="purpose='Module imports and re-exports for the GenericAppShell component'; No verified external callers; imports: .framework/src/hooks/useApps.ts,.framework/src/components/app-shell/GenericListPage.tsx,.framework/src/components/app-shell/GenericDetailPage.tsx"]
|
|
16
17
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
17
18
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
@@ -76,6 +77,7 @@ export function GenericAppShell({ app }: GenericAppShellProps) {
|
|
|
76
77
|
const navigate = useNavigate()
|
|
77
78
|
const location = useLocation()
|
|
78
79
|
const [sidebarOpen, setSidebarOpen] = useState(false)
|
|
80
|
+
const branding = useBranding()
|
|
79
81
|
|
|
80
82
|
const navItems: NavItem[] = (app.nav_items || []) as NavItem[]
|
|
81
83
|
|
|
@@ -98,7 +100,7 @@ export function GenericAppShell({ app }: GenericAppShellProps) {
|
|
|
98
100
|
${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
|
|
99
101
|
`}>
|
|
100
102
|
<div className="flex items-center gap-3 h-16 px-6 border-b border-slate-200">
|
|
101
|
-
<img src=
|
|
103
|
+
<img src={branding.logo_url} alt={branding.app_name} className="h-8 w-auto shrink-0" />
|
|
102
104
|
<div>
|
|
103
105
|
<h2 className="font-semibold text-slate-900 text-sm">{app.name}</h2>
|
|
104
106
|
{app.description && (
|
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
|
|
11
11
|
import { useState, useEffect } from 'react'
|
|
12
12
|
import { useParams, useSearchParams, useNavigate } from 'react-router-dom'
|
|
13
|
+
import { apiFetch } from '../../lib/api'
|
|
13
14
|
import { useEntityRecord } from '../../hooks/useEntityRecord'
|
|
14
15
|
import { DataDetailHeader } from '../runtime/DataDetailHeader'
|
|
15
16
|
import { SchemaDetailForm } from '../runtime/SchemaDetailForm'
|
|
17
|
+
// CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:module_header:module_header"]
|
|
16
18
|
// CIL[DOC-VECTOR type="context" content="purpose='Imports and module setup for the generic detail page'; No verified external callers; imports: .framework/src/hooks/useEntityRecord.ts,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx"]
|
|
17
19
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
18
20
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
19
21
|
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
20
22
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
21
23
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
22
|
-
// CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:module_header:module_header"]
|
|
23
|
-
// CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface" type="interface" identity="GenericDetailPageProps" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
|
|
24
24
|
// CIL[DOC-MACRO purpose="Props interface for GenericDetailPage"]
|
|
25
25
|
// CIL[DOC-RESPONSIBILITY responsibility="Define the expected props for the detail page"]
|
|
26
26
|
// CIL[DOC-CONTEXT module="app-shell" layer="framework" related_files=".framework/src/components/app-shell/GenericDetailPage.tsx,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx,.framework/src/hooks/useEntityRecord.ts"]
|
|
@@ -28,21 +28,21 @@ import { SchemaDetailForm } from '../runtime/SchemaDetailForm'
|
|
|
28
28
|
// CIL[DOC-MICRO logic_summary="TypeScript interface describing typeSlug, viewSlug, and isCreating" notable_decisions="[]"]
|
|
29
29
|
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
30
30
|
// CIL[DOC-STABILITY stability="stable"]
|
|
31
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface" type="interface" identity="GenericDetailPageProps" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
|
|
31
32
|
interface GenericDetailPageProps {
|
|
32
33
|
typeSlug: string
|
|
33
34
|
viewSlug?: string
|
|
34
35
|
isCreating?: boolean
|
|
35
36
|
}
|
|
37
|
+
// CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface"]
|
|
36
38
|
// CIL[DOC-VECTOR type="context" content="purpose='Props interface for GenericDetailPage'; No verified external callers; imports: .framework/src/hooks/useEntityRecord.ts,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx"]
|
|
37
39
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
38
40
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
39
41
|
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
40
42
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
41
43
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
42
|
-
// CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPageProps:interface"]
|
|
43
44
|
|
|
44
45
|
|
|
45
|
-
// CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component" type="component" identity="GenericDetailPage" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
|
|
46
46
|
// CIL[DOC-MACRO purpose="Render the generic detail page for an app type"]
|
|
47
47
|
// CIL[DOC-RESPONSIBILITY responsibility="Display, edit, create, and delete records driven by a design schema"]
|
|
48
48
|
// CIL[DOC-CONTEXT module="app-shell" layer="framework" related_files=".framework/src/components/app-shell/GenericDetailPage.tsx,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx,.framework/src/hooks/useEntityRecord.ts"]
|
|
@@ -50,6 +50,7 @@ interface GenericDetailPageProps {
|
|
|
50
50
|
// CIL[DOC-MICRO logic_summary="Load record with useEntityRecord, resolve detail view, initialize form data, and render DataDetailHeader and SchemaDetailForm" notable_decisions="[]"]
|
|
51
51
|
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
52
52
|
// CIL[DOC-STABILITY stability="stable"]
|
|
53
|
+
// CIL[BEGIN stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component" type="component" identity="GenericDetailPage" parent="~/.framework/src/components/app-shell/GenericDetailPage.tsx"]
|
|
53
54
|
export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate }: GenericDetailPageProps) {
|
|
54
55
|
const { id } = useParams<{ id: string }>()
|
|
55
56
|
const navigate = useNavigate()
|
|
@@ -83,10 +84,31 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
|
|
|
83
84
|
deleting
|
|
84
85
|
} = useEntityRecord('items', id, config)
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
87
|
+
// In create mode there is no record to take a stamped design_schema from —
|
|
88
|
+
// resolve it from the type instead (get_type_schema RPC via /api/types).
|
|
89
|
+
const [typeSchema, setTypeSchema] = useState<any>(null)
|
|
90
|
+
const [schemaLoading, setSchemaLoading] = useState(false)
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (!isCreating) return
|
|
93
|
+
let cancelled = false
|
|
94
|
+
setSchemaLoading(true)
|
|
95
|
+
apiFetch(`/api/types?action=schema&kind=item&slug=${encodeURIComponent(typeSlug)}`)
|
|
96
|
+
.then(async (res) => {
|
|
97
|
+
const result = await res.json()
|
|
98
|
+
const ds = (result.data ?? result)?.design_schema
|
|
99
|
+
if (!cancelled) setTypeSchema(ds && Object.keys(ds).length ? ds : null)
|
|
100
|
+
})
|
|
101
|
+
.catch(() => { if (!cancelled) setTypeSchema(null) })
|
|
102
|
+
.finally(() => { if (!cancelled) setSchemaLoading(false) })
|
|
103
|
+
return () => { cancelled = true }
|
|
104
|
+
}, [isCreating, typeSlug])
|
|
105
|
+
|
|
106
|
+
const schema = record?.design_schema || typeSchema || null
|
|
107
|
+
// nav_item `view` is a single slug shared by list + detail pages; a
|
|
108
|
+
// list-shaped view (fields, no sections) must not resolve here.
|
|
109
|
+
const namedView = viewSlug ? schema?.views?.[viewSlug] : null
|
|
110
|
+
const resolvedDetailView = namedView && (namedView.type === 'detail' || namedView.sections)
|
|
111
|
+
? namedView
|
|
90
112
|
: schema?.views?.default_detail
|
|
91
113
|
const view = resolvedDetailView || null
|
|
92
114
|
|
|
@@ -175,7 +197,7 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
|
|
|
175
197
|
}
|
|
176
198
|
}
|
|
177
199
|
|
|
178
|
-
if (loading) {
|
|
200
|
+
if (loading || schemaLoading) {
|
|
179
201
|
return (
|
|
180
202
|
<div className="p-8 text-center">
|
|
181
203
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto"></div>
|
|
@@ -193,11 +215,13 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
|
|
|
193
215
|
)
|
|
194
216
|
}
|
|
195
217
|
|
|
196
|
-
if (!schema
|
|
218
|
+
if (!schema) {
|
|
197
219
|
return (
|
|
198
220
|
<div className="p-8 text-center">
|
|
199
221
|
<h2 className="text-lg font-medium text-slate-900">No schema available</h2>
|
|
200
|
-
<p className="mt-2 text-sm text-slate-500">
|
|
222
|
+
<p className="mt-2 text-sm text-slate-500">
|
|
223
|
+
{isCreating ? `No design_schema found for type "${typeSlug}".` : 'This record does not have a design_schema.'}
|
|
224
|
+
</p>
|
|
201
225
|
</div>
|
|
202
226
|
)
|
|
203
227
|
}
|
|
@@ -233,10 +257,10 @@ export function GenericDetailPage({ typeSlug, viewSlug, isCreating: forceCreate
|
|
|
233
257
|
</div>
|
|
234
258
|
)
|
|
235
259
|
}
|
|
260
|
+
// CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component"]
|
|
236
261
|
// CIL[DOC-VECTOR type="context" content="purpose='Render the generic detail page for an app type'; No verified external callers; imports: .framework/src/hooks/useEntityRecord.ts,.framework/src/components/runtime/DataDetailHeader.tsx,.framework/src/components/runtime/SchemaDetailForm.tsx"]
|
|
237
262
|
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
238
263
|
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
239
264
|
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
240
265
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
241
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
242
|
-
// CIL[END stable_id="~/.framework/src/components/app-shell/GenericDetailPage.tsx:GenericDetailPage:component"]
|
|
266
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|