@stigmer/react 3.2.3 → 3.4.0
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/agent/steps/ReviewStep.d.ts.map +1 -1
- package/agent/steps/ReviewStep.js +2 -3
- package/agent/steps/ReviewStep.js.map +1 -1
- package/billing/index.d.ts.map +1 -1
- package/billing/index.js +4 -0
- package/billing/index.js.map +1 -1
- package/channel/AgentChannelsPanel.d.ts.map +1 -1
- package/channel/AgentChannelsPanel.js +11 -5
- package/channel/AgentChannelsPanel.js.map +1 -1
- package/composer/SessionComposer.d.ts +1 -1
- package/cursor-accounts/CursorAccountEditor.d.ts +34 -0
- package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountEditor.js +67 -0
- package/cursor-accounts/CursorAccountEditor.js.map +1 -0
- package/cursor-accounts/CursorAccountsAccessNotice.d.ts +11 -0
- package/cursor-accounts/CursorAccountsAccessNotice.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountsAccessNotice.js +14 -0
- package/cursor-accounts/CursorAccountsAccessNotice.js.map +1 -0
- package/cursor-accounts/CursorAccountsConsole.d.ts +32 -0
- package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountsConsole.js +169 -0
- package/cursor-accounts/CursorAccountsConsole.js.map +1 -0
- package/cursor-accounts/MemberCoverageTable.d.ts +29 -0
- package/cursor-accounts/MemberCoverageTable.d.ts.map +1 -0
- package/cursor-accounts/MemberCoverageTable.js +150 -0
- package/cursor-accounts/MemberCoverageTable.js.map +1 -0
- package/cursor-accounts/MemberKeysPanel.d.ts +25 -0
- package/cursor-accounts/MemberKeysPanel.d.ts.map +1 -0
- package/cursor-accounts/MemberKeysPanel.js +115 -0
- package/cursor-accounts/MemberKeysPanel.js.map +1 -0
- package/cursor-accounts/badges.d.ts +9 -0
- package/cursor-accounts/badges.d.ts.map +1 -0
- package/cursor-accounts/badges.js +10 -0
- package/cursor-accounts/badges.js.map +1 -0
- package/cursor-accounts/cursor-account-coverage.d.ts +41 -0
- package/cursor-accounts/cursor-account-coverage.d.ts.map +1 -0
- package/cursor-accounts/cursor-account-coverage.js +26 -0
- package/cursor-accounts/cursor-account-coverage.js.map +1 -0
- package/cursor-accounts/cursor-account-format.d.ts +23 -0
- package/cursor-accounts/cursor-account-format.d.ts.map +1 -0
- package/cursor-accounts/cursor-account-format.js +41 -0
- package/cursor-accounts/cursor-account-format.js.map +1 -0
- package/cursor-accounts/index.d.ts +18 -0
- package/cursor-accounts/index.d.ts.map +1 -0
- package/cursor-accounts/index.js +13 -0
- package/cursor-accounts/index.js.map +1 -0
- package/cursor-accounts/useCursorAccountView.d.ts +30 -0
- package/cursor-accounts/useCursorAccountView.d.ts.map +1 -0
- package/cursor-accounts/useCursorAccountView.js +25 -0
- package/cursor-accounts/useCursorAccountView.js.map +1 -0
- package/cursor-accounts/useCursorAccounts.d.ts +33 -0
- package/cursor-accounts/useCursorAccounts.d.ts.map +1 -0
- package/cursor-accounts/useCursorAccounts.js +25 -0
- package/cursor-accounts/useCursorAccounts.js.map +1 -0
- package/cursor-accounts/useCursorMemberKeyActions.d.ts +49 -0
- package/cursor-accounts/useCursorMemberKeyActions.d.ts.map +1 -0
- package/cursor-accounts/useCursorMemberKeyActions.js +38 -0
- package/cursor-accounts/useCursorMemberKeyActions.js.map +1 -0
- package/cursor-accounts/useDeleteCursorAccount.d.ts +30 -0
- package/cursor-accounts/useDeleteCursorAccount.d.ts.map +1 -0
- package/cursor-accounts/useDeleteCursorAccount.js +32 -0
- package/cursor-accounts/useDeleteCursorAccount.js.map +1 -0
- package/cursor-accounts/useSyncCursorAccount.d.ts +23 -0
- package/cursor-accounts/useSyncCursorAccount.d.ts.map +1 -0
- package/cursor-accounts/useSyncCursorAccount.js +31 -0
- package/cursor-accounts/useSyncCursorAccount.js.map +1 -0
- package/cursor-accounts/useUpsertCursorAccount.d.ts +26 -0
- package/cursor-accounts/useUpsertCursorAccount.d.ts.map +1 -0
- package/cursor-accounts/useUpsertCursorAccount.js +34 -0
- package/cursor-accounts/useUpsertCursorAccount.js.map +1 -0
- package/datastore/CollectionRecordsBrowser.d.ts +34 -0
- package/datastore/CollectionRecordsBrowser.d.ts.map +1 -0
- package/datastore/CollectionRecordsBrowser.js +223 -0
- package/datastore/CollectionRecordsBrowser.js.map +1 -0
- package/datastore/CollectionSchemaView.d.ts +29 -0
- package/datastore/CollectionSchemaView.d.ts.map +1 -0
- package/datastore/CollectionSchemaView.js +93 -0
- package/datastore/CollectionSchemaView.js.map +1 -0
- package/datastore/DatastoreDetailView.d.ts +44 -0
- package/datastore/DatastoreDetailView.d.ts.map +1 -0
- package/datastore/DatastoreDetailView.js +76 -0
- package/datastore/DatastoreDetailView.js.map +1 -0
- package/datastore/DatastoreSyncReport.d.ts +19 -0
- package/datastore/DatastoreSyncReport.d.ts.map +1 -0
- package/datastore/DatastoreSyncReport.js +45 -0
- package/datastore/DatastoreSyncReport.js.map +1 -0
- package/datastore/DeleteDatastoreDialog.d.ts +35 -0
- package/datastore/DeleteDatastoreDialog.d.ts.map +1 -0
- package/datastore/DeleteDatastoreDialog.js +90 -0
- package/datastore/DeleteDatastoreDialog.js.map +1 -0
- package/datastore/FieldValueControl.d.ts +55 -0
- package/datastore/FieldValueControl.d.ts.map +1 -0
- package/datastore/FieldValueControl.js +138 -0
- package/datastore/FieldValueControl.js.map +1 -0
- package/datastore/RecordFilterBuilder.d.ts +37 -0
- package/datastore/RecordFilterBuilder.d.ts.map +1 -0
- package/datastore/RecordFilterBuilder.js +122 -0
- package/datastore/RecordFilterBuilder.js.map +1 -0
- package/datastore/RecordFormPanel.d.ts +45 -0
- package/datastore/RecordFormPanel.d.ts.map +1 -0
- package/datastore/RecordFormPanel.js +215 -0
- package/datastore/RecordFormPanel.js.map +1 -0
- package/datastore/index.d.ts +43 -0
- package/datastore/index.d.ts.map +1 -0
- package/datastore/index.js +22 -0
- package/datastore/index.js.map +1 -0
- package/datastore/recordFilter.d.ts +62 -0
- package/datastore/recordFilter.d.ts.map +1 -0
- package/datastore/recordFilter.js +104 -0
- package/datastore/recordFilter.js.map +1 -0
- package/datastore/recordValues.d.ts +85 -0
- package/datastore/recordValues.d.ts.map +1 -0
- package/datastore/recordValues.js +282 -0
- package/datastore/recordValues.js.map +1 -0
- package/datastore/useDatastore.d.ts +39 -0
- package/datastore/useDatastore.d.ts.map +1 -0
- package/datastore/useDatastore.js +44 -0
- package/datastore/useDatastore.js.map +1 -0
- package/datastore/useDatastoreCount.d.ts +48 -0
- package/datastore/useDatastoreCount.d.ts.map +1 -0
- package/datastore/useDatastoreCount.js +27 -0
- package/datastore/useDatastoreCount.js.map +1 -0
- package/datastore/useDatastoreDescription.d.ts +54 -0
- package/datastore/useDatastoreDescription.d.ts.map +1 -0
- package/datastore/useDatastoreDescription.js +50 -0
- package/datastore/useDatastoreDescription.js.map +1 -0
- package/datastore/useDatastoreList.d.ts +57 -0
- package/datastore/useDatastoreList.d.ts.map +1 -0
- package/datastore/useDatastoreList.js +29 -0
- package/datastore/useDatastoreList.js.map +1 -0
- package/datastore/useDatastoreSearch.d.ts +19 -0
- package/datastore/useDatastoreSearch.d.ts.map +1 -0
- package/datastore/useDatastoreSearch.js +22 -0
- package/datastore/useDatastoreSearch.js.map +1 -0
- package/datastore/useDeleteDatastore.d.ts +53 -0
- package/datastore/useDeleteDatastore.d.ts.map +1 -0
- package/datastore/useDeleteDatastore.js +40 -0
- package/datastore/useDeleteDatastore.js.map +1 -0
- package/datastore/useDeleteRecord.d.ts +34 -0
- package/datastore/useDeleteRecord.d.ts.map +1 -0
- package/datastore/useDeleteRecord.js +43 -0
- package/datastore/useDeleteRecord.js.map +1 -0
- package/datastore/useInsertRecord.d.ts +50 -0
- package/datastore/useInsertRecord.d.ts.map +1 -0
- package/datastore/useInsertRecord.js +55 -0
- package/datastore/useInsertRecord.js.map +1 -0
- package/datastore/useRecordCollection.d.ts +104 -0
- package/datastore/useRecordCollection.d.ts.map +1 -0
- package/datastore/useRecordCollection.js +136 -0
- package/datastore/useRecordCollection.js.map +1 -0
- package/datastore/useRecordList.d.ts +66 -0
- package/datastore/useRecordList.d.ts.map +1 -0
- package/datastore/useRecordList.js +58 -0
- package/datastore/useRecordList.js.map +1 -0
- package/datastore/useUpdateRecord.d.ts +52 -0
- package/datastore/useUpdateRecord.d.ts.map +1 -0
- package/datastore/useUpdateRecord.js +55 -0
- package/datastore/useUpdateRecord.js.map +1 -0
- package/environment/EnvironmentListPanel.d.ts.map +1 -1
- package/environment/EnvironmentListPanel.js +12 -7
- package/environment/EnvironmentListPanel.js.map +1 -1
- package/execution/ExecutionProgress.d.ts.map +1 -1
- package/execution/ExecutionProgress.js +13 -4
- package/execution/ExecutionProgress.js.map +1 -1
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +10 -2
- package/execution/MessageThread.js.map +1 -1
- package/execution/useCreateAgentExecution.d.ts +31 -1
- package/execution/useCreateAgentExecution.d.ts.map +1 -1
- package/execution/useCreateAgentExecution.js +2 -0
- package/execution/useCreateAgentExecution.js.map +1 -1
- package/iam-policy/index.d.ts +1 -1
- package/iam-policy/index.d.ts.map +1 -1
- package/iam-policy/index.js.map +1 -1
- package/iam-policy/useCheckPermission.d.ts +32 -11
- package/iam-policy/useCheckPermission.d.ts.map +1 -1
- package/iam-policy/useCheckPermission.js +24 -19
- package/iam-policy/useCheckPermission.js.map +1 -1
- package/index.d.ts +12 -4
- package/index.d.ts.map +1 -1
- package/index.js +18 -3
- package/index.js.map +1 -1
- package/internal/form-primitives.d.ts +10 -0
- package/internal/form-primitives.d.ts.map +1 -0
- package/internal/form-primitives.js +15 -0
- package/internal/form-primitives.js.map +1 -0
- package/library/index.d.ts +0 -7
- package/library/index.d.ts.map +1 -1
- package/library/index.js +0 -4
- package/library/index.js.map +1 -1
- package/library/useApplyResource.d.ts +12 -12
- package/library/useApplyResource.d.ts.map +1 -1
- package/library/useApplyResource.js +16 -25
- package/library/useApplyResource.js.map +1 -1
- package/library/useExportResource.d.ts +13 -9
- package/library/useExportResource.d.ts.map +1 -1
- package/library/useExportResource.js +18 -36
- package/library/useExportResource.js.map +1 -1
- package/manifest/ApplyManifestDialog.d.ts +48 -0
- package/manifest/ApplyManifestDialog.d.ts.map +1 -0
- package/manifest/ApplyManifestDialog.js +135 -0
- package/manifest/ApplyManifestDialog.js.map +1 -0
- package/manifest/EditResourceYamlDialog.d.ts +51 -0
- package/manifest/EditResourceYamlDialog.d.ts.map +1 -0
- package/manifest/EditResourceYamlDialog.js +104 -0
- package/manifest/EditResourceYamlDialog.js.map +1 -0
- package/manifest/RedactedSecretsNotice.d.ts +14 -0
- package/manifest/RedactedSecretsNotice.d.ts.map +1 -0
- package/manifest/RedactedSecretsNotice.js +14 -0
- package/manifest/RedactedSecretsNotice.js.map +1 -0
- package/manifest/YamlEditor.d.ts +44 -0
- package/manifest/YamlEditor.d.ts.map +1 -0
- package/manifest/YamlEditor.js +216 -0
- package/manifest/YamlEditor.js.map +1 -0
- package/manifest/index.d.ts +13 -0
- package/manifest/index.d.ts.map +1 -0
- package/manifest/index.js +13 -0
- package/manifest/index.js.map +1 -0
- package/manifest/useApplyManifest.d.ts +82 -0
- package/manifest/useApplyManifest.d.ts.map +1 -0
- package/manifest/useApplyManifest.js +180 -0
- package/manifest/useApplyManifest.js.map +1 -0
- package/manifest/useEditResourceYaml.d.ts +106 -0
- package/manifest/useEditResourceYaml.d.ts.map +1 -0
- package/manifest/useEditResourceYaml.js +168 -0
- package/manifest/useEditResourceYaml.js.map +1 -0
- package/mcp-server/steps/ReviewStep.d.ts.map +1 -1
- package/mcp-server/steps/ReviewStep.js +2 -3
- package/mcp-server/steps/ReviewStep.js.map +1 -1
- package/package.json +4 -4
- package/pricing-governance/BaselineEditor.d.ts +9 -0
- package/pricing-governance/BaselineEditor.d.ts.map +1 -0
- package/pricing-governance/BaselineEditor.js +270 -0
- package/pricing-governance/BaselineEditor.js.map +1 -0
- package/pricing-governance/ModelCatalogPanel.d.ts +28 -0
- package/pricing-governance/ModelCatalogPanel.d.ts.map +1 -0
- package/pricing-governance/ModelCatalogPanel.js +102 -0
- package/pricing-governance/ModelCatalogPanel.js.map +1 -0
- package/pricing-governance/ModelGovernanceDetail.d.ts +8 -0
- package/pricing-governance/ModelGovernanceDetail.d.ts.map +1 -0
- package/pricing-governance/ModelGovernanceDetail.js +64 -0
- package/pricing-governance/ModelGovernanceDetail.js.map +1 -0
- package/pricing-governance/OperatorAccessNotice.d.ts +12 -0
- package/pricing-governance/OperatorAccessNotice.d.ts.map +1 -0
- package/pricing-governance/OperatorAccessNotice.js +15 -0
- package/pricing-governance/OperatorAccessNotice.js.map +1 -0
- package/pricing-governance/PricingGovernanceConsole.d.ts +57 -0
- package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -0
- package/pricing-governance/PricingGovernanceConsole.js +164 -0
- package/pricing-governance/PricingGovernanceConsole.js.map +1 -0
- package/pricing-governance/PricingGovernancePanel.d.ts +26 -0
- package/pricing-governance/PricingGovernancePanel.d.ts.map +1 -0
- package/pricing-governance/PricingGovernancePanel.js +64 -0
- package/pricing-governance/PricingGovernancePanel.js.map +1 -0
- package/pricing-governance/RetireConfirm.d.ts +9 -0
- package/pricing-governance/RetireConfirm.d.ts.map +1 -0
- package/pricing-governance/RetireConfirm.js +19 -0
- package/pricing-governance/RetireConfirm.js.map +1 -0
- package/pricing-governance/governance-primitives.d.ts +33 -0
- package/pricing-governance/governance-primitives.d.ts.map +1 -0
- package/pricing-governance/governance-primitives.js +43 -0
- package/pricing-governance/governance-primitives.js.map +1 -0
- package/pricing-governance/index.d.ts +19 -0
- package/pricing-governance/index.d.ts.map +1 -0
- package/pricing-governance/index.js +20 -0
- package/pricing-governance/index.js.map +1 -0
- package/pricing-governance/pricing-format.d.ts +12 -0
- package/pricing-governance/pricing-format.d.ts.map +1 -0
- package/pricing-governance/pricing-format.js +50 -0
- package/pricing-governance/pricing-format.js.map +1 -0
- package/pricing-governance/useDecidePricingOverride.d.ts +46 -0
- package/pricing-governance/useDecidePricingOverride.d.ts.map +1 -0
- package/pricing-governance/useDecidePricingOverride.js +44 -0
- package/pricing-governance/useDecidePricingOverride.js.map +1 -0
- package/pricing-governance/useModelGovernanceView.d.ts +103 -0
- package/pricing-governance/useModelGovernanceView.d.ts.map +1 -0
- package/pricing-governance/useModelGovernanceView.js +144 -0
- package/pricing-governance/useModelGovernanceView.js.map +1 -0
- package/pricing-governance/useModelPricingBaselines.d.ts +40 -0
- package/pricing-governance/useModelPricingBaselines.d.ts.map +1 -0
- package/pricing-governance/useModelPricingBaselines.js +32 -0
- package/pricing-governance/useModelPricingBaselines.js.map +1 -0
- package/pricing-governance/usePricingGovernance.d.ts +39 -0
- package/pricing-governance/usePricingGovernance.d.ts.map +1 -0
- package/pricing-governance/usePricingGovernance.js +31 -0
- package/pricing-governance/usePricingGovernance.js.map +1 -0
- package/pricing-governance/useRetireModelPricingBaseline.d.ts +31 -0
- package/pricing-governance/useRetireModelPricingBaseline.d.ts.map +1 -0
- package/pricing-governance/useRetireModelPricingBaseline.js +36 -0
- package/pricing-governance/useRetireModelPricingBaseline.js.map +1 -0
- package/pricing-governance/useUpsertModelPricingBaseline.d.ts +38 -0
- package/pricing-governance/useUpsertModelPricingBaseline.d.ts.map +1 -0
- package/pricing-governance/useUpsertModelPricingBaseline.js +37 -0
- package/pricing-governance/useUpsertModelPricingBaseline.js.map +1 -0
- package/resource-creation/templates/workflow-templates.js +4 -4
- package/session/useCreateSession.d.ts +28 -0
- package/session/useCreateSession.d.ts.map +1 -1
- package/session/useCreateSession.js +2 -1
- package/session/useCreateSession.js.map +1 -1
- package/session/useEditSessionPrep.js +3 -3
- package/session/useEditSessionPrep.js.map +1 -1
- package/session/useNewSessionFlow.d.ts +30 -0
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +7 -1
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useUpdateSession.d.ts +29 -10
- package/session/useUpdateSession.d.ts.map +1 -1
- package/session/useUpdateSession.js +29 -10
- package/session/useUpdateSession.js.map +1 -1
- package/settings/index.d.ts +2 -1
- package/settings/index.d.ts.map +1 -1
- package/settings/index.js +2 -1
- package/settings/index.js.map +1 -1
- package/settings/settings-nav.d.ts +22 -0
- package/settings/settings-nav.d.ts.map +1 -1
- package/settings/settings-nav.js +32 -1
- package/settings/settings-nav.js.map +1 -1
- package/settings/useSettingsNavGroups.d.ts +29 -0
- package/settings/useSettingsNavGroups.d.ts.map +1 -0
- package/settings/useSettingsNavGroups.js +61 -0
- package/settings/useSettingsNavGroups.js.map +1 -0
- package/src/agent/steps/ReviewStep.tsx +2 -3
- package/src/billing/index.ts +5 -0
- package/src/channel/AgentChannelsPanel.tsx +27 -1
- package/src/composer/SessionComposer.tsx +1 -1
- package/src/cursor-accounts/CursorAccountEditor.tsx +229 -0
- package/src/cursor-accounts/CursorAccountsAccessNotice.tsx +36 -0
- package/src/cursor-accounts/CursorAccountsConsole.tsx +454 -0
- package/src/cursor-accounts/MemberCoverageTable.tsx +439 -0
- package/src/cursor-accounts/MemberKeysPanel.tsx +278 -0
- package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +680 -0
- package/src/cursor-accounts/__tests__/cursor-account-coverage.test.ts +73 -0
- package/src/cursor-accounts/badges.tsx +26 -0
- package/src/cursor-accounts/cursor-account-coverage.ts +71 -0
- package/src/cursor-accounts/cursor-account-format.ts +45 -0
- package/src/cursor-accounts/index.ts +29 -0
- package/src/cursor-accounts/useCursorAccountView.ts +49 -0
- package/src/cursor-accounts/useCursorAccounts.ts +49 -0
- package/src/cursor-accounts/useCursorMemberKeyActions.ts +106 -0
- package/src/cursor-accounts/useDeleteCursorAccount.ts +62 -0
- package/src/cursor-accounts/useSyncCursorAccount.ts +54 -0
- package/src/cursor-accounts/useUpsertCursorAccount.ts +57 -0
- package/src/datastore/CollectionRecordsBrowser.tsx +570 -0
- package/src/datastore/CollectionSchemaView.tsx +247 -0
- package/src/datastore/DatastoreDetailView.tsx +201 -0
- package/src/datastore/DatastoreSyncReport.tsx +105 -0
- package/src/datastore/DeleteDatastoreDialog.tsx +202 -0
- package/src/datastore/FieldValueControl.tsx +289 -0
- package/src/datastore/RecordFilterBuilder.tsx +422 -0
- package/src/datastore/RecordFormPanel.tsx +432 -0
- package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +245 -0
- package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +133 -0
- package/src/datastore/__tests__/FieldValueControl.test.tsx +160 -0
- package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +155 -0
- package/src/datastore/__tests__/RecordFormPanel.test.tsx +227 -0
- package/src/datastore/__tests__/recordFilter.test.ts +169 -0
- package/src/datastore/__tests__/recordMutations.test.tsx +195 -0
- package/src/datastore/__tests__/recordValues.test.ts +359 -0
- package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +142 -0
- package/src/datastore/__tests__/useDatastoreDescription.test.tsx +143 -0
- package/src/datastore/__tests__/useRecordCollection.test.tsx +250 -0
- package/src/datastore/__tests__/useRecordList.test.tsx +85 -0
- package/src/datastore/index.ts +111 -0
- package/src/datastore/recordFilter.ts +154 -0
- package/src/datastore/recordValues.ts +327 -0
- package/src/datastore/useDatastore.ts +67 -0
- package/src/datastore/useDatastoreCount.ts +67 -0
- package/src/datastore/useDatastoreDescription.ts +90 -0
- package/src/datastore/useDatastoreList.ts +79 -0
- package/src/datastore/useDatastoreSearch.ts +39 -0
- package/src/datastore/useDeleteDatastore.ts +87 -0
- package/src/datastore/useDeleteRecord.ts +77 -0
- package/src/datastore/useInsertRecord.ts +92 -0
- package/src/datastore/useRecordCollection.ts +256 -0
- package/src/datastore/useRecordList.ts +131 -0
- package/src/datastore/useUpdateRecord.ts +95 -0
- package/src/environment/EnvironmentListPanel.tsx +24 -0
- package/src/execution/ExecutionProgress.tsx +14 -4
- package/src/execution/MessageThread.tsx +10 -2
- package/src/execution/__tests__/ExecutionProgress.test.tsx +67 -0
- package/src/execution/__tests__/MessageThread.test.tsx +44 -0
- package/src/execution/__tests__/useArtifactInspection.test.tsx +12 -2
- package/src/execution/__tests__/useCreateAgentExecution.test.tsx +86 -0
- package/src/execution/useCreateAgentExecution.ts +41 -6
- package/src/iam-policy/__tests__/useCheckPermission.test.tsx +221 -0
- package/src/iam-policy/index.ts +1 -0
- package/src/iam-policy/useCheckPermission.ts +45 -19
- package/src/index.ts +172 -14
- package/src/internal/form-primitives.tsx +40 -0
- package/src/library/index.ts +0 -20
- package/src/library/useApplyResource.ts +27 -34
- package/src/library/useExportResource.ts +21 -40
- package/src/manifest/ApplyManifestDialog.tsx +315 -0
- package/src/manifest/EditResourceYamlDialog.tsx +265 -0
- package/src/manifest/RedactedSecretsNotice.tsx +30 -0
- package/src/manifest/YamlEditor.tsx +272 -0
- package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +118 -0
- package/src/manifest/__tests__/useApplyManifest.test.tsx +237 -0
- package/src/manifest/__tests__/useEditResourceYaml.test.tsx +252 -0
- package/src/manifest/index.ts +33 -0
- package/src/manifest/useApplyManifest.ts +270 -0
- package/src/manifest/useEditResourceYaml.ts +273 -0
- package/src/mcp-server/steps/ReviewStep.tsx +2 -3
- package/src/pricing-governance/BaselineEditor.tsx +652 -0
- package/src/pricing-governance/ModelCatalogPanel.tsx +283 -0
- package/src/pricing-governance/ModelGovernanceDetail.tsx +289 -0
- package/src/pricing-governance/OperatorAccessNotice.tsx +32 -0
- package/src/pricing-governance/PricingGovernanceConsole.tsx +465 -0
- package/src/pricing-governance/PricingGovernancePanel.tsx +166 -0
- package/src/pricing-governance/RetireConfirm.tsx +82 -0
- package/src/pricing-governance/__tests__/ModelCatalogPanel.test.tsx +253 -0
- package/src/pricing-governance/__tests__/PricingGovernanceConsole.test.tsx +410 -0
- package/src/pricing-governance/__tests__/useModelGovernanceView.test.tsx +308 -0
- package/src/pricing-governance/governance-primitives.tsx +133 -0
- package/src/pricing-governance/index.ts +50 -0
- package/src/pricing-governance/pricing-format.ts +53 -0
- package/src/pricing-governance/useDecidePricingOverride.ts +78 -0
- package/src/pricing-governance/useModelGovernanceView.ts +290 -0
- package/src/pricing-governance/useModelPricingBaselines.ts +69 -0
- package/src/pricing-governance/usePricingGovernance.ts +57 -0
- package/src/pricing-governance/useRetireModelPricingBaseline.ts +65 -0
- package/src/pricing-governance/useUpsertModelPricingBaseline.ts +72 -0
- package/src/resource-creation/templates/workflow-templates.ts +4 -4
- package/src/session/__tests__/useCreateSession.test.tsx +94 -0
- package/src/session/__tests__/useNewSessionFlow.test.tsx +33 -0
- package/src/session/useCreateSession.ts +30 -0
- package/src/session/useEditSessionPrep.ts +3 -3
- package/src/session/useNewSessionFlow.ts +45 -1
- package/src/session/useUpdateSession.ts +29 -10
- package/src/settings/__tests__/useSettingsNavGroups.test.tsx +138 -0
- package/src/settings/index.ts +5 -1
- package/src/settings/settings-nav.ts +43 -0
- package/src/settings/useSettingsNavGroups.ts +81 -0
- package/src/workflow/WorkflowYamlEditor.tsx +6 -270
- package/styles.css +1 -1
- package/workflow/CanvasTransitionEdge.d.ts +1 -1
- package/workflow/WorkflowYamlEditor.d.ts +2 -42
- package/workflow/WorkflowYamlEditor.d.ts.map +1 -1
- package/workflow/WorkflowYamlEditor.js +5 -214
- package/workflow/WorkflowYamlEditor.js.map +1 -1
- package/library/ImportResourceDialog.d.ts +0 -43
- package/library/ImportResourceDialog.d.ts.map +0 -1
- package/library/ImportResourceDialog.js +0 -90
- package/library/ImportResourceDialog.js.map +0 -1
- package/library/parse-resource-yaml.d.ts +0 -63
- package/library/parse-resource-yaml.d.ts.map +0 -1
- package/library/parse-resource-yaml.js +0 -407
- package/library/parse-resource-yaml.js.map +0 -1
- package/library/serialize-resource-yaml.d.ts +0 -103
- package/library/serialize-resource-yaml.d.ts.map +0 -1
- package/library/serialize-resource-yaml.js +0 -565
- package/library/serialize-resource-yaml.js.map +0 -1
- package/library/useImportResource.d.ts +0 -84
- package/library/useImportResource.d.ts.map +0 -1
- package/library/useImportResource.js +0 -188
- package/library/useImportResource.js.map +0 -1
- package/src/library/ImportResourceDialog.tsx +0 -227
- package/src/library/parse-resource-yaml.ts +0 -630
- package/src/library/serialize-resource-yaml.ts +0 -756
- package/src/library/useImportResource.ts +0 -253
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useMemo, useState } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
6
|
+
import { getUserMessage, isPermissionDenied } from "@stigmer/sdk";
|
|
7
|
+
import {
|
|
8
|
+
DatastoreVerb,
|
|
9
|
+
FieldType,
|
|
10
|
+
type CollectionDeclaration,
|
|
11
|
+
type DatastoreSpec,
|
|
12
|
+
} from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/spec_pb";
|
|
13
|
+
import type {
|
|
14
|
+
CollectionDescription,
|
|
15
|
+
RecordEnvelope,
|
|
16
|
+
} from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
|
|
17
|
+
import { ResourceTable } from "../resource-workbench/components/ResourceTable.js";
|
|
18
|
+
import { ConfirmDialog } from "../resource-detail/ConfirmDialog.js";
|
|
19
|
+
import { useConfirmAction } from "../resource-detail/useConfirmAction.js";
|
|
20
|
+
import { toast } from "../feedback/toast.js";
|
|
21
|
+
import { FIELD_INPUT_CLASSES } from "./FieldValueControl.js";
|
|
22
|
+
import { RecordFilterBuilder } from "./RecordFilterBuilder.js";
|
|
23
|
+
import { RecordFormPanel } from "./RecordFormPanel.js";
|
|
24
|
+
import { buildRecordFilter, type RecordConditionDraft } from "./recordFilter.js";
|
|
25
|
+
import {
|
|
26
|
+
formatFieldValue,
|
|
27
|
+
formatSystemTimestamp,
|
|
28
|
+
isSortableField,
|
|
29
|
+
} from "./recordValues.js";
|
|
30
|
+
import { useDatastoreDescription } from "./useDatastoreDescription.js";
|
|
31
|
+
import { useRecordCollection, type RecordColumnDef } from "./useRecordCollection.js";
|
|
32
|
+
import { useDeleteRecord } from "./useDeleteRecord.js";
|
|
33
|
+
import type { SortValue } from "../resource-workbench/types.js";
|
|
34
|
+
|
|
35
|
+
/** Props for {@link CollectionRecordsBrowser}. */
|
|
36
|
+
export interface CollectionRecordsBrowserProps {
|
|
37
|
+
/** Organization slug. */
|
|
38
|
+
readonly org: string;
|
|
39
|
+
/** Datastore slug. */
|
|
40
|
+
readonly datastoreSlug: string;
|
|
41
|
+
/** The datastore spec — collections and fields drive the grid columns. */
|
|
42
|
+
readonly spec: DatastoreSpec;
|
|
43
|
+
/** Additional CSS classes for the root container. */
|
|
44
|
+
readonly className?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const PAGE_SIZE = 25;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The records browser (DD-008 SD-3): collection selector, partition
|
|
51
|
+
* picker, schema-aware filter builder, typed-cell grid, RPC-paged
|
|
52
|
+
* navigation, and verb-gated write affordances — the console surface
|
|
53
|
+
* that absorbs the Supabase-dashboard capability the datastore
|
|
54
|
+
* primitive retires.
|
|
55
|
+
*
|
|
56
|
+
* Authorization is rendered as the two layers it is:
|
|
57
|
+
* - Write affordances gate on `describeDatastore`'s per-collection
|
|
58
|
+
* effective verbs (projections, never authority — the server's
|
|
59
|
+
* record layer stays the enforcer).
|
|
60
|
+
* - **The denied state is a first-class render**, driven primarily by
|
|
61
|
+
* empty access lists (deny-by-default renders as empty access, never
|
|
62
|
+
* an error) with a caught reach-level `PERMISSION_DENIED` as the
|
|
63
|
+
* defensive branch. Both show the relayable message plus operator
|
|
64
|
+
* guidance — never a silently empty grid.
|
|
65
|
+
*
|
|
66
|
+
* All visual properties flow through `--stgm-*` design tokens.
|
|
67
|
+
* Zero Console dependencies — safe for platform builder embedding.
|
|
68
|
+
*/
|
|
69
|
+
export function CollectionRecordsBrowser({
|
|
70
|
+
org,
|
|
71
|
+
datastoreSlug,
|
|
72
|
+
spec,
|
|
73
|
+
className,
|
|
74
|
+
}: CollectionRecordsBrowserProps) {
|
|
75
|
+
const collections = spec.collections;
|
|
76
|
+
const [collectionName, setCollectionName] = useState(collections[0]?.name ?? "");
|
|
77
|
+
const collection = collections.find((c) => c.name === collectionName);
|
|
78
|
+
|
|
79
|
+
const description = useDatastoreDescription(org, datastoreSlug);
|
|
80
|
+
const [partition, setPartition] = useState("default");
|
|
81
|
+
|
|
82
|
+
// Filter, sort, and page state — per collection selection.
|
|
83
|
+
const [conditions, setConditions] = useState<readonly RecordConditionDraft[]>([]);
|
|
84
|
+
const [sort, setSort] = useState<SortValue | null>(null);
|
|
85
|
+
const [page, setPage] = useState(1);
|
|
86
|
+
|
|
87
|
+
const selectCollection = useCallback((name: string) => {
|
|
88
|
+
setCollectionName(name);
|
|
89
|
+
setConditions([]);
|
|
90
|
+
setSort(null);
|
|
91
|
+
setPage(1);
|
|
92
|
+
}, []);
|
|
93
|
+
|
|
94
|
+
const selectPartition = useCallback((name: string) => {
|
|
95
|
+
setPartition(name);
|
|
96
|
+
setPage(1);
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
99
|
+
const applyConditions = useCallback((next: readonly RecordConditionDraft[]) => {
|
|
100
|
+
setConditions(next);
|
|
101
|
+
setPage(1);
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
if (collections.length === 0) {
|
|
105
|
+
return (
|
|
106
|
+
<p className={cn("px-3 py-6 text-center text-sm text-muted-foreground", className)}>
|
|
107
|
+
This datastore declares no collections.
|
|
108
|
+
</p>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (!collection) return null;
|
|
112
|
+
|
|
113
|
+
const collectionAccess = description.description?.collections.find(
|
|
114
|
+
(c) => c.name === collection.name,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<div className={cn("flex flex-col gap-3", className)}>
|
|
119
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
120
|
+
<label className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
|
121
|
+
Collection
|
|
122
|
+
<select
|
|
123
|
+
className={cn(FIELD_INPUT_CLASSES, "w-auto")}
|
|
124
|
+
value={collectionName}
|
|
125
|
+
onChange={(e) => selectCollection(e.target.value)}
|
|
126
|
+
>
|
|
127
|
+
{collections.map((c) => (
|
|
128
|
+
<option key={c.name} value={c.name}>
|
|
129
|
+
{c.name}
|
|
130
|
+
</option>
|
|
131
|
+
))}
|
|
132
|
+
</select>
|
|
133
|
+
</label>
|
|
134
|
+
<label className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
|
135
|
+
Partition
|
|
136
|
+
<select
|
|
137
|
+
className={cn(FIELD_INPUT_CLASSES, "w-auto")}
|
|
138
|
+
value={partition}
|
|
139
|
+
onChange={(e) => selectPartition(e.target.value)}
|
|
140
|
+
>
|
|
141
|
+
{description.partitions.map((p) => (
|
|
142
|
+
<option key={p} value={p}>
|
|
143
|
+
{p}
|
|
144
|
+
</option>
|
|
145
|
+
))}
|
|
146
|
+
</select>
|
|
147
|
+
</label>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<RecordsPane
|
|
151
|
+
org={org}
|
|
152
|
+
datastoreSlug={datastoreSlug}
|
|
153
|
+
collection={collection}
|
|
154
|
+
partition={partition}
|
|
155
|
+
conditions={conditions}
|
|
156
|
+
onConditionsChange={applyConditions}
|
|
157
|
+
sort={sort}
|
|
158
|
+
onSortChange={setSort}
|
|
159
|
+
page={page}
|
|
160
|
+
onPageChange={setPage}
|
|
161
|
+
access={collectionAccess}
|
|
162
|
+
describeError={description.error}
|
|
163
|
+
describeLoaded={description.description !== null}
|
|
164
|
+
/>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
// The per-collection pane: denied panel or grid
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
|
|
173
|
+
function RecordsPane({
|
|
174
|
+
org,
|
|
175
|
+
datastoreSlug,
|
|
176
|
+
collection,
|
|
177
|
+
partition,
|
|
178
|
+
conditions,
|
|
179
|
+
onConditionsChange,
|
|
180
|
+
sort,
|
|
181
|
+
onSortChange,
|
|
182
|
+
page,
|
|
183
|
+
onPageChange,
|
|
184
|
+
access,
|
|
185
|
+
describeError,
|
|
186
|
+
describeLoaded,
|
|
187
|
+
}: {
|
|
188
|
+
readonly org: string;
|
|
189
|
+
readonly datastoreSlug: string;
|
|
190
|
+
readonly collection: CollectionDeclaration;
|
|
191
|
+
readonly partition: string;
|
|
192
|
+
readonly conditions: readonly RecordConditionDraft[];
|
|
193
|
+
readonly onConditionsChange: (c: readonly RecordConditionDraft[]) => void;
|
|
194
|
+
readonly sort: SortValue | null;
|
|
195
|
+
readonly onSortChange: (s: SortValue | null) => void;
|
|
196
|
+
readonly page: number;
|
|
197
|
+
readonly onPageChange: (p: number) => void;
|
|
198
|
+
readonly access: CollectionDescription | undefined;
|
|
199
|
+
readonly describeError: Error | null;
|
|
200
|
+
readonly describeLoaded: boolean;
|
|
201
|
+
}) {
|
|
202
|
+
const verbs = useMemo(() => {
|
|
203
|
+
const set = new Set<DatastoreVerb>();
|
|
204
|
+
for (const grant of access?.access ?? []) set.add(grant.verb);
|
|
205
|
+
return set;
|
|
206
|
+
}, [access]);
|
|
207
|
+
const canRead = verbs.has(DatastoreVerb.read);
|
|
208
|
+
const canInsert = verbs.has(DatastoreVerb.insert);
|
|
209
|
+
const canUpdate = verbs.has(DatastoreVerb.update);
|
|
210
|
+
const canDelete = verbs.has(DatastoreVerb.delete);
|
|
211
|
+
|
|
212
|
+
// The caller's column-level read access (empty means every field): a
|
|
213
|
+
// field-restricted read grant returns only these fields, so the grid
|
|
214
|
+
// and the filter builder narrow to them — no permanently-empty
|
|
215
|
+
// columns, no filter the server would refuse (DD-008 invariant 2).
|
|
216
|
+
const readableFields = useMemo(
|
|
217
|
+
() => access?.access.find((a) => a.verb === DatastoreVerb.read)?.readableFields ?? [],
|
|
218
|
+
[access],
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const scope = { org, datastore: datastoreSlug, collection: collection.name, partition };
|
|
222
|
+
|
|
223
|
+
const filter = useMemo(() => buildRecordFilter(conditions), [conditions]);
|
|
224
|
+
const columns = useMemo(
|
|
225
|
+
() => buildRecordColumns(collection, readableFields),
|
|
226
|
+
[collection, readableFields],
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Fetch only once read access is confirmed — the denied panel is the
|
|
230
|
+
// primary render for deny-by-default, not a failed query.
|
|
231
|
+
const records = useRecordCollection({
|
|
232
|
+
org: describeLoaded && canRead ? org : null,
|
|
233
|
+
datastore: datastoreSlug,
|
|
234
|
+
collection: collection.name,
|
|
235
|
+
partition,
|
|
236
|
+
filter,
|
|
237
|
+
page,
|
|
238
|
+
pageSize: PAGE_SIZE,
|
|
239
|
+
sort,
|
|
240
|
+
onSortChange,
|
|
241
|
+
columns,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Row actions and write panel state.
|
|
245
|
+
const [formOpen, setFormOpen] = useState(false);
|
|
246
|
+
const [editing, setEditing] = useState<RecordEnvelope | null>(null);
|
|
247
|
+
const { confirmState, confirm, handleConfirm, handleCancel } = useConfirmAction();
|
|
248
|
+
const deleteRecord = useDeleteRecord();
|
|
249
|
+
|
|
250
|
+
const openInsert = useCallback(() => {
|
|
251
|
+
setEditing(null);
|
|
252
|
+
setFormOpen(true);
|
|
253
|
+
}, []);
|
|
254
|
+
|
|
255
|
+
const openEdit = useCallback((record: RecordEnvelope) => {
|
|
256
|
+
setEditing(record);
|
|
257
|
+
setFormOpen(true);
|
|
258
|
+
}, []);
|
|
259
|
+
|
|
260
|
+
// Deps narrowed to the specific stable callbacks used (DD-010).
|
|
261
|
+
const deleteRecordFn = deleteRecord.deleteRecord;
|
|
262
|
+
const refetchRecords = records.refetch;
|
|
263
|
+
const collectionName = collection.name;
|
|
264
|
+
const handleDelete = useCallback(
|
|
265
|
+
async (record: RecordEnvelope) => {
|
|
266
|
+
const ok = await confirm({
|
|
267
|
+
title: "Delete record?",
|
|
268
|
+
description: `Record ${record.id} will be permanently deleted.`,
|
|
269
|
+
confirmLabel: "Delete",
|
|
270
|
+
variant: "destructive",
|
|
271
|
+
});
|
|
272
|
+
if (!ok) return;
|
|
273
|
+
try {
|
|
274
|
+
await deleteRecordFn({
|
|
275
|
+
org,
|
|
276
|
+
datastore: datastoreSlug,
|
|
277
|
+
collection: collectionName,
|
|
278
|
+
partition,
|
|
279
|
+
id: record.id,
|
|
280
|
+
});
|
|
281
|
+
toast.success("Record deleted");
|
|
282
|
+
refetchRecords();
|
|
283
|
+
} catch (err) {
|
|
284
|
+
toast.error(getUserMessage(err));
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
[confirm, deleteRecordFn, refetchRecords, org, datastoreSlug, collectionName, partition],
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
// --- Denied states (DD-008 SD-3): first-class renders ---------------------
|
|
291
|
+
if (describeError && isPermissionDenied(describeError)) {
|
|
292
|
+
return <DeniedPanel message={getUserMessage(describeError)} />;
|
|
293
|
+
}
|
|
294
|
+
if (describeLoaded && !canRead) {
|
|
295
|
+
return (
|
|
296
|
+
<DeniedPanel
|
|
297
|
+
message={`You do not have record access to “${collection.name}”.`}
|
|
298
|
+
/>
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
if (records.error && isPermissionDenied(records.error)) {
|
|
302
|
+
return <DeniedPanel message={getUserMessage(records.error)} />;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const totalPages = Math.max(records.totalPages, 1);
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<div className="flex flex-col gap-3">
|
|
309
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
310
|
+
<RecordFilterBuilder
|
|
311
|
+
collection={collection}
|
|
312
|
+
readableFields={readableFields}
|
|
313
|
+
conditions={conditions}
|
|
314
|
+
onChange={onConditionsChange}
|
|
315
|
+
className="min-w-0 flex-1"
|
|
316
|
+
/>
|
|
317
|
+
{canInsert && (
|
|
318
|
+
<button
|
|
319
|
+
type="button"
|
|
320
|
+
onClick={openInsert}
|
|
321
|
+
className={cn(
|
|
322
|
+
"shrink-0 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground",
|
|
323
|
+
"hover:bg-primary-hover",
|
|
324
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
325
|
+
)}
|
|
326
|
+
>
|
|
327
|
+
Insert record
|
|
328
|
+
</button>
|
|
329
|
+
)}
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
{records.error ? (
|
|
333
|
+
<div
|
|
334
|
+
role="alert"
|
|
335
|
+
className="rounded-md border border-destructive bg-card px-3 py-2 text-sm text-destructive"
|
|
336
|
+
>
|
|
337
|
+
{getUserMessage(records.error)}
|
|
338
|
+
</div>
|
|
339
|
+
) : records.isLoading ? (
|
|
340
|
+
<div className="rounded-lg border border-border px-3 py-6 text-center text-sm text-muted-foreground">
|
|
341
|
+
Loading records…
|
|
342
|
+
</div>
|
|
343
|
+
) : records.records.length === 0 ? (
|
|
344
|
+
<div className="rounded-lg border border-border px-3 py-6 text-center text-sm text-muted-foreground">
|
|
345
|
+
{conditions.length > 0
|
|
346
|
+
? "No records match the current filters."
|
|
347
|
+
: `No records in “${collection.name}” yet.`}
|
|
348
|
+
</div>
|
|
349
|
+
) : (
|
|
350
|
+
records.table && (
|
|
351
|
+
<div className="overflow-x-auto rounded-lg border border-border">
|
|
352
|
+
<ResourceTable
|
|
353
|
+
table={records.table}
|
|
354
|
+
aria-label={`Records in ${collection.name}`}
|
|
355
|
+
renderRowAction={
|
|
356
|
+
canUpdate || canDelete
|
|
357
|
+
? (record) => (
|
|
358
|
+
<RowActions
|
|
359
|
+
record={record}
|
|
360
|
+
canUpdate={canUpdate}
|
|
361
|
+
canDelete={canDelete}
|
|
362
|
+
onEdit={openEdit}
|
|
363
|
+
onDelete={handleDelete}
|
|
364
|
+
/>
|
|
365
|
+
)
|
|
366
|
+
: undefined
|
|
367
|
+
}
|
|
368
|
+
/>
|
|
369
|
+
</div>
|
|
370
|
+
)
|
|
371
|
+
)}
|
|
372
|
+
|
|
373
|
+
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
|
374
|
+
<span>
|
|
375
|
+
{records.total} record{records.total === 1 ? "" : "s"}
|
|
376
|
+
</span>
|
|
377
|
+
<div className="flex items-center gap-2">
|
|
378
|
+
<button
|
|
379
|
+
type="button"
|
|
380
|
+
onClick={() => onPageChange(page - 1)}
|
|
381
|
+
disabled={page <= 1}
|
|
382
|
+
className={paginationButtonClass}
|
|
383
|
+
>
|
|
384
|
+
Previous
|
|
385
|
+
</button>
|
|
386
|
+
<span>
|
|
387
|
+
Page {page} of {totalPages}
|
|
388
|
+
</span>
|
|
389
|
+
<button
|
|
390
|
+
type="button"
|
|
391
|
+
onClick={() => onPageChange(page + 1)}
|
|
392
|
+
disabled={page >= totalPages}
|
|
393
|
+
className={paginationButtonClass}
|
|
394
|
+
>
|
|
395
|
+
Next
|
|
396
|
+
</button>
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
|
|
400
|
+
<RecordFormPanel
|
|
401
|
+
open={formOpen}
|
|
402
|
+
onOpenChange={setFormOpen}
|
|
403
|
+
scope={scope}
|
|
404
|
+
collection={collection}
|
|
405
|
+
record={editing}
|
|
406
|
+
onSaved={() => records.refetch()}
|
|
407
|
+
/>
|
|
408
|
+
<ConfirmDialog state={confirmState} onConfirm={handleConfirm} onCancel={handleCancel} />
|
|
409
|
+
</div>
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const paginationButtonClass = cn(
|
|
414
|
+
"rounded-md border border-input bg-background px-2 py-1 text-xs font-medium text-foreground",
|
|
415
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
416
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
417
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
// ---------------------------------------------------------------------------
|
|
421
|
+
// Denied panel — an explanation, never an empty grid
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
423
|
+
|
|
424
|
+
function DeniedPanel({ message }: { readonly message: string }) {
|
|
425
|
+
return (
|
|
426
|
+
<div
|
|
427
|
+
role="status"
|
|
428
|
+
className="flex flex-col items-center gap-2 rounded-lg border border-border bg-muted px-4 py-8 text-center"
|
|
429
|
+
>
|
|
430
|
+
<p className="text-sm font-medium text-foreground">{message}</p>
|
|
431
|
+
<p className="max-w-md text-xs text-muted-foreground">
|
|
432
|
+
Record access is granted by the datastore's authorization block. To
|
|
433
|
+
gain access, add a role binding for your principal or set a{" "}
|
|
434
|
+
<code className="font-mono">default_role</code> in the datastore YAML,
|
|
435
|
+
with the verbs you need granted on this collection.
|
|
436
|
+
</p>
|
|
437
|
+
</div>
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// ---------------------------------------------------------------------------
|
|
442
|
+
// Columns: typed cells from FieldDeclaration + system columns
|
|
443
|
+
// ---------------------------------------------------------------------------
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Grid columns for a collection: declared fields with typed cells, then
|
|
447
|
+
* `created_at` (visible by default). The remaining system columns
|
|
448
|
+
* (`id`, `updated_at`, `created_by`) stay out of the default grid —
|
|
449
|
+
* they are shown in the record form's read-only summary; a column
|
|
450
|
+
* toggle is recorded growth.
|
|
451
|
+
*
|
|
452
|
+
* `readableFields` narrows the declared columns to the caller's
|
|
453
|
+
* column-level read access (empty means every field): a hidden field's
|
|
454
|
+
* cells would be permanently empty, which reads as missing data rather
|
|
455
|
+
* than restricted access.
|
|
456
|
+
*/
|
|
457
|
+
function buildRecordColumns(
|
|
458
|
+
collection: CollectionDeclaration,
|
|
459
|
+
readableFields: readonly string[],
|
|
460
|
+
): RecordColumnDef[] {
|
|
461
|
+
const readable = readableFields.length > 0 ? new Set(readableFields) : null;
|
|
462
|
+
const declaredColumns =
|
|
463
|
+
readable === null
|
|
464
|
+
? collection.fields
|
|
465
|
+
: collection.fields.filter((field) => readable.has(field.name));
|
|
466
|
+
const fieldColumns: RecordColumnDef[] = declaredColumns.map((field) => ({
|
|
467
|
+
id: field.name,
|
|
468
|
+
header: field.name,
|
|
469
|
+
sortable: isSortableField(field),
|
|
470
|
+
cell: (record) => (
|
|
471
|
+
<TypedCell
|
|
472
|
+
value={formatFieldValue(field.type, record.fields?.[field.name])}
|
|
473
|
+
numeric={field.type === FieldType.integer || field.type === FieldType.number}
|
|
474
|
+
mono={field.type === FieldType.json}
|
|
475
|
+
/>
|
|
476
|
+
),
|
|
477
|
+
}));
|
|
478
|
+
|
|
479
|
+
return [
|
|
480
|
+
...fieldColumns,
|
|
481
|
+
{
|
|
482
|
+
id: "created_at",
|
|
483
|
+
header: "created_at",
|
|
484
|
+
sortable: true,
|
|
485
|
+
cell: (record) => (
|
|
486
|
+
<TypedCell
|
|
487
|
+
value={
|
|
488
|
+
record.createdAt
|
|
489
|
+
? formatSystemTimestamp(timestampDate(record.createdAt).toISOString())
|
|
490
|
+
: ""
|
|
491
|
+
}
|
|
492
|
+
mono
|
|
493
|
+
/>
|
|
494
|
+
),
|
|
495
|
+
},
|
|
496
|
+
];
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function TypedCell({
|
|
500
|
+
value,
|
|
501
|
+
numeric,
|
|
502
|
+
mono,
|
|
503
|
+
}: {
|
|
504
|
+
readonly value: string;
|
|
505
|
+
readonly numeric?: boolean;
|
|
506
|
+
readonly mono?: boolean;
|
|
507
|
+
}) {
|
|
508
|
+
const truncated = value.length > 80 ? `${value.slice(0, 79)}…` : value;
|
|
509
|
+
return (
|
|
510
|
+
<span
|
|
511
|
+
title={value.length > 80 ? value : undefined}
|
|
512
|
+
className={cn(
|
|
513
|
+
"block max-w-xs truncate",
|
|
514
|
+
numeric && "text-right tabular-nums",
|
|
515
|
+
mono && "font-mono",
|
|
516
|
+
)}
|
|
517
|
+
>
|
|
518
|
+
{truncated}
|
|
519
|
+
</span>
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// ---------------------------------------------------------------------------
|
|
524
|
+
// Row actions
|
|
525
|
+
// ---------------------------------------------------------------------------
|
|
526
|
+
|
|
527
|
+
function RowActions({
|
|
528
|
+
record,
|
|
529
|
+
canUpdate,
|
|
530
|
+
canDelete,
|
|
531
|
+
onEdit,
|
|
532
|
+
onDelete,
|
|
533
|
+
}: {
|
|
534
|
+
readonly record: RecordEnvelope;
|
|
535
|
+
readonly canUpdate: boolean;
|
|
536
|
+
readonly canDelete: boolean;
|
|
537
|
+
readonly onEdit: (record: RecordEnvelope) => void;
|
|
538
|
+
readonly onDelete: (record: RecordEnvelope) => void;
|
|
539
|
+
}) {
|
|
540
|
+
return (
|
|
541
|
+
<div className="flex items-center gap-1">
|
|
542
|
+
{canUpdate && (
|
|
543
|
+
<button
|
|
544
|
+
type="button"
|
|
545
|
+
onClick={() => onEdit(record)}
|
|
546
|
+
aria-label={`Edit record ${record.id}`}
|
|
547
|
+
className={rowActionClass}
|
|
548
|
+
>
|
|
549
|
+
Edit
|
|
550
|
+
</button>
|
|
551
|
+
)}
|
|
552
|
+
{canDelete && (
|
|
553
|
+
<button
|
|
554
|
+
type="button"
|
|
555
|
+
onClick={() => onDelete(record)}
|
|
556
|
+
aria-label={`Delete record ${record.id}`}
|
|
557
|
+
className={cn(rowActionClass, "text-destructive hover:text-destructive")}
|
|
558
|
+
>
|
|
559
|
+
Delete
|
|
560
|
+
</button>
|
|
561
|
+
)}
|
|
562
|
+
</div>
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const rowActionClass = cn(
|
|
567
|
+
"rounded-md px-1.5 py-0.5 text-xs font-medium text-muted-foreground",
|
|
568
|
+
"hover:bg-accent hover:text-foreground",
|
|
569
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
570
|
+
);
|