@stigmer/react 3.2.3 → 3.3.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/BaselineEditor.d.ts +9 -0
- package/billing/BaselineEditor.d.ts.map +1 -0
- package/billing/BaselineEditor.js +253 -0
- package/billing/BaselineEditor.js.map +1 -0
- package/billing/ModelCatalogPanel.d.ts +28 -0
- package/billing/ModelCatalogPanel.d.ts.map +1 -0
- package/billing/ModelCatalogPanel.js +102 -0
- package/billing/ModelCatalogPanel.js.map +1 -0
- package/billing/ModelGovernanceDetail.d.ts +8 -0
- package/billing/ModelGovernanceDetail.d.ts.map +1 -0
- package/billing/ModelGovernanceDetail.js +64 -0
- package/billing/ModelGovernanceDetail.js.map +1 -0
- package/billing/OperatorAccessNotice.d.ts +12 -0
- package/billing/OperatorAccessNotice.d.ts.map +1 -0
- package/billing/OperatorAccessNotice.js +15 -0
- package/billing/OperatorAccessNotice.js.map +1 -0
- package/billing/PricingGovernanceConsole.d.ts +57 -0
- package/billing/PricingGovernanceConsole.d.ts.map +1 -0
- package/billing/PricingGovernanceConsole.js +164 -0
- package/billing/PricingGovernanceConsole.js.map +1 -0
- package/billing/PricingGovernancePanel.d.ts +26 -0
- package/billing/PricingGovernancePanel.d.ts.map +1 -0
- package/billing/PricingGovernancePanel.js +64 -0
- package/billing/PricingGovernancePanel.js.map +1 -0
- package/billing/RetireConfirm.d.ts +9 -0
- package/billing/RetireConfirm.d.ts.map +1 -0
- package/billing/RetireConfirm.js +19 -0
- package/billing/RetireConfirm.js.map +1 -0
- package/billing/form-primitives.d.ts +18 -0
- package/billing/form-primitives.d.ts.map +1 -0
- package/billing/form-primitives.js +19 -0
- package/billing/form-primitives.js.map +1 -0
- package/billing/governance-primitives.d.ts +33 -0
- package/billing/governance-primitives.d.ts.map +1 -0
- package/billing/governance-primitives.js +43 -0
- package/billing/governance-primitives.js.map +1 -0
- package/billing/index.d.ts +18 -0
- package/billing/index.d.ts.map +1 -1
- package/billing/index.js +9 -0
- package/billing/index.js.map +1 -1
- package/billing/pricing-format.d.ts +12 -0
- package/billing/pricing-format.d.ts.map +1 -0
- package/billing/pricing-format.js +50 -0
- package/billing/pricing-format.js.map +1 -0
- package/billing/useDecidePricingOverride.d.ts +46 -0
- package/billing/useDecidePricingOverride.d.ts.map +1 -0
- package/billing/useDecidePricingOverride.js +44 -0
- package/billing/useDecidePricingOverride.js.map +1 -0
- package/billing/useModelGovernanceView.d.ts +103 -0
- package/billing/useModelGovernanceView.d.ts.map +1 -0
- package/billing/useModelGovernanceView.js +144 -0
- package/billing/useModelGovernanceView.js.map +1 -0
- package/billing/useModelPricingBaselines.d.ts +40 -0
- package/billing/useModelPricingBaselines.d.ts.map +1 -0
- package/billing/useModelPricingBaselines.js +32 -0
- package/billing/useModelPricingBaselines.js.map +1 -0
- package/billing/usePricingGovernance.d.ts +39 -0
- package/billing/usePricingGovernance.d.ts.map +1 -0
- package/billing/usePricingGovernance.js +31 -0
- package/billing/usePricingGovernance.js.map +1 -0
- package/billing/useRetireModelPricingBaseline.d.ts +31 -0
- package/billing/useRetireModelPricingBaseline.d.ts.map +1 -0
- package/billing/useRetireModelPricingBaseline.js +36 -0
- package/billing/useRetireModelPricingBaseline.js.map +1 -0
- package/billing/useUpsertModelPricingBaseline.d.ts +38 -0
- package/billing/useUpsertModelPricingBaseline.d.ts.map +1 -0
- package/billing/useUpsertModelPricingBaseline.js +37 -0
- package/billing/useUpsertModelPricingBaseline.js.map +1 -0
- 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 +28 -0
- package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountEditor.js +51 -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 +28 -0
- package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -0
- package/cursor-accounts/CursorAccountsConsole.js +275 -0
- package/cursor-accounts/CursorAccountsConsole.js.map +1 -0
- package/cursor-accounts/cursor-account-format.d.ts +10 -0
- package/cursor-accounts/cursor-account-format.d.ts.map +1 -0
- package/cursor-accounts/cursor-account-format.js +26 -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 +209 -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 +30 -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 +54 -0
- package/datastore/recordFilter.d.ts.map +1 -0
- package/datastore/recordFilter.js +93 -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/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 -6
- package/index.d.ts.map +1 -1
- package/index.js +14 -3
- package/index.js.map +1 -1
- 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/resource-creation/templates/workflow-templates.js +4 -4
- package/session/useEditSessionPrep.js +3 -3
- package/session/useEditSessionPrep.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/BaselineEditor.tsx +619 -0
- package/src/billing/ModelCatalogPanel.tsx +283 -0
- package/src/billing/ModelGovernanceDetail.tsx +289 -0
- package/src/billing/OperatorAccessNotice.tsx +32 -0
- package/src/billing/PricingGovernanceConsole.tsx +465 -0
- package/src/billing/PricingGovernancePanel.tsx +166 -0
- package/src/billing/RetireConfirm.tsx +82 -0
- package/src/billing/__tests__/ModelCatalogPanel.test.tsx +253 -0
- package/src/billing/__tests__/PricingGovernanceConsole.test.tsx +410 -0
- package/src/billing/__tests__/useModelGovernanceView.test.tsx +308 -0
- package/src/billing/form-primitives.tsx +68 -0
- package/src/billing/governance-primitives.tsx +133 -0
- package/src/billing/index.ts +37 -0
- package/src/billing/pricing-format.ts +53 -0
- package/src/billing/useDecidePricingOverride.ts +78 -0
- package/src/billing/useModelGovernanceView.ts +290 -0
- package/src/billing/useModelPricingBaselines.ts +69 -0
- package/src/billing/usePricingGovernance.ts +57 -0
- package/src/billing/useRetireModelPricingBaseline.ts +65 -0
- package/src/billing/useUpsertModelPricingBaseline.ts +72 -0
- package/src/channel/AgentChannelsPanel.tsx +27 -1
- package/src/composer/SessionComposer.tsx +1 -1
- package/src/cursor-accounts/CursorAccountEditor.tsx +181 -0
- package/src/cursor-accounts/CursorAccountsAccessNotice.tsx +36 -0
- package/src/cursor-accounts/CursorAccountsConsole.tsx +810 -0
- package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +384 -0
- package/src/cursor-accounts/cursor-account-format.ts +29 -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 +544 -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 +411 -0
- package/src/datastore/RecordFormPanel.tsx +432 -0
- package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +207 -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 +141 -0
- package/src/datastore/__tests__/RecordFormPanel.test.tsx +227 -0
- package/src/datastore/__tests__/recordFilter.test.ts +156 -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 +140 -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/__tests__/useArtifactInspection.test.tsx +12 -2
- 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 +163 -13
- 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/resource-creation/templates/workflow-templates.ts +4 -4
- package/src/session/useEditSessionPrep.ts +3 -3
- 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,315 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { lazy, Suspense, useCallback, useEffect, useRef } from "react";
|
|
4
|
+
import { cn } from "@stigmer/theme";
|
|
5
|
+
import { toast } from "../feedback/toast.js";
|
|
6
|
+
import { RedactedSecretsNotice } from "./RedactedSecretsNotice.js";
|
|
7
|
+
import {
|
|
8
|
+
useApplyManifest,
|
|
9
|
+
type ManifestPreviewEntry,
|
|
10
|
+
} from "./useApplyManifest.js";
|
|
11
|
+
|
|
12
|
+
// CodeMirror loads only when the dialog actually opens (DD-013).
|
|
13
|
+
const LazyYamlEditor = lazy(() =>
|
|
14
|
+
import("./YamlEditor.js").then((m) => ({ default: m.YamlEditor })),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
/** Props for {@link ApplyManifestDialog}. */
|
|
18
|
+
export interface ApplyManifestDialogProps {
|
|
19
|
+
/** Whether the dialog is open. */
|
|
20
|
+
readonly open: boolean;
|
|
21
|
+
/** Called when the dialog should open or close. */
|
|
22
|
+
readonly onOpenChange: (open: boolean) => void;
|
|
23
|
+
/** Target organization slug for documents that omit `metadata.org`. */
|
|
24
|
+
readonly org: string;
|
|
25
|
+
/**
|
|
26
|
+
* Called after every document applied successfully, with the per-document
|
|
27
|
+
* results in apply order. Use for navigation or list refresh.
|
|
28
|
+
*/
|
|
29
|
+
readonly onSuccess?: (entries: readonly ManifestPreviewEntry[]) => void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Modal dialog for applying a Stigmer resource manifest — paste YAML or
|
|
34
|
+
* upload a file, review what will change, and apply. The console
|
|
35
|
+
* counterpart of `stigmer apply -f`, for every supported resource kind.
|
|
36
|
+
*
|
|
37
|
+
* Workflow:
|
|
38
|
+
* 1. Paste manifest YAML (or JSON) into the editor, or pick a file
|
|
39
|
+
* 2. Each document is validated against its kind's generated proto schema
|
|
40
|
+
* and previewed with a create-or-update badge resolved from server state
|
|
41
|
+
* 3. Apply runs the documents sequentially in dependency order with live
|
|
42
|
+
* per-document status; a failure stops the run and renders inline
|
|
43
|
+
*
|
|
44
|
+
* Multi-document manifests (`---` separators) are supported. Documents
|
|
45
|
+
* that omit `metadata.org` are applied to the active org; documents naming
|
|
46
|
+
* a different org are honored with a warning (matching `stigmer apply`).
|
|
47
|
+
*
|
|
48
|
+
* Uses the native `<dialog>` element for built-in focus trapping, Escape
|
|
49
|
+
* key handling, and backdrop — consistent with {@link ConfirmDialog}.
|
|
50
|
+
*
|
|
51
|
+
* Zero Console dependencies — safe for platform builder embedding.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <ApplyManifestDialog
|
|
56
|
+
* open={open}
|
|
57
|
+
* onOpenChange={setOpen}
|
|
58
|
+
* org={activeOrg}
|
|
59
|
+
* onSuccess={() => refetchList()}
|
|
60
|
+
* />
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function ApplyManifestDialog({
|
|
64
|
+
open,
|
|
65
|
+
onOpenChange,
|
|
66
|
+
org,
|
|
67
|
+
onSuccess,
|
|
68
|
+
}: ApplyManifestDialogProps) {
|
|
69
|
+
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
70
|
+
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
71
|
+
const manifest = useApplyManifest(org);
|
|
72
|
+
const { reset } = manifest;
|
|
73
|
+
|
|
74
|
+
// Sync dialog open state with the native <dialog> element.
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const dialog = dialogRef.current;
|
|
77
|
+
if (!dialog) return;
|
|
78
|
+
if (open && !dialog.open) {
|
|
79
|
+
dialog.showModal();
|
|
80
|
+
} else if (!open && dialog.open) {
|
|
81
|
+
dialog.close();
|
|
82
|
+
}
|
|
83
|
+
}, [open]);
|
|
84
|
+
|
|
85
|
+
// Start each session clean.
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (open) {
|
|
88
|
+
reset();
|
|
89
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
90
|
+
}
|
|
91
|
+
}, [open, reset]);
|
|
92
|
+
|
|
93
|
+
const handleCancel = useCallback(
|
|
94
|
+
(e: React.SyntheticEvent) => {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
onOpenChange(false);
|
|
97
|
+
},
|
|
98
|
+
[onOpenChange],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const handleFileChange = useCallback(
|
|
102
|
+
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
103
|
+
const file = e.target.files?.[0];
|
|
104
|
+
if (file) manifest.readFile(file);
|
|
105
|
+
},
|
|
106
|
+
[manifest],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const handleApply = useCallback(async () => {
|
|
110
|
+
const allApplied = await manifest.applyAll();
|
|
111
|
+
if (allApplied && manifest.entries) {
|
|
112
|
+
const count = manifest.entries.length;
|
|
113
|
+
toast.success(
|
|
114
|
+
count === 1 ? "Resource applied" : `${count} resources applied`,
|
|
115
|
+
);
|
|
116
|
+
onOpenChange(false);
|
|
117
|
+
onSuccess?.(manifest.entries);
|
|
118
|
+
}
|
|
119
|
+
// On failure the dialog stays open — per-entry status shows what
|
|
120
|
+
// applied and what failed.
|
|
121
|
+
}, [manifest, onOpenChange, onSuccess]);
|
|
122
|
+
|
|
123
|
+
const canApply =
|
|
124
|
+
manifest.entries !== null &&
|
|
125
|
+
manifest.entries.length > 0 &&
|
|
126
|
+
!manifest.isValidating &&
|
|
127
|
+
!manifest.isApplying;
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<dialog
|
|
131
|
+
ref={dialogRef}
|
|
132
|
+
onCancel={handleCancel}
|
|
133
|
+
className={cn(
|
|
134
|
+
"fixed inset-0 z-50 m-auto w-full max-w-3xl rounded-lg border border-border bg-popover p-0 text-popover-foreground shadow-lg",
|
|
135
|
+
"backdrop:bg-black/50",
|
|
136
|
+
"open:animate-in open:fade-in-0 open:zoom-in-95",
|
|
137
|
+
)}
|
|
138
|
+
>
|
|
139
|
+
<div className="flex flex-col gap-4 p-6">
|
|
140
|
+
{/* Header */}
|
|
141
|
+
<div className="flex flex-col gap-1">
|
|
142
|
+
<h3 className="text-base font-semibold text-foreground">Apply YAML</h3>
|
|
143
|
+
<p className="text-sm text-muted-foreground">
|
|
144
|
+
Paste a resource manifest or upload a file. Resources are created
|
|
145
|
+
when new and updated when they already exist.
|
|
146
|
+
</p>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
{/* File picker */}
|
|
150
|
+
<input
|
|
151
|
+
ref={fileInputRef}
|
|
152
|
+
type="file"
|
|
153
|
+
accept=".yaml,.yml,.json"
|
|
154
|
+
onChange={handleFileChange}
|
|
155
|
+
className={cn(
|
|
156
|
+
"w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-foreground",
|
|
157
|
+
"file:mr-3 file:rounded-md file:border-0 file:bg-primary file:px-2.5 file:py-1 file:text-xs file:font-medium file:text-primary-foreground",
|
|
158
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
159
|
+
)}
|
|
160
|
+
aria-label="Select manifest file"
|
|
161
|
+
/>
|
|
162
|
+
|
|
163
|
+
{/* Manifest editor */}
|
|
164
|
+
<Suspense fallback={<EditorLoading />}>
|
|
165
|
+
<LazyYamlEditor
|
|
166
|
+
value={manifest.content}
|
|
167
|
+
onChange={manifest.setContent}
|
|
168
|
+
className="h-56"
|
|
169
|
+
/>
|
|
170
|
+
</Suspense>
|
|
171
|
+
|
|
172
|
+
{manifest.hasRedactedSecrets && <RedactedSecretsNotice />}
|
|
173
|
+
|
|
174
|
+
{/* Validation error */}
|
|
175
|
+
{manifest.validationError && (
|
|
176
|
+
<div
|
|
177
|
+
role="alert"
|
|
178
|
+
className="rounded-md border border-destructive bg-card px-3 py-2.5 text-sm text-destructive"
|
|
179
|
+
>
|
|
180
|
+
{manifest.validationError}
|
|
181
|
+
</div>
|
|
182
|
+
)}
|
|
183
|
+
|
|
184
|
+
{/* Per-document preview */}
|
|
185
|
+
{manifest.entries && manifest.entries.length > 0 && (
|
|
186
|
+
<ul className="flex max-h-48 flex-col gap-2 overflow-y-auto" aria-label="Resources to apply">
|
|
187
|
+
{manifest.entries.map((entry, index) => (
|
|
188
|
+
<PreviewRow key={`${entry.document.handler.yamlKind}/${entry.document.org}/${entry.document.slug}/${index}`} entry={entry} />
|
|
189
|
+
))}
|
|
190
|
+
</ul>
|
|
191
|
+
)}
|
|
192
|
+
|
|
193
|
+
{/* Actions */}
|
|
194
|
+
<div className="flex items-center justify-between gap-3">
|
|
195
|
+
<p className="text-xs text-muted-foreground" aria-live="polite">
|
|
196
|
+
{manifest.isValidating ? "Validating…" : ""}
|
|
197
|
+
</p>
|
|
198
|
+
<div className="flex gap-2">
|
|
199
|
+
<button
|
|
200
|
+
type="button"
|
|
201
|
+
onClick={() => onOpenChange(false)}
|
|
202
|
+
disabled={manifest.isApplying}
|
|
203
|
+
className={cn(
|
|
204
|
+
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
205
|
+
"border border-input bg-background text-foreground",
|
|
206
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
207
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
208
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
209
|
+
)}
|
|
210
|
+
>
|
|
211
|
+
Cancel
|
|
212
|
+
</button>
|
|
213
|
+
<button
|
|
214
|
+
type="button"
|
|
215
|
+
onClick={handleApply}
|
|
216
|
+
disabled={!canApply}
|
|
217
|
+
className={cn(
|
|
218
|
+
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
219
|
+
"bg-primary text-primary-foreground hover:bg-primary-hover",
|
|
220
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
221
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
222
|
+
)}
|
|
223
|
+
>
|
|
224
|
+
{manifest.isApplying
|
|
225
|
+
? "Applying…"
|
|
226
|
+
: applyLabel(manifest.entries?.length ?? 0)}
|
|
227
|
+
</button>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
</dialog>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function applyLabel(count: number): string {
|
|
236
|
+
if (count <= 1) return "Apply";
|
|
237
|
+
return `Apply ${count} resources`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function EditorLoading() {
|
|
241
|
+
return (
|
|
242
|
+
<div className="flex h-56 items-center justify-center rounded-md border border-border bg-muted text-sm text-muted-foreground">
|
|
243
|
+
Loading editor…
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
// Per-document preview row
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
|
|
252
|
+
function PreviewRow({ entry }: { readonly entry: ManifestPreviewEntry }) {
|
|
253
|
+
return (
|
|
254
|
+
<li className="rounded-md border border-border bg-card px-3 py-2">
|
|
255
|
+
<div className="flex items-center gap-2">
|
|
256
|
+
<span className="inline-flex rounded bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground">
|
|
257
|
+
{entry.document.handler.displayName}
|
|
258
|
+
</span>
|
|
259
|
+
<span className="text-sm font-medium text-foreground">
|
|
260
|
+
{entry.document.name}
|
|
261
|
+
</span>
|
|
262
|
+
<ActionBadge entry={entry} />
|
|
263
|
+
<span className="ml-auto text-xs text-muted-foreground">
|
|
264
|
+
{entry.document.org}
|
|
265
|
+
</span>
|
|
266
|
+
</div>
|
|
267
|
+
{entry.document.warning && (
|
|
268
|
+
<p className="mt-1 text-xs text-muted-foreground">{entry.document.warning}</p>
|
|
269
|
+
)}
|
|
270
|
+
{entry.status === "failed" && entry.errorMessage && (
|
|
271
|
+
<p role="alert" className="mt-1 text-xs text-destructive">
|
|
272
|
+
{entry.errorMessage}
|
|
273
|
+
</p>
|
|
274
|
+
)}
|
|
275
|
+
</li>
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function ActionBadge({ entry }: { readonly entry: ManifestPreviewEntry }) {
|
|
280
|
+
const label = badgeLabel(entry);
|
|
281
|
+
return (
|
|
282
|
+
<span
|
|
283
|
+
className={cn(
|
|
284
|
+
"inline-flex rounded px-1.5 py-0.5 text-xs font-medium",
|
|
285
|
+
entry.status === "failed"
|
|
286
|
+
? "bg-card text-destructive border border-destructive"
|
|
287
|
+
: "bg-muted text-muted-foreground",
|
|
288
|
+
)}
|
|
289
|
+
>
|
|
290
|
+
{label}
|
|
291
|
+
</span>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function badgeLabel(entry: ManifestPreviewEntry): string {
|
|
296
|
+
switch (entry.status) {
|
|
297
|
+
case "applying":
|
|
298
|
+
return "Applying…";
|
|
299
|
+
case "applied":
|
|
300
|
+
return "Applied";
|
|
301
|
+
case "failed":
|
|
302
|
+
return "Failed";
|
|
303
|
+
case "skipped":
|
|
304
|
+
return "Skipped";
|
|
305
|
+
case "pending":
|
|
306
|
+
switch (entry.action) {
|
|
307
|
+
case "create":
|
|
308
|
+
return "Will create";
|
|
309
|
+
case "update":
|
|
310
|
+
return "Will update";
|
|
311
|
+
case "unknown":
|
|
312
|
+
return "Create or update";
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { lazy, Suspense, useCallback, useEffect, useRef } from "react";
|
|
4
|
+
import type { Message } from "@bufbuild/protobuf";
|
|
5
|
+
import { cn } from "@stigmer/theme";
|
|
6
|
+
import { getUserMessage, type AppliedManifest } from "@stigmer/sdk";
|
|
7
|
+
import { toast } from "../feedback/toast.js";
|
|
8
|
+
import { RedactedSecretsNotice } from "./RedactedSecretsNotice.js";
|
|
9
|
+
import { useEditResourceYaml } from "./useEditResourceYaml.js";
|
|
10
|
+
|
|
11
|
+
// CodeMirror loads only when an editor dialog actually opens (DD-013).
|
|
12
|
+
const LazyYamlEditor = lazy(() =>
|
|
13
|
+
import("./YamlEditor.js").then((m) => ({ default: m.YamlEditor })),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
/** Props for {@link EditResourceYamlDialog}. */
|
|
17
|
+
export interface EditResourceYamlDialogProps {
|
|
18
|
+
/** Whether the dialog is open. */
|
|
19
|
+
readonly open: boolean;
|
|
20
|
+
/** Called when the dialog should open or close. */
|
|
21
|
+
readonly onOpenChange: (open: boolean) => void;
|
|
22
|
+
/**
|
|
23
|
+
* The resource to edit, as returned by the server. `null` while loading —
|
|
24
|
+
* the dialog shows the editor as soon as the resource arrives.
|
|
25
|
+
*/
|
|
26
|
+
readonly resource: Message | null;
|
|
27
|
+
/** Called after a successful apply. Use for refetching or navigation. */
|
|
28
|
+
readonly onApplied?: (result: AppliedManifest) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Modal dialog for editing a resource as YAML and applying the changes —
|
|
33
|
+
* the kind-agnostic "Edit YAML" experience for detail pages and panels.
|
|
34
|
+
*
|
|
35
|
+
* Workflow:
|
|
36
|
+
* 1. The resource is serialized to canonical YAML (system-managed state
|
|
37
|
+
* stripped) and seeded into a CodeMirror editor
|
|
38
|
+
* 2. Every edit is validated against the kind's generated proto schema;
|
|
39
|
+
* errors render inline with the exact schema complaint
|
|
40
|
+
* 3. A live summary states what applying will do ("update X" / "create Y"),
|
|
41
|
+
* resolved against server state — so a rename reads as a create
|
|
42
|
+
* 4. Apply calls the kind's `apply` RPC (create-or-update by slug)
|
|
43
|
+
*
|
|
44
|
+
* Redacted secret values (`***REDACTED***`) are explained inline: applying
|
|
45
|
+
* them preserves the stored secrets (the server's marker contract).
|
|
46
|
+
*
|
|
47
|
+
* Uses the native `<dialog>` element for built-in focus trapping, Escape
|
|
48
|
+
* key handling, and backdrop — consistent with {@link ConfirmDialog}.
|
|
49
|
+
*
|
|
50
|
+
* Zero Console dependencies — safe for platform builder embedding.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* const { agent, refetch } = useAgent(org, slug);
|
|
55
|
+
*
|
|
56
|
+
* <EditResourceYamlDialog
|
|
57
|
+
* open={editOpen}
|
|
58
|
+
* onOpenChange={setEditOpen}
|
|
59
|
+
* resource={agent}
|
|
60
|
+
* onApplied={() => refetch()}
|
|
61
|
+
* />
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export function EditResourceYamlDialog({
|
|
65
|
+
open,
|
|
66
|
+
onOpenChange,
|
|
67
|
+
resource,
|
|
68
|
+
onApplied,
|
|
69
|
+
}: EditResourceYamlDialogProps) {
|
|
70
|
+
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
71
|
+
const edit = useEditResourceYaml({ resource });
|
|
72
|
+
const { reset } = edit;
|
|
73
|
+
|
|
74
|
+
// Sync dialog open state with the native <dialog> element.
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const dialog = dialogRef.current;
|
|
77
|
+
if (!dialog) return;
|
|
78
|
+
if (open && !dialog.open) {
|
|
79
|
+
dialog.showModal();
|
|
80
|
+
} else if (!open && dialog.open) {
|
|
81
|
+
dialog.close();
|
|
82
|
+
}
|
|
83
|
+
}, [open]);
|
|
84
|
+
|
|
85
|
+
// Discard stale edits from a previous session when the dialog opens.
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (open) reset();
|
|
88
|
+
}, [open, reset]);
|
|
89
|
+
|
|
90
|
+
const handleCancel = useCallback(
|
|
91
|
+
(e: React.SyntheticEvent) => {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
onOpenChange(false);
|
|
94
|
+
},
|
|
95
|
+
[onOpenChange],
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const handleApply = useCallback(async () => {
|
|
99
|
+
try {
|
|
100
|
+
const result = await edit.apply();
|
|
101
|
+
if (!result) return;
|
|
102
|
+
toast.success(`${result.displayName} "${result.name}" applied`);
|
|
103
|
+
onOpenChange(false);
|
|
104
|
+
onApplied?.(result);
|
|
105
|
+
} catch {
|
|
106
|
+
// error state is set by the hook and rendered inline
|
|
107
|
+
}
|
|
108
|
+
}, [edit, onOpenChange, onApplied]);
|
|
109
|
+
|
|
110
|
+
const canApply =
|
|
111
|
+
edit.validation.status === "valid" && edit.isDirty && !edit.isApplying;
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<dialog
|
|
115
|
+
ref={dialogRef}
|
|
116
|
+
onCancel={handleCancel}
|
|
117
|
+
className={cn(
|
|
118
|
+
"fixed inset-0 z-50 m-auto w-full max-w-3xl rounded-lg border border-border bg-popover p-0 text-popover-foreground shadow-lg",
|
|
119
|
+
"backdrop:bg-black/50",
|
|
120
|
+
"open:animate-in open:fade-in-0 open:zoom-in-95",
|
|
121
|
+
)}
|
|
122
|
+
>
|
|
123
|
+
<div className="flex flex-col gap-4 p-6">
|
|
124
|
+
{/* Header */}
|
|
125
|
+
<div className="flex flex-col gap-1">
|
|
126
|
+
<h3 className="text-base font-semibold text-foreground">Edit YAML</h3>
|
|
127
|
+
<p className="text-sm text-muted-foreground">
|
|
128
|
+
Edit the resource definition and apply. Changes are validated
|
|
129
|
+
against the resource schema as you type.
|
|
130
|
+
</p>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
{/* Editor */}
|
|
134
|
+
{resource ? (
|
|
135
|
+
<Suspense fallback={<EditorLoading />}>
|
|
136
|
+
<LazyYamlEditor
|
|
137
|
+
value={edit.yaml}
|
|
138
|
+
onChange={edit.setYaml}
|
|
139
|
+
className="h-80"
|
|
140
|
+
/>
|
|
141
|
+
</Suspense>
|
|
142
|
+
) : (
|
|
143
|
+
<EditorLoading label="Loading resource…" />
|
|
144
|
+
)}
|
|
145
|
+
|
|
146
|
+
{edit.hasRedactedSecrets && <RedactedSecretsNotice />}
|
|
147
|
+
|
|
148
|
+
{/* Validation error */}
|
|
149
|
+
{edit.validation.status === "invalid" && (
|
|
150
|
+
<div
|
|
151
|
+
role="alert"
|
|
152
|
+
className="rounded-md border border-destructive bg-card px-3 py-2.5 text-sm text-destructive"
|
|
153
|
+
>
|
|
154
|
+
{edit.validation.message}
|
|
155
|
+
</div>
|
|
156
|
+
)}
|
|
157
|
+
|
|
158
|
+
{/* Apply error — the server's refusal (e.g. a datastore
|
|
159
|
+
collection-removal rejection) rendered verbatim, with an
|
|
160
|
+
acknowledge-and-retry affordance: the operator reads the
|
|
161
|
+
guard, edits or decides, and re-applies without reopening
|
|
162
|
+
the dialog. */}
|
|
163
|
+
{edit.error && (
|
|
164
|
+
<div
|
|
165
|
+
role="alert"
|
|
166
|
+
className="flex items-start gap-3 rounded-md border border-destructive bg-card px-3 py-2.5"
|
|
167
|
+
>
|
|
168
|
+
<p className="flex-1 text-sm text-destructive">
|
|
169
|
+
{getUserMessage(edit.error)}
|
|
170
|
+
</p>
|
|
171
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
172
|
+
<button
|
|
173
|
+
type="button"
|
|
174
|
+
onClick={handleApply}
|
|
175
|
+
disabled={edit.validation.status !== "valid" || edit.isApplying}
|
|
176
|
+
className={cn(
|
|
177
|
+
"rounded-md border border-input bg-background px-2 py-1 text-xs font-medium text-foreground",
|
|
178
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
179
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
180
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
181
|
+
)}
|
|
182
|
+
>
|
|
183
|
+
Try again
|
|
184
|
+
</button>
|
|
185
|
+
<button
|
|
186
|
+
type="button"
|
|
187
|
+
onClick={edit.clearError}
|
|
188
|
+
aria-label="Dismiss error"
|
|
189
|
+
className={cn(
|
|
190
|
+
"rounded-md px-2 py-1 text-xs font-medium text-muted-foreground",
|
|
191
|
+
"hover:bg-accent hover:text-foreground",
|
|
192
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
193
|
+
)}
|
|
194
|
+
>
|
|
195
|
+
Dismiss
|
|
196
|
+
</button>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
)}
|
|
200
|
+
|
|
201
|
+
{/* Footer: target summary + actions */}
|
|
202
|
+
<div className="flex items-center justify-between gap-3">
|
|
203
|
+
<p className="text-xs text-muted-foreground" aria-live="polite">
|
|
204
|
+
{targetSummary(edit.validation.status, edit.isDirty, edit.target)}
|
|
205
|
+
</p>
|
|
206
|
+
<div className="flex gap-2">
|
|
207
|
+
<button
|
|
208
|
+
type="button"
|
|
209
|
+
onClick={() => onOpenChange(false)}
|
|
210
|
+
disabled={edit.isApplying}
|
|
211
|
+
className={cn(
|
|
212
|
+
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
213
|
+
"border border-input bg-background text-foreground",
|
|
214
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
215
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
216
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
217
|
+
)}
|
|
218
|
+
>
|
|
219
|
+
Cancel
|
|
220
|
+
</button>
|
|
221
|
+
<button
|
|
222
|
+
type="button"
|
|
223
|
+
onClick={handleApply}
|
|
224
|
+
disabled={!canApply}
|
|
225
|
+
className={cn(
|
|
226
|
+
"rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
|
|
227
|
+
"bg-primary text-primary-foreground hover:bg-primary-hover",
|
|
228
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
229
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
230
|
+
)}
|
|
231
|
+
>
|
|
232
|
+
{edit.isApplying ? "Applying…" : "Apply changes"}
|
|
233
|
+
</button>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
</dialog>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function targetSummary(
|
|
242
|
+
validationStatus: "empty" | "invalid" | "valid",
|
|
243
|
+
isDirty: boolean,
|
|
244
|
+
target: ReturnType<typeof useEditResourceYaml>["target"],
|
|
245
|
+
): string {
|
|
246
|
+
if (validationStatus !== "valid") return "";
|
|
247
|
+
if (!isDirty) return "No changes yet.";
|
|
248
|
+
if (target === null) return "Checking what applying will do…";
|
|
249
|
+
switch (target.action) {
|
|
250
|
+
case "update":
|
|
251
|
+
return `Applying will update ${target.slug}.`;
|
|
252
|
+
case "create":
|
|
253
|
+
return `Applying will create ${target.slug} — the name or slug changed.`;
|
|
254
|
+
case "unknown":
|
|
255
|
+
return `Applying will create or update ${target.slug}.`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function EditorLoading({ label = "Loading editor…" }: { readonly label?: string }) {
|
|
260
|
+
return (
|
|
261
|
+
<div className="flex h-80 items-center justify-center rounded-md border border-border bg-muted text-sm text-muted-foreground">
|
|
262
|
+
{label}
|
|
263
|
+
</div>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@stigmer/theme";
|
|
4
|
+
|
|
5
|
+
/** Props for {@link RedactedSecretsNotice}. */
|
|
6
|
+
export interface RedactedSecretsNoticeProps {
|
|
7
|
+
/** Additional CSS classes for the root container. */
|
|
8
|
+
readonly className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Inline explanation shown when manifest content contains `***REDACTED***`
|
|
13
|
+
* secret markers, so the marker reads as a contract rather than a bug:
|
|
14
|
+
* applying it preserves the stored secret; replacing it sets a new value.
|
|
15
|
+
*
|
|
16
|
+
* Shared by {@link EditResourceYamlDialog} and {@link ApplyManifestDialog}.
|
|
17
|
+
*/
|
|
18
|
+
export function RedactedSecretsNotice({ className }: RedactedSecretsNoticeProps) {
|
|
19
|
+
return (
|
|
20
|
+
<p
|
|
21
|
+
className={cn(
|
|
22
|
+
"rounded-md border border-border bg-muted px-3 py-2 text-xs text-muted-foreground",
|
|
23
|
+
className,
|
|
24
|
+
)}
|
|
25
|
+
>
|
|
26
|
+
Secret values are shown as <code className="font-mono">***REDACTED***</code>.
|
|
27
|
+
Applying keeps the stored secrets; replace a marker to set a new value.
|
|
28
|
+
</p>
|
|
29
|
+
);
|
|
30
|
+
}
|