spine-framework 0.3.124 → 0.3.126
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/.framework/cli/commands/agents.ts +35 -37
- package/.framework/cli/commands/auth.ts +35 -34
- package/.framework/cli/commands/create-app.ts +104 -40
- package/.framework/cli/commands/dev.ts +104 -69
- package/.framework/cli/commands/doctor.ts +179 -69
- package/.framework/cli/commands/generate.ts +83 -143
- package/.framework/cli/commands/init.ts +72 -34
- package/.framework/cli/commands/install-app.ts +260 -125
- package/.framework/cli/commands/items.ts +33 -44
- package/.framework/cli/commands/migrate.ts +122 -40
- package/.framework/cli/commands/migrations.ts +33 -40
- package/.framework/cli/commands/pipelines.ts +31 -39
- package/.framework/cli/commands/status.ts +47 -23
- package/.framework/cli/commands/system.ts +47 -37
- package/.framework/cli/commands/test.ts +112 -68
- package/.framework/cli/commands/validate-app.ts +215 -121
- package/.framework/cli/context.ts +112 -130
- package/.framework/cli/env-loader.ts +47 -18
- package/.framework/cli/index.ts +81 -42
- package/.framework/docs/runtime-types.md +1024 -0
- package/.framework/functions/_shared/agent-runner.ts +1296 -961
- package/.framework/functions/_shared/app-manifest.ts +82 -68
- package/.framework/functions/_shared/audit.ts +135 -83
- package/.framework/functions/_shared/{cil-state.ts → cil.ts} +158 -56
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +224 -335
- package/.framework/functions/_shared/kb.ts +319 -0
- package/.framework/functions/_shared/llm.ts +92 -0
- package/.framework/functions/_shared/logging.ts +288 -0
- package/.framework/functions/_shared/middleware.ts +329 -365
- package/.framework/functions/_shared/outcomes.ts +36 -0
- package/.framework/functions/_shared/permissions.ts +359 -643
- package/.framework/functions/_shared/pipeline-runner.ts +243 -316
- package/.framework/functions/_shared/principal.ts +376 -468
- package/.framework/functions/_shared/resolve-credentials.ts +102 -0
- package/.framework/functions/_shared/resolve-ids.ts +188 -16
- package/.framework/functions/_shared/retry-deliveries.ts +104 -0
- package/.framework/functions/_shared/schema-utils.ts +611 -373
- package/.framework/functions/_shared/testing.ts +207 -137
- package/.framework/functions/_shared/tracing.ts +276 -0
- package/.framework/functions/_shared/trigger-engine.ts +159 -211
- package/.framework/functions/_shared/webhook-registration.ts +95 -81
- package/.framework/functions/_shared/webhook-registry.ts +153 -75
- package/.framework/functions/account-nodes.ts +31 -53
- package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
- package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
- package/.framework/functions/adapters/openai-outbound.ts +40 -0
- package/.framework/functions/admin-data.ts +685 -537
- package/.framework/functions/admin-funnel.ts +31 -20
- package/.framework/functions/admin-install-funnel.ts +47 -28
- package/.framework/functions/admin-signals.ts +47 -29
- package/.framework/functions/ai-agents.ts +122 -147
- package/.framework/functions/ai-interactions.ts +180 -90
- package/.framework/functions/api-keys.ts +250 -192
- package/.framework/functions/apps.ts +203 -197
- package/.framework/functions/auth.ts +98 -91
- package/.framework/functions/cil-agent-ingest.ts +773 -0
- package/.framework/functions/cil-agent.ts +592 -0
- package/.framework/functions/cil-callmap.ts +1227 -0
- package/.framework/functions/cil-config.ts +583 -0
- package/.framework/functions/cil-context.ts +445 -0
- package/.framework/functions/cil-doc.ts +1752 -0
- package/.framework/functions/cil-embeddings.ts +1202 -0
- package/.framework/functions/cil-graph.ts +585 -0
- package/.framework/functions/cil-ingest.ts +2416 -0
- package/.framework/functions/cil-pipeline.ts +318 -0
- package/.framework/functions/cil-project.ts +499 -0
- package/.framework/functions/cil-validate.ts +469 -0
- package/.framework/functions/debug-auth.ts +73 -53
- package/.framework/functions/deliveries.ts +117 -0
- package/.framework/functions/embeddings.ts +528 -516
- package/.framework/functions/eval-harness.ts +158 -106
- package/.framework/functions/integration-outbound.ts +311 -0
- package/.framework/functions/integration-routes.ts +240 -466
- package/.framework/functions/integrations.ts +132 -140
- package/.framework/functions/invites.ts +401 -201
- package/.framework/functions/item-progress.ts +113 -53
- package/.framework/functions/kb.ts +28 -0
- package/.framework/functions/logs.ts +239 -222
- package/.framework/functions/observability.ts +308 -259
- package/.framework/functions/pipeline-executions.ts +179 -235
- package/.framework/functions/pipelines.ts +163 -205
- package/.framework/functions/prompt-configs.ts +109 -156
- package/.framework/functions/roles.ts +97 -147
- package/.framework/functions/system-cron.ts +132 -218
- package/.framework/functions/system.ts +112 -52
- package/.framework/functions/tests.ts +32 -28
- package/.framework/functions/timers.ts +162 -210
- package/.framework/functions/triggers.ts +282 -346
- package/.framework/functions/types.ts +283 -400
- package/.framework/migrations/001_core_schema.sql +630 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
- package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
- package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
- package/.framework/migrations/005_core_observability.sql +598 -0
- package/.framework/migrations/006_security_hardening_rls.sql +97 -0
- package/.framework/migrations/007_kb_article_list.sql +237 -0
- package/.framework/migrations/008_items_target.sql +8 -0
- package/.framework/migrations/009_roles_slug_unique.sql +11 -0
- package/.framework/public/spine.config.json +91 -0
- package/.framework/scripts/app-install-cli.ts +112 -98
- package/.framework/src/App.tsx +67 -20
- package/.framework/src/apps/admin/index.tsx +97 -27
- package/.framework/src/components/AppWrapper.tsx +50 -11
- package/.framework/src/components/CustomAppLoader.tsx +131 -22
- package/.framework/src/components/admin/AdminListPage.tsx +75 -8
- package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
- package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
- package/.framework/src/components/admin/PageInstructions.tsx +49 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
- package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
- package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
- package/.framework/src/components/app-sidebar.tsx +50 -3
- package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
- package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
- package/.framework/src/components/kb/KBArticleList.tsx +557 -0
- package/.framework/src/components/layout/AppShell.tsx +54 -16
- package/.framework/src/components/layout/Header.tsx +50 -38
- package/.framework/src/components/layout/Layout.tsx +48 -32
- package/.framework/src/components/layout/Sidebar.tsx +167 -16
- package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
- package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
- package/.framework/src/components/runtime/DataFilters.tsx +78 -1
- package/.framework/src/components/runtime/DataHeader.tsx +32 -29
- package/.framework/src/components/runtime/DataListPage.tsx +161 -2
- package/.framework/src/components/runtime/DataStats.tsx +48 -1
- package/.framework/src/components/runtime/DataTable.tsx +153 -1
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
- package/.framework/src/components/runtime/index.ts +16 -9
- package/.framework/src/components/search-form.tsx +33 -1
- package/.framework/src/components/shared/AgentView.tsx +48 -51
- package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
- package/.framework/src/components/shared/InviteManager.tsx +113 -52
- package/.framework/src/components/shared/MemberList.tsx +182 -0
- package/.framework/src/components/shared/SchemaFields.tsx +96 -78
- package/.framework/src/components/ui/DataTable.tsx +86 -56
- package/.framework/src/components/ui/Form.tsx +188 -109
- package/.framework/src/components/ui/ItemCard.tsx +86 -58
- package/.framework/src/components/ui/ItemListView.tsx +88 -61
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
- package/.framework/src/components/ui/Modal.tsx +81 -4
- package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
- package/.framework/src/components/ui/accordion.tsx +97 -5
- package/.framework/src/components/ui/alert-dialog.tsx +225 -13
- package/.framework/src/components/ui/alert.tsx +113 -6
- package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
- package/.framework/src/components/ui/avatar.tsx +129 -7
- package/.framework/src/components/ui/badge.tsx +65 -3
- package/.framework/src/components/ui/breadcrumb.tsx +145 -8
- package/.framework/src/components/ui/button-group.tsx +81 -4
- package/.framework/src/components/ui/button.tsx +49 -2
- package/.framework/src/components/ui/calendar.tsx +65 -3
- package/.framework/src/components/ui/card.tsx +145 -8
- package/.framework/src/components/ui/carousel.tsx +129 -7
- package/.framework/src/components/ui/chart.tsx +161 -10
- package/.framework/src/components/ui/checkbox.tsx +49 -2
- package/.framework/src/components/ui/collapsible.tsx +81 -5
- package/.framework/src/components/ui/combobox.tsx +305 -20
- package/.framework/src/components/ui/command.tsx +177 -11
- package/.framework/src/components/ui/context-menu.tsx +273 -17
- package/.framework/src/components/ui/dialog.tsx +209 -27
- package/.framework/src/components/ui/direction.tsx +64 -4
- package/.framework/src/components/ui/drawer.tsx +193 -12
- package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
- package/.framework/src/components/ui/empty.tsx +145 -9
- package/.framework/src/components/ui/field.tsx +209 -14
- package/.framework/src/components/ui/hover-card.tsx +81 -4
- package/.framework/src/components/ui/input-group.tsx +162 -10
- package/.framework/src/components/ui/input-otp.tsx +98 -5
- package/.framework/src/components/ui/input.tsx +49 -2
- package/.framework/src/components/ui/item.tsx +225 -13
- package/.framework/src/components/ui/kbd.tsx +65 -3
- package/.framework/src/components/ui/label.tsx +49 -2
- package/.framework/src/components/ui/menubar.tsx +289 -17
- package/.framework/src/components/ui/native-select.tsx +97 -5
- package/.framework/src/components/ui/navigation-menu.tsx +177 -10
- package/.framework/src/components/ui/pagination.tsx +161 -9
- package/.framework/src/components/ui/popover.tsx +145 -8
- package/.framework/src/components/ui/progress.tsx +49 -2
- package/.framework/src/components/ui/radio-group.tsx +65 -3
- package/.framework/src/components/ui/resizable.tsx +82 -4
- package/.framework/src/components/ui/scroll-area.tsx +65 -3
- package/.framework/src/components/ui/select.tsx +193 -11
- package/.framework/src/components/ui/separator.tsx +49 -2
- package/.framework/src/components/ui/sheet.tsx +193 -11
- package/.framework/src/components/ui/sidebar.tsx +481 -38
- package/.framework/src/components/ui/skeleton.tsx +49 -2
- package/.framework/src/components/ui/slider.tsx +49 -2
- package/.framework/src/components/ui/sonner.tsx +49 -2
- package/.framework/src/components/ui/spinner.tsx +49 -2
- package/.framework/src/components/ui/switch.tsx +49 -2
- package/.framework/src/components/ui/table-primitives.tsx +160 -33
- package/.framework/src/components/ui/table.tsx +161 -9
- package/.framework/src/components/ui/tabs.tsx +113 -6
- package/.framework/src/components/ui/textarea.tsx +49 -2
- package/.framework/src/components/ui/toggle-group.tsx +81 -4
- package/.framework/src/components/ui/toggle.tsx +65 -3
- package/.framework/src/components/ui/tooltip.tsx +97 -5
- package/.framework/src/contexts/AppContext.tsx +129 -45
- package/.framework/src/contexts/AuthContext.tsx +187 -144
- package/.framework/src/hooks/use-mobile.ts +48 -2
- package/.framework/src/hooks/useApi.ts +208 -159
- package/.framework/src/hooks/useAppPath.ts +32 -23
- package/.framework/src/hooks/useApps.ts +51 -20
- package/.framework/src/hooks/useEntityList.ts +32 -78
- package/.framework/src/hooks/useEntityRecord.ts +35 -96
- package/.framework/src/hooks/useForm.ts +32 -92
- package/.framework/src/hooks/useListSchema.ts +49 -78
- package/.framework/src/hooks/useSchemaRecord.ts +114 -105
- package/.framework/src/lib/api.ts +195 -116
- package/.framework/src/lib/supabase.ts +98 -64
- package/.framework/src/lib/utils.ts +287 -151
- package/.framework/src/main.tsx +49 -3
- package/.framework/src/pages/DashboardPage.tsx +52 -29
- package/.framework/src/pages/NotFoundPage.tsx +32 -10
- package/.framework/src/pages/SetupPage.tsx +32 -12
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
- package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
- package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
- package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
- package/.framework/src/pages/admin/AppsPage.tsx +49 -2
- package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
- package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
- package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
- package/.framework/src/pages/admin/LogsPage.tsx +422 -75
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
- package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
- package/.framework/src/pages/admin/RolesPage.tsx +171 -18
- package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
- package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
- package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
- package/.framework/src/pages/admin/TimersPage.tsx +48 -20
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
- package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
- package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
- package/.framework/src/pages/admin/TypesPage.tsx +48 -20
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
- package/.framework/src/pages/auth/LoginPage.tsx +50 -23
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
- package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
- package/.framework/src/types/auth.ts +128 -71
- package/.framework/src/types/types.ts +373 -157
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
- package/docs/README.md +9 -130
- package/netlify.toml +5 -2
- package/package.json +13 -25
- package/scripts/kb-ingest-docs.ts +203 -0
- package/spine.config.json +65 -4
- package/.framework/migrations/001_schema.sql +0 -425
- package/.framework/migrations/002_rls_and_functions.sql +0 -763
- package/.framework/migrations/004_enhancements.sql +0 -43
- package/.framework/migrations/005_auth_user_trigger.sql +0 -105
- package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
- package/.framework/migrations/016_invites.sql +0 -27
- package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
- package/.framework/migrations/018_apps_required_roles.sql +0 -17
- package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
- package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
- package/.framework/migrations/021_app_domains.sql +0 -112
- package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
- package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
- package/.framework/migrations/024_messages_account_id.sql +0 -9
- package/.framework/migrations/025_retype_threads_messages.sql +0 -240
- package/.framework/migrations/026_fix_rls_policies.sql +0 -47
- package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
- package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
- package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
- package/.framework/migrations/030_messages_updated_by.sql +0 -6
- package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
- package/docs/APPS.md +0 -232
- package/docs/ARCHITECTURE.md +0 -246
- package/docs/INSTALL.md +0 -155
- package/docs/design-schema-spec.md +0 -1837
- package/docs/dev-guides/01-create-an-app.md +0 -183
- package/docs/dev-guides/02-create-a-function.md +0 -178
- package/docs/dev-guides/03-create-a-component.md +0 -178
- package/docs/dev-guides/04-webhook-handlers.md +0 -129
- package/docs/dev-guides/05-testing.md +0 -168
- package/docs/dev-guides/README.md +0 -40
- package/docs/npm-packages-plan.md +0 -288
- package/docs/spine-core--api-reference.md +0 -822
|
@@ -1,48 +1,35 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module src/components/shared/FieldRenderer
|
|
3
|
-
* @audience installer
|
|
4
|
-
* @layer frontend-component
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Low-level field rendering primitive. Given a `FieldDefinition` and a
|
|
8
|
-
* current value, renders the appropriate input widget (edit mode) or
|
|
9
|
-
* display element (read-only mode).
|
|
10
|
-
*
|
|
11
|
-
* **Render type resolution** (`resolveRenderType`):
|
|
12
|
-
* 1. If `displayType` is set (from the view config), it maps to a canonical
|
|
13
|
-
* render type first — this lets a view override how a field looks without
|
|
14
|
-
* changing the underlying `FieldDefinition`.
|
|
15
|
-
* 2. Falls back to `field.data_type`.
|
|
16
|
-
*
|
|
17
|
-
* **Supported render types:**
|
|
18
|
-
* `text`, `textarea`, `email`, `phone`, `url`, `number`, `date`,
|
|
19
|
-
* `datetime`, `select`, `multiselect`, `radio`, `checkbox`, `json`,
|
|
20
|
-
* `file`, `color`, `range`
|
|
21
|
-
*
|
|
22
|
-
* **Error display:** when `error` is set, a red helper text is shown below
|
|
23
|
-
* the field and `border-red-500` is applied where applicable.
|
|
24
|
-
*
|
|
25
|
-
* **Label + description:** rendered above / below the input respectively,
|
|
26
|
-
* with a red `*` suffix when `field.required` is true.
|
|
27
|
-
*
|
|
28
|
-
* @seeAlso src/components/shared/SchemaFields.tsx (mounts this component)
|
|
29
|
-
* @seeAlso src/types/types.ts (FieldDefinition)
|
|
30
|
-
*/
|
|
31
1
|
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// CIL[BEGIN chunk_id="FieldRenderer_module_header_1783927912" type="module_header" identity="module_header" parent="none"]
|
|
5
|
+
// CIL[DOC-MACRO purpose="Import dependencies and define field renderer component interfaces"]
|
|
6
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Manage React imports and field renderer prop types"]
|
|
7
|
+
// CIL[DOC-CONTEXT module="field-renderer" layer="frontend-component" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
|
|
8
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Imported modules and interface" errors="none" side_effects="none"]
|
|
9
|
+
// CIL[DOC-MICRO logic_summary="Imports React, field types, and defines FieldRendererProps interface" notable_decisions="[]"]
|
|
10
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
11
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
12
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
13
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/dialog.tsx, .framework/src/components/ui/table-primitives.tsx, .framework/functions/_shared/schema-utils.ts, \."]
|
|
14
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
15
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
16
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
17
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
18
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
32
19
|
import React from 'react'
|
|
20
|
+
import DOMPurify from 'dompurify'
|
|
21
|
+
import { marked } from 'marked'
|
|
33
22
|
import { FieldDefinition } from '../../types/types'
|
|
23
|
+
import { RichTextEditor } from '../ui/RichTextEditor'
|
|
24
|
+
|
|
25
|
+
function toSafeHtml(raw: string | undefined): string {
|
|
26
|
+
const source = (raw ?? '').trim()
|
|
27
|
+
if (!source) return '<p class="text-slate-400 italic">—</p>'
|
|
28
|
+
const likelyHtml = /<\/?(?:h[1-6]|p|div|ul|ol|li|pre|code|br|span|strong|em|a|table|tr|td|th|thead|tbody|blockquote)\b/i.test(source)
|
|
29
|
+
const html = likelyHtml ? source : (marked.parse(source, { async: false }) as string)
|
|
30
|
+
return DOMPurify.sanitize(html)
|
|
31
|
+
}
|
|
34
32
|
|
|
35
|
-
/**
|
|
36
|
-
* Props for `FieldRenderer`.
|
|
37
|
-
*
|
|
38
|
-
* @prop field - Full field definition including data_type, options, validation
|
|
39
|
-
* @prop value - Current controlled value
|
|
40
|
-
* @prop onChange - Value change callback (omit or pass `undefined` for read-only)
|
|
41
|
-
* @prop onBlur - Optional blur callback for validation triggers
|
|
42
|
-
* @prop readonly - If true, renders a display element instead of an input
|
|
43
|
-
* @prop error - Validation error message to display below the field
|
|
44
|
-
* @prop displayType - View-config widget override (e.g. `'textarea'`, `'select'`)
|
|
45
|
-
*/
|
|
46
33
|
interface FieldRendererProps {
|
|
47
34
|
field: FieldDefinition
|
|
48
35
|
value: any
|
|
@@ -50,27 +37,32 @@ interface FieldRendererProps {
|
|
|
50
37
|
onBlur?: () => void
|
|
51
38
|
readonly?: boolean
|
|
52
39
|
error?: string
|
|
53
|
-
displayType?: string
|
|
40
|
+
displayType?: string
|
|
54
41
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
42
|
+
// CIL[END chunk_id="FieldRenderer_module_header_1783927912"]
|
|
43
|
+
// CIL[BEGIN chunk_id="FieldRenderer_resolverendertype_1783927912" type="function" identity="resolveRenderType" parent="none"]
|
|
44
|
+
// CIL[DOC-LEARNING topic="runtime-type:generic/field_rendering" content="FieldRenderer maps field.data_type or display_type to a widget: text, textarea, email, phone, url, number, date, datetime, checkbox, select, multiselect, radio, color, file, json. display_type overrides data_type when provided."]
|
|
45
|
+
// CIL[DOC-NOTE type="design_schema_caveat" content="Unknown data_type or display_type silently falls back to text. Select/multiselect fields must define options or the user sees an empty control."]
|
|
46
|
+
// CIL[DOC-MACRO purpose="Resolve canonical render type from field definition and display type"]
|
|
47
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Map display types and data types to render types"]
|
|
48
|
+
// CIL[DOC-CONTEXT module="field-renderer" layer="frontend-component" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/migrations/025_retype_threads_messages.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
|
|
49
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Render type string" errors="none" side_effects="none"]
|
|
50
|
+
// CIL[DOC-MICRO logic_summary="Display type overrides data type, maps to canonical render types" notable_decisions="[]"]
|
|
51
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
52
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
53
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 1. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/migrations/025_retype_threads_messages.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/functions/_shared/schema-utils.ts, \."]
|
|
54
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
|
|
55
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
56
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
57
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
58
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
67
59
|
function resolveRenderType(field: FieldDefinition, displayType?: string): string {
|
|
68
|
-
// displayType from view config overrides data_type for rendering decisions
|
|
69
60
|
if (displayType) {
|
|
70
61
|
switch (displayType) {
|
|
71
62
|
case 'textarea':
|
|
72
|
-
case 'rich_text':
|
|
73
63
|
return 'textarea'
|
|
64
|
+
case 'rich_text':
|
|
65
|
+
return 'rich_text'
|
|
74
66
|
case 'select':
|
|
75
67
|
return 'select'
|
|
76
68
|
case 'multiselect':
|
|
@@ -93,11 +85,11 @@ function resolveRenderType(field: FieldDefinition, displayType?: string): string
|
|
|
93
85
|
return 'file'
|
|
94
86
|
}
|
|
95
87
|
}
|
|
96
|
-
// Fall back to data_type
|
|
97
88
|
switch (field.data_type) {
|
|
98
89
|
case 'textarea':
|
|
99
|
-
case 'rich_text':
|
|
100
90
|
return 'textarea'
|
|
91
|
+
case 'rich_text':
|
|
92
|
+
return 'rich_text'
|
|
101
93
|
case 'email':
|
|
102
94
|
return 'email'
|
|
103
95
|
case 'phone':
|
|
@@ -132,14 +124,21 @@ function resolveRenderType(field: FieldDefinition, displayType?: string): string
|
|
|
132
124
|
return 'text'
|
|
133
125
|
}
|
|
134
126
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
127
|
+
// CIL[END chunk_id="FieldRenderer_resolverendertype_1783927912"]
|
|
128
|
+
// CIL[BEGIN chunk_id="FieldRenderer_fieldrenderer_1783927912" type="function" identity="FieldRenderer" parent="none"]
|
|
129
|
+
// CIL[DOC-MACRO purpose="Render appropriate input widget or display element for field type"]
|
|
130
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Display field as editable input or read-only value based on type"]
|
|
131
|
+
// CIL[DOC-CONTEXT module="field-renderer" layer="frontend-component" related_files="[\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/migrations/025_retype_threads_messages.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\"\\\"]"]
|
|
132
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Rendered field widget" errors="none" side_effects="Renders UI, calls onChange"]
|
|
133
|
+
// CIL[DOC-MICRO logic_summary="Switches on render type to return appropriate input or display component" notable_decisions="[]"]
|
|
134
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
135
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
136
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/schema-utils.ts, .framework/migrations/025_retype_threads_messages.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, \."]
|
|
137
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
138
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
139
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
140
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
141
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
143
142
|
export function FieldRenderer({ field, value, onChange, readonly = false, error, displayType }: FieldRendererProps) {
|
|
144
143
|
const renderType = resolveRenderType(field, displayType)
|
|
145
144
|
|
|
@@ -160,6 +159,24 @@ export function FieldRenderer({ field, value, onChange, readonly = false, error,
|
|
|
160
159
|
/>
|
|
161
160
|
)
|
|
162
161
|
|
|
162
|
+
case 'rich_text':
|
|
163
|
+
return readonly ? (
|
|
164
|
+
<div
|
|
165
|
+
className={`prose prose-sm dark:prose-invert max-w-none ${error ? 'border-red-500' : ''}`}
|
|
166
|
+
// Sanitize before injecting: `value` may be rich-text HTML or legacy
|
|
167
|
+
// markdown stored in records, and must never execute scripts/handlers
|
|
168
|
+
// for readers (stored-XSS defense).
|
|
169
|
+
dangerouslySetInnerHTML={{ __html: toSafeHtml(value) }}
|
|
170
|
+
/>
|
|
171
|
+
) : (
|
|
172
|
+
<RichTextEditor
|
|
173
|
+
value={value || ''}
|
|
174
|
+
onChange={onChange}
|
|
175
|
+
placeholder={field.placeholder}
|
|
176
|
+
minHeight="200px"
|
|
177
|
+
/>
|
|
178
|
+
)
|
|
179
|
+
|
|
163
180
|
case 'textarea':
|
|
164
181
|
return readonly ? (
|
|
165
182
|
<div className={`text-slate-900 whitespace-pre-wrap ${error ? 'border-red-500' : ''}`}>
|
|
@@ -355,7 +372,6 @@ export function FieldRenderer({ field, value, onChange, readonly = false, error,
|
|
|
355
372
|
try {
|
|
356
373
|
onChange?.(JSON.parse(e.target.value))
|
|
357
374
|
} catch {
|
|
358
|
-
// Invalid JSON, don't update
|
|
359
375
|
}
|
|
360
376
|
}}
|
|
361
377
|
className={`textarea font-mono text-sm ${error ? 'border-red-500' : ''}`}
|
|
@@ -476,3 +492,4 @@ export function FieldRenderer({ field, value, onChange, readonly = false, error,
|
|
|
476
492
|
</div>
|
|
477
493
|
)
|
|
478
494
|
}
|
|
495
|
+
// CIL[END chunk_id="FieldRenderer_fieldrenderer_1783927912"]
|
|
@@ -1,36 +1,28 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module src/components/shared/InviteManager
|
|
3
|
-
* @audience installer
|
|
4
|
-
* @layer frontend-component
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Reusable invite and access-request management UI.
|
|
8
|
-
* Consumed by Cortex TeamPage, Portal TeamPage, and the Admin InvitesPage.
|
|
9
|
-
*
|
|
10
|
-
* Layout:
|
|
11
|
-
* [ Name input ] [ Email input ] [ Role picker ] [ Generate Link button ]
|
|
12
|
-
* ─────────────────────────────────────────────────────────────────────────
|
|
13
|
-
* Searchable/sortable invite list table with status + actions
|
|
14
|
-
*
|
|
15
|
-
* @prop accountId - Scope invites to this account UUID.
|
|
16
|
-
* Omit (system_admin only) to show all accounts.
|
|
17
|
-
* @prop allowedRoles - Roles the admin may assign. First entry is the default.
|
|
18
|
-
* If only one entry, no picker is shown.
|
|
19
|
-
* @prop roleSlugsFilter - Comma-separated role slugs to pass to list-invites.
|
|
20
|
-
* Limits which people appear in the list.
|
|
21
|
-
* @prop scope - 'account' = scoped to one account | 'system' = all accounts
|
|
22
|
-
*
|
|
23
|
-
* @seeAlso functions/invites.ts (API)
|
|
24
|
-
* @seeAlso pages/admin/InvitesPage.tsx
|
|
25
|
-
* @seeAlso custom/apps/cortex/pages/team/TeamPage.tsx
|
|
26
|
-
* @seeAlso custom/apps/portal/pages/team/TeamPage.tsx
|
|
27
|
-
*/
|
|
28
1
|
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// CIL[BEGIN chunk_id="InviteManager_module_header_1783927912" type="module_header" identity="module_header" parent="none"]
|
|
9
|
+
// CIL[DOC-MACRO purpose="Import dependencies and define invite management component interfaces"]
|
|
10
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Manage React imports and invite component prop types"]
|
|
11
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/dialog.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
|
|
12
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Imported modules and interfaces" errors="none" side_effects="none"]
|
|
13
|
+
// CIL[DOC-MICRO logic_summary="Imports React hooks and API, defines invite-related types and interfaces" notable_decisions="[]"]
|
|
14
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
15
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
16
|
+
// CIL[DOC-AUDIENCE audience="developer"]
|
|
17
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 0. Direct calls: 0. Related files: custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/dialog.tsx, .framework/src/components/ui/table-primitives.tsx, \."]
|
|
18
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
19
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
20
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
21
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
22
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
29
23
|
import React, { useState, useEffect, useCallback, useMemo } from 'react'
|
|
30
24
|
import { apiFetch } from '../../lib/api'
|
|
31
25
|
|
|
32
|
-
// ─── TYPES ────────────────────────────────────────────────────────────────────
|
|
33
|
-
|
|
34
26
|
export type InviteScope = 'account' | 'system'
|
|
35
27
|
|
|
36
28
|
export interface AllowedRole {
|
|
@@ -41,7 +33,7 @@ export interface AllowedRole {
|
|
|
41
33
|
export interface InviteManagerProps {
|
|
42
34
|
accountId?: string
|
|
43
35
|
allowedRoles: AllowedRole[]
|
|
44
|
-
roleSlugsFilter?: string
|
|
36
|
+
roleSlugsFilter?: string
|
|
45
37
|
scope: InviteScope
|
|
46
38
|
}
|
|
47
39
|
|
|
@@ -57,9 +49,21 @@ interface InviteRow {
|
|
|
57
49
|
account: { id: string; slug: string; display_name: string } | null
|
|
58
50
|
role: { id: string; slug: string; name: string } | null
|
|
59
51
|
}
|
|
60
|
-
|
|
61
|
-
//
|
|
62
|
-
|
|
52
|
+
// CIL[END chunk_id="InviteManager_module_header_1783927912"]
|
|
53
|
+
// CIL[BEGIN chunk_id="InviteManager_callinvitesapi_1783927912" type="function" identity="callInvitesApi" parent="none"]
|
|
54
|
+
// CIL[DOC-MACRO purpose="Make API calls to invites endpoint with proper method handling"]
|
|
55
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Handle GET/POST requests to invites API functions"]
|
|
56
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\".framework/src/components/ui/table-primitives.tsx\",\"\\\"]"]
|
|
57
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="API response JSON" errors="API errors" side_effects="Network requests"]
|
|
58
|
+
// CIL[DOC-MICRO logic_summary="Builds query strings for GET, sends JSON for POST to invites endpoint" notable_decisions="[]"]
|
|
59
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
60
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
61
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 1. Direct calls: 0. Related files: custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/src/pages/admin/RolesPage.tsx, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, .framework/src/components/ui/table-primitives.tsx, \."]
|
|
62
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
|
|
63
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
64
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
65
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
66
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
63
67
|
async function callInvitesApi(action: string, params: Record<string, any> = {}, method: 'GET' | 'POST' = 'GET') {
|
|
64
68
|
const base = '/.netlify/functions/invites'
|
|
65
69
|
if (method === 'GET') {
|
|
@@ -74,7 +78,21 @@ async function callInvitesApi(action: string, params: Record<string, any> = {},
|
|
|
74
78
|
})
|
|
75
79
|
return res.json()
|
|
76
80
|
}
|
|
77
|
-
|
|
81
|
+
// CIL[END chunk_id="InviteManager_callinvitesapi_1783927912"]
|
|
82
|
+
// CIL[BEGIN chunk_id="InviteManager_derivedisplaystatus_1783927912" type="function" identity="deriveDisplayStatus" parent="none"]
|
|
83
|
+
// CIL[DOC-MACRO purpose="Convert invite status to human-readable display text"]
|
|
84
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Map internal status codes to user-friendly labels"]
|
|
85
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[\".framework/src/pages/admin/RolesPage.tsx\",\"custom/apps/cortex/functions/custom_cil-embeddings.ts\",\".framework/functions/_shared/schema-utils.ts\",\"custom/apps/portal/pages/ContentPage.tsx\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"\\\"]"]
|
|
86
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Display status string" errors="none" side_effects="none"]
|
|
87
|
+
// CIL[DOC-MICRO logic_summary="Handles special cases like expiration, blocking, and invite vs access request" notable_decisions="[]"]
|
|
88
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
89
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
90
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 1. Direct calls: 0. Related files: .framework/src/pages/admin/RolesPage.tsx, custom/apps/cortex/functions/custom_cil-embeddings.ts, .framework/functions/_shared/schema-utils.ts, custom/apps/portal/pages/ContentPage.tsx, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, \."]
|
|
91
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
|
|
92
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
93
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
94
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
95
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
78
96
|
function deriveDisplayStatus(row: InviteRow): string {
|
|
79
97
|
if (row.blocked_at) return 'blocked'
|
|
80
98
|
if (row.status === 'inactive') return 'revoked'
|
|
@@ -87,7 +105,21 @@ function deriveDisplayStatus(row: InviteRow): string {
|
|
|
87
105
|
}
|
|
88
106
|
return row.status
|
|
89
107
|
}
|
|
90
|
-
|
|
108
|
+
// CIL[END chunk_id="InviteManager_derivedisplaystatus_1783927912"]
|
|
109
|
+
// CIL[BEGIN chunk_id="InviteManager_statusclasses_1783927912" type="constant" identity="STATUS_CLASSES" parent="none"]
|
|
110
|
+
// CIL[DOC-MACRO purpose="Define CSS classes for different invite status colors"]
|
|
111
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide styling mappings for status badge components"]
|
|
112
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[\".framework/src/pages/admin/RolesPage.tsx\",\".framework/functions/_shared/principal.ts\",\".framework/src/pages/admin/IntegrationsPage.tsx\",\".framework/functions/_shared/schema-utils.ts\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
|
|
113
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="CSS class mapping object" errors="none" side_effects="none"]
|
|
114
|
+
// CIL[DOC-MICRO logic_summary="Maps status strings to Tailwind color classes for consistent styling" notable_decisions="[]"]
|
|
115
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
116
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
117
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 0. Direct calls: 0. Related files: .framework/src/pages/admin/RolesPage.tsx, .framework/functions/_shared/principal.ts, .framework/src/pages/admin/IntegrationsPage.tsx, .framework/functions/_shared/schema-utils.ts, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
|
|
118
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
119
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
120
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
121
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
122
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
91
123
|
const STATUS_CLASSES: Record<string, string> = {
|
|
92
124
|
pending: 'bg-yellow-100 text-yellow-800',
|
|
93
125
|
'pending approval': 'bg-blue-100 text-blue-800',
|
|
@@ -97,7 +129,21 @@ const STATUS_CLASSES: Record<string, string> = {
|
|
|
97
129
|
blocked: 'bg-red-100 text-red-800',
|
|
98
130
|
revoked: 'bg-slate-100 text-slate-500',
|
|
99
131
|
}
|
|
100
|
-
|
|
132
|
+
// CIL[END chunk_id="InviteManager_statusclasses_1783927912"]
|
|
133
|
+
// CIL[BEGIN chunk_id="InviteManager_timeuntil_1783927912" type="function" identity="timeUntil" parent="none"]
|
|
134
|
+
// CIL[DOC-MACRO purpose="Calculate human-readable time until expiration from ISO date"]
|
|
135
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Format time remaining as days or hours until expiry"]
|
|
136
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[\".framework/functions/_shared/schema-utils.ts\",\"\\\"]"]
|
|
137
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Time remaining string" errors="none" side_effects="none"]
|
|
138
|
+
// CIL[DOC-MICRO logic_summary="Computes time difference, returns days/hours or 'expired' if past" notable_decisions="[]"]
|
|
139
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
140
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
141
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 1. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, \."]
|
|
142
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 1. Total affected: 1."]
|
|
143
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
144
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
145
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
146
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
101
147
|
function timeUntil(iso: string | null): string {
|
|
102
148
|
if (!iso) return '—'
|
|
103
149
|
const diff = new Date(iso).getTime() - Date.now()
|
|
@@ -107,9 +153,21 @@ function timeUntil(iso: string | null): string {
|
|
|
107
153
|
if (days > 0) return `${days}d`
|
|
108
154
|
return `${hours}h`
|
|
109
155
|
}
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
|
|
156
|
+
// CIL[END chunk_id="InviteManager_timeuntil_1783927912"]
|
|
157
|
+
// CIL[BEGIN chunk_id="InviteManager_invitemanager_1783927912" type="function" identity="InviteManager" parent="none"]
|
|
158
|
+
// CIL[DOC-MACRO purpose="Manage invite creation, listing, and actions with searchable table UI"]
|
|
159
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Provide complete invite management interface with form and table"]
|
|
160
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[]"]
|
|
161
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Invite management UI" errors="API errors" side_effects="Renders UI, API calls"]
|
|
162
|
+
// CIL[DOC-MICRO logic_summary="Handles invite generation, listing, searching, sorting, and bulk actions" notable_decisions="[]"]
|
|
163
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
164
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
165
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
166
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
167
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
168
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
169
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
170
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
113
171
|
export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope }: InviteManagerProps) {
|
|
114
172
|
const [invites, setInvites] = useState<InviteRow[]>([])
|
|
115
173
|
const [loading, setLoading] = useState(true)
|
|
@@ -122,19 +180,15 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
122
180
|
const [generateError, setGenerateError] = useState('')
|
|
123
181
|
const [copiedId, setCopiedId] = useState<string | null>(null)
|
|
124
182
|
|
|
125
|
-
// Search / sort state
|
|
126
183
|
const [search, setSearch] = useState('')
|
|
127
184
|
const [sortKey, setSortKey] = useState<'full_name' | 'email' | 'status' | 'created_at'>('created_at')
|
|
128
185
|
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')
|
|
129
|
-
|
|
130
|
-
// Keep selectedRoleSlug in sync if allowedRoles changes
|
|
131
186
|
useEffect(() => {
|
|
132
187
|
if (!allowedRoles.find(r => r.slug === selectedRoleSlug)) {
|
|
133
188
|
setSelectedRoleSlug(allowedRoles[0]?.slug ?? '')
|
|
134
189
|
}
|
|
135
190
|
}, [allowedRoles, selectedRoleSlug])
|
|
136
191
|
|
|
137
|
-
// ── Load invites ──────────────────────────────────────────────────────────
|
|
138
192
|
const loadInvites = useCallback(async () => {
|
|
139
193
|
setLoading(true)
|
|
140
194
|
setError('')
|
|
@@ -153,7 +207,6 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
153
207
|
|
|
154
208
|
useEffect(() => { loadInvites() }, [loadInvites])
|
|
155
209
|
|
|
156
|
-
// ── Filtered + sorted list ─────────────────────────────────────────────────
|
|
157
210
|
const filteredInvites = useMemo(() => {
|
|
158
211
|
const q = search.toLowerCase()
|
|
159
212
|
const filtered = q
|
|
@@ -185,7 +238,6 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
185
238
|
}
|
|
186
239
|
}
|
|
187
240
|
|
|
188
|
-
// ── Generate invite ────────────────────────────────────────────────────────
|
|
189
241
|
const handleGenerate = async (e: React.FormEvent) => {
|
|
190
242
|
e.preventDefault()
|
|
191
243
|
if (!newEmail.trim() || !accountId) return
|
|
@@ -208,7 +260,6 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
208
260
|
return
|
|
209
261
|
}
|
|
210
262
|
|
|
211
|
-
// Copy URL to clipboard automatically
|
|
212
263
|
if (result.data?.invite_url) {
|
|
213
264
|
navigator.clipboard.writeText(result.data.invite_url).catch(() => {})
|
|
214
265
|
}
|
|
@@ -218,7 +269,6 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
218
269
|
await loadInvites()
|
|
219
270
|
}
|
|
220
271
|
|
|
221
|
-
// ── Reinvite (issues new token, copies URL) ────────────────────────────────
|
|
222
272
|
const handleReinvite = async (personId: string) => {
|
|
223
273
|
const result = await callInvitesApi('reinvite', {
|
|
224
274
|
person_id: personId,
|
|
@@ -236,7 +286,6 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
236
286
|
}
|
|
237
287
|
}
|
|
238
288
|
|
|
239
|
-
// ── Generic action (revoke, approve, deny, block) ─────────────────────────
|
|
240
289
|
const handleAction = async (action: string, personId: string) => {
|
|
241
290
|
const result = await callInvitesApi(action, { person_id: personId }, 'POST')
|
|
242
291
|
if (result.error) {
|
|
@@ -246,7 +295,6 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
246
295
|
}
|
|
247
296
|
}
|
|
248
297
|
|
|
249
|
-
// ── Render ─────────────────────────────────────────────────────────────────
|
|
250
298
|
const canGenerate = !!accountId || scope === 'system'
|
|
251
299
|
const showRolePicker = allowedRoles.length > 1
|
|
252
300
|
|
|
@@ -508,9 +556,21 @@ export function InviteManager({ accountId, allowedRoles, roleSlugsFilter, scope
|
|
|
508
556
|
</div>
|
|
509
557
|
)
|
|
510
558
|
}
|
|
511
|
-
|
|
512
|
-
//
|
|
513
|
-
|
|
559
|
+
// CIL[END chunk_id="InviteManager_invitemanager_1783927912"]
|
|
560
|
+
// CIL[BEGIN chunk_id="InviteManager_sortth_1783927912" type="function" identity="SortTh" parent="none"]
|
|
561
|
+
// CIL[DOC-MACRO purpose="Render sortable table header with sort direction indicator"]
|
|
562
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Create clickable table header with visual sort state"]
|
|
563
|
+
// CIL[DOC-CONTEXT module="invite-manager" layer="frontend-component" related_files="[]"]
|
|
564
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="Table header element" errors="none" side_effects="Renders UI, calls onSort"]
|
|
565
|
+
// CIL[DOC-MICRO logic_summary="Shows sort arrows and handles click events for column sorting" notable_decisions="[]"]
|
|
566
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
567
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
568
|
+
// CIL[DOC-VECTOR type="context" content="Layer: frontend-component. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
569
|
+
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
570
|
+
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
571
|
+
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
572
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
573
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
514
574
|
function SortTh({
|
|
515
575
|
label, col, current, dir, onSort
|
|
516
576
|
}: {
|
|
@@ -531,3 +591,4 @@ function SortTh({
|
|
|
531
591
|
</th>
|
|
532
592
|
)
|
|
533
593
|
}
|
|
594
|
+
// CIL[END chunk_id="InviteManager_sortth_1783927912"]
|