@object-ui/app-shell 6.2.2 → 7.0.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/CHANGELOG.md +967 -0
- package/README.md +292 -0
- package/dist/assistant/assistantBus.d.ts +72 -0
- package/dist/assistant/assistantBus.js +133 -0
- package/dist/chrome/CommandPalette.d.ts +1 -1
- package/dist/chrome/CommandPalette.js +26 -22
- package/dist/chrome/ConditionalAuthWrapper.d.ts +1 -1
- package/dist/chrome/ConsoleToaster.d.ts +1 -1
- package/dist/chrome/ConsoleToaster.js +3 -1
- package/dist/chrome/ErrorBoundary.d.ts +1 -1
- package/dist/chrome/KeyboardShortcutsDialog.d.ts +1 -1
- package/dist/chrome/KeyboardShortcutsDialog.js +16 -5
- package/dist/chrome/LoadingScreen.d.ts +1 -1
- package/dist/chrome/LoadingScreen.js +22 -26
- package/dist/chrome/RouteFader.d.ts +1 -1
- package/dist/chrome/ThemeProvider.d.ts +1 -1
- package/dist/components/ManagedByBadge.d.ts +1 -1
- package/dist/console/AppContent.d.ts +1 -1
- package/dist/console/AppContent.js +170 -37
- package/dist/console/ConsoleShell.d.ts +7 -7
- package/dist/console/ConsoleShell.js +32 -3
- package/dist/console/ai/AiChatPage.d.ts +88 -1
- package/dist/console/ai/AiChatPage.js +743 -66
- package/dist/console/ai/ConversationsSidebar.d.ts +26 -1
- package/dist/console/ai/ConversationsSidebar.js +149 -34
- package/dist/console/ai/LiveCanvas.d.ts +22 -0
- package/dist/console/ai/LiveCanvas.js +78 -0
- package/dist/console/ai/reconcileTurn.d.ts +8 -0
- package/dist/console/ai/reconcileTurn.js +20 -0
- package/dist/console/auth/AuthPageLayout.d.ts +1 -1
- package/dist/console/auth/ForgotPasswordPage.d.ts +1 -1
- package/dist/console/auth/LoginPage.d.ts +1 -1
- package/dist/console/auth/RegisterPage.d.ts +1 -1
- package/dist/console/auth/RegisterPage.js +23 -3
- package/dist/console/cloud-connection/CloudConnectionPanel.d.ts +1 -0
- package/dist/console/cloud-connection/CloudConnectionPanel.js +169 -0
- package/dist/console/home/AppCard.d.ts +1 -1
- package/dist/console/home/AppCard.js +6 -12
- package/dist/console/home/HomeAppsStrip.d.ts +8 -0
- package/dist/console/home/HomeAppsStrip.js +61 -0
- package/dist/console/home/HomeLayout.d.ts +1 -1
- package/dist/console/home/HomeLayout.js +3 -1
- package/dist/console/home/HomePage.d.ts +1 -2
- package/dist/console/home/HomePage.js +149 -21
- package/dist/console/home/HomeRail.d.ts +22 -0
- package/dist/console/home/HomeRail.js +62 -0
- package/dist/console/home/QuickActions.d.ts +1 -1
- package/dist/console/home/QuickActions.js +3 -11
- package/dist/console/home/RecentApps.d.ts +1 -1
- package/dist/console/home/RecentApps.js +2 -2
- package/dist/console/home/StarredApps.d.ts +1 -1
- package/dist/console/home/StarredApps.js +2 -2
- package/dist/console/marketplace/InstalledListWidget.d.ts +1 -0
- package/dist/console/marketplace/InstalledListWidget.js +93 -0
- package/dist/console/marketplace/MarkdownText.d.ts +1 -1
- package/dist/console/marketplace/MarketplaceAccessDenied.d.ts +1 -1
- package/dist/console/marketplace/MarketplaceInstalledPage.d.ts +8 -14
- package/dist/console/marketplace/MarketplaceInstalledPage.js +14 -66
- package/dist/console/marketplace/MarketplacePackagePage.d.ts +1 -1
- package/dist/console/marketplace/MarketplacePackagePage.js +249 -8
- package/dist/console/marketplace/MarketplacePage.d.ts +1 -1
- package/dist/console/marketplace/MarketplacePage.js +60 -3
- package/dist/console/marketplace/PackageIcon.d.ts +1 -1
- package/dist/console/marketplace/PluginDisclosure.d.ts +14 -0
- package/dist/console/marketplace/PluginDisclosure.js +38 -0
- package/dist/console/marketplace/marketplaceApi.d.ts +123 -0
- package/dist/console/marketplace/marketplaceApi.js +254 -1
- package/dist/console/organizations/CreateWorkspaceDialog.d.ts +1 -1
- package/dist/console/organizations/OrganizationsLayout.d.ts +1 -1
- package/dist/console/organizations/OrganizationsPage.d.ts +1 -1
- package/dist/console/organizations/manage/AcceptInvitationPage.d.ts +1 -1
- package/dist/console/organizations/manage/InvitationsPage.d.ts +1 -1
- package/dist/console/organizations/manage/InviteMemberDialog.d.ts +1 -1
- package/dist/console/organizations/manage/MembersPage.d.ts +1 -1
- package/dist/console/organizations/manage/OrganizationLayout.d.ts +1 -1
- package/dist/console/organizations/manage/SettingsPage.d.ts +1 -1
- package/dist/context/CommandPaletteProvider.d.ts +44 -0
- package/dist/context/CommandPaletteProvider.js +71 -0
- package/dist/context/FavoritesProvider.d.ts +1 -1
- package/dist/context/NavigationContext.d.ts +1 -1
- package/dist/context/RecentItemsProvider.d.ts +2 -2
- package/dist/context/UserStateAdapters.d.ts +1 -1
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.js +1 -0
- package/dist/hooks/index.d.ts +5 -2
- package/dist/hooks/index.js +4 -1
- package/dist/hooks/useActionModal.d.ts +53 -0
- package/dist/hooks/useActionModal.js +111 -0
- package/dist/hooks/useChatConversation.d.ts +107 -4
- package/dist/hooks/useChatConversation.js +253 -25
- package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
- package/dist/hooks/useConsoleActionRuntime.js +560 -0
- package/dist/hooks/useConversationList.js +61 -3
- package/dist/hooks/useHomeInbox.d.ts +13 -0
- package/dist/hooks/useHomeInbox.js +142 -0
- package/dist/hooks/useNavPins.js +17 -23
- package/dist/hooks/useNavigationSync.d.ts +33 -0
- package/dist/hooks/useNavigationSync.js +98 -12
- package/dist/hooks/useReconcileOnError.d.ts +40 -0
- package/dist/hooks/useReconcileOnError.js +37 -0
- package/dist/hooks/useRecordApprovals.d.ts +18 -19
- package/dist/hooks/useRecordApprovals.js +24 -40
- package/dist/hooks/useResponsiveSidebar.js +14 -5
- package/dist/hooks/useSettleSignal.d.ts +19 -0
- package/dist/hooks/useSettleSignal.js +20 -0
- package/dist/hooks/useTrackRouteAsRecent.js +35 -0
- package/dist/hooks/useUrlOverlay.d.ts +62 -0
- package/dist/hooks/useUrlOverlay.js +88 -0
- package/dist/index.d.ts +16 -7
- package/dist/index.js +12 -4
- package/dist/layout/ActivityFeed.d.ts +1 -1
- package/dist/layout/AppHeader.d.ts +3 -2
- package/dist/layout/AppHeader.js +237 -72
- package/dist/layout/AppSidebar.d.ts +2 -1
- package/dist/layout/AppSidebar.js +26 -46
- package/dist/layout/AppSwitcher.d.ts +2 -1
- package/dist/layout/AppSwitcher.js +9 -5
- package/dist/layout/AuthPageLayout.d.ts +1 -1
- package/dist/layout/ConnectionStatus.d.ts +1 -1
- package/dist/layout/ConnectionStatus.js +9 -6
- package/dist/layout/ConsoleChatbotFab.d.ts +19 -1
- package/dist/layout/ConsoleChatbotFab.js +16 -2
- package/dist/layout/ConsoleFloatingChatbot.d.ts +32 -2
- package/dist/layout/ConsoleFloatingChatbot.js +374 -41
- package/dist/layout/ConsoleLayout.d.ts +1 -1
- package/dist/layout/ConsoleLayout.js +27 -11
- package/dist/layout/ContextSelectors.d.ts +44 -0
- package/dist/layout/ContextSelectors.js +218 -0
- package/dist/layout/InboxPopover.d.ts +6 -1
- package/dist/layout/InboxPopover.js +25 -6
- package/dist/layout/LocaleSwitcher.d.ts +1 -1
- package/dist/layout/LocalizedSidebarTrigger.d.ts +2 -0
- package/dist/layout/LocalizedSidebarTrigger.js +15 -0
- package/dist/layout/MobileViewSwitcherContext.d.ts +1 -1
- package/dist/layout/ModeToggle.d.ts +1 -1
- package/dist/layout/PageHeader.d.ts +1 -1
- package/dist/layout/UnifiedSidebar.d.ts +2 -1
- package/dist/layout/UnifiedSidebar.js +116 -15
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.js +1 -0
- package/dist/observability/settleSignal.d.ts +64 -0
- package/dist/observability/settleSignal.js +131 -0
- package/dist/preview/DraftChangesPanel.d.ts +19 -0
- package/dist/preview/DraftChangesPanel.js +114 -0
- package/dist/preview/DraftPreviewBar.d.ts +8 -0
- package/dist/preview/DraftPreviewBar.js +86 -0
- package/dist/preview/PreviewDraftEmptyState.d.ts +16 -0
- package/dist/preview/PreviewDraftEmptyState.js +47 -0
- package/dist/preview/PreviewModeContext.d.ts +57 -0
- package/dist/preview/PreviewModeContext.js +99 -0
- package/dist/preview/UnpublishedAppBar.d.ts +8 -0
- package/dist/preview/UnpublishedAppBar.js +79 -0
- package/dist/preview/draftStatus.d.ts +20 -0
- package/dist/preview/draftStatus.js +27 -0
- package/dist/preview/usePublishAllDrafts.d.ts +18 -0
- package/dist/preview/usePublishAllDrafts.js +106 -0
- package/dist/providers/AdapterProvider.d.ts +1 -1
- package/dist/providers/AdapterProvider.js +6 -1
- package/dist/providers/ExpressionProvider.d.ts +1 -1
- package/dist/providers/MetadataProvider.d.ts +17 -2
- package/dist/providers/MetadataProvider.js +183 -12
- package/dist/runtime-config.d.ts +46 -2
- package/dist/runtime-config.js +39 -2
- package/dist/services/builtinComponents.js +68 -59
- package/dist/skeletons/SkeletonDashboard.d.ts +1 -1
- package/dist/skeletons/SkeletonDetail.d.ts +1 -1
- package/dist/skeletons/SkeletonGrid.d.ts +1 -1
- package/dist/utils/appRoute.d.ts +21 -0
- package/dist/utils/appRoute.js +25 -0
- package/dist/utils/deriveRelatedLists.d.ts +54 -0
- package/dist/utils/deriveRelatedLists.js +91 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/managedByEmptyState.d.ts +8 -1
- package/dist/utils/managedByEmptyState.js +13 -7
- package/dist/utils/preferLocal.d.ts +18 -0
- package/dist/utils/preferLocal.js +24 -0
- package/dist/views/ActionConfirmDialog.d.ts +1 -1
- package/dist/views/ActionConfirmDialog.js +3 -1
- package/dist/views/ActionParamDialog.d.ts +6 -1
- package/dist/views/ActionParamDialog.js +9 -3
- package/dist/views/ActionResultDialog.d.ts +13 -0
- package/dist/views/ActionResultDialog.js +134 -0
- package/dist/views/ComponentNavView.d.ts +14 -1
- package/dist/views/CreateViewDialog.d.ts +1 -1
- package/dist/views/DashboardConfigPanel.d.ts +28 -0
- package/dist/views/DashboardConfigPanel.js +81 -0
- package/dist/views/DashboardView.d.ts +4 -3
- package/dist/views/DashboardView.js +38 -239
- package/dist/views/FlowRunner.d.ts +59 -0
- package/dist/views/FlowRunner.js +153 -0
- package/dist/views/InterfaceListPage.d.ts +49 -0
- package/dist/views/InterfaceListPage.js +347 -0
- package/dist/views/MetadataInspector.d.ts +2 -2
- package/dist/views/ObjectView.d.ts +1 -1
- package/dist/views/ObjectView.js +209 -532
- package/dist/views/PageView.d.ts +8 -3
- package/dist/views/PageView.js +45 -32
- package/dist/views/RecordDetailView.d.ts +1 -1
- package/dist/views/RecordDetailView.js +363 -148
- package/dist/views/RecordFormPage.d.ts +1 -1
- package/dist/views/RecordFormPage.js +26 -1
- package/dist/views/ReportConfigPanel.d.ts +37 -0
- package/dist/views/ReportConfigPanel.js +85 -0
- package/dist/views/ReportView.d.ts +1 -1
- package/dist/views/ReportView.js +116 -7
- package/dist/views/RuntimeDraftBar.d.ts +30 -0
- package/dist/views/RuntimeDraftBar.js +112 -0
- package/dist/views/SearchResultsPage.d.ts +1 -1
- package/dist/views/SearchResultsPage.js +8 -18
- package/dist/views/ViewConfigPanel.d.ts +24 -17
- package/dist/views/ViewConfigPanel.js +121 -77
- package/dist/views/index.d.ts +1 -1
- package/dist/views/index.js +1 -1
- package/dist/views/metadata-admin/AuditPanel.d.ts +28 -0
- package/dist/views/metadata-admin/AuditPanel.js +79 -0
- package/dist/views/metadata-admin/DiagnosticsPage.d.ts +20 -0
- package/dist/views/metadata-admin/DiagnosticsPage.js +69 -0
- package/dist/views/metadata-admin/DirectoryPage.d.ts +16 -1
- package/dist/views/metadata-admin/DirectoryPage.js +113 -24
- package/dist/views/metadata-admin/DraftReviewPanel.d.ts +33 -0
- package/dist/views/metadata-admin/DraftReviewPanel.js +77 -0
- package/dist/views/metadata-admin/EmbeddedItemEditor.d.ts +17 -1
- package/dist/views/metadata-admin/EmbeddedItemEditor.js +15 -8
- package/dist/views/metadata-admin/JsonSourceEditor.d.ts +37 -0
- package/dist/views/metadata-admin/JsonSourceEditor.js +178 -0
- package/dist/views/metadata-admin/LayeredDiff.d.ts +39 -1
- package/dist/views/metadata-admin/LayeredDiff.js +171 -5
- package/dist/views/metadata-admin/MetadataDetailDrawer.d.ts +15 -1
- package/dist/views/metadata-admin/MetadataTypeActions.d.ts +48 -0
- package/dist/views/metadata-admin/MetadataTypeActions.js +165 -0
- package/dist/views/metadata-admin/PackagesPage.d.ts +18 -0
- package/dist/views/metadata-admin/PackagesPage.js +395 -0
- package/dist/views/metadata-admin/PageShell.d.ts +1 -1
- package/dist/views/metadata-admin/PageShell.js +9 -4
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +35 -1
- package/dist/views/metadata-admin/QuickFind.d.ts +21 -1
- package/dist/views/metadata-admin/QuickFind.js +6 -3
- package/dist/views/metadata-admin/RelatedPanel.d.ts +24 -1
- package/dist/views/metadata-admin/RelatedPanel.js +20 -18
- package/dist/views/metadata-admin/ResourceEditPage.d.ts +40 -1
- package/dist/views/metadata-admin/ResourceEditPage.js +1223 -60
- package/dist/views/metadata-admin/ResourceHistoryPage.d.ts +39 -1
- package/dist/views/metadata-admin/ResourceHistoryPage.js +66 -16
- package/dist/views/metadata-admin/ResourceListPage.d.ts +13 -1
- package/dist/views/metadata-admin/ResourceListPage.js +266 -30
- package/dist/views/metadata-admin/ResourceRouter.d.ts +23 -1
- package/dist/views/metadata-admin/SchemaForm.d.ts +34 -1
- package/dist/views/metadata-admin/SchemaForm.js +559 -49
- package/dist/views/metadata-admin/StudioHomePage.d.ts +22 -0
- package/dist/views/metadata-admin/StudioHomePage.js +213 -0
- package/dist/views/metadata-admin/anchors.js +237 -24
- package/dist/views/metadata-admin/clientValidation.d.ts +50 -0
- package/dist/views/metadata-admin/clientValidation.js +169 -0
- package/dist/views/metadata-admin/color-variant-field.d.ts +30 -0
- package/dist/views/metadata-admin/color-variant-field.js +38 -0
- package/dist/views/metadata-admin/createDerive.d.ts +75 -0
- package/dist/views/metadata-admin/createDerive.js +179 -0
- package/dist/views/metadata-admin/dashboard-schema.d.ts +12 -0
- package/dist/views/metadata-admin/dashboard-schema.js +80 -0
- package/dist/views/metadata-admin/datasource/DatasourceResourcePage.d.ts +35 -0
- package/dist/views/metadata-admin/datasource/DatasourceResourcePage.js +327 -0
- package/dist/views/metadata-admin/datasource/register.d.ts +1 -0
- package/dist/views/metadata-admin/datasource/register.js +24 -0
- package/dist/views/metadata-admin/default-inspector-registry.d.ts +49 -0
- package/dist/views/metadata-admin/default-inspector-registry.js +8 -0
- package/dist/views/metadata-admin/default-schemas.js +115 -10
- package/dist/views/metadata-admin/external/ExternalDatasourcePanel.d.ts +27 -0
- package/dist/views/metadata-admin/external/ExternalDatasourcePanel.js +69 -0
- package/dist/views/metadata-admin/external/ImportObjectDialog.d.ts +27 -0
- package/dist/views/metadata-admin/external/ImportObjectDialog.js +77 -0
- package/dist/views/metadata-admin/external/SchemaBrowser.d.ts +16 -0
- package/dist/views/metadata-admin/external/SchemaBrowser.js +74 -0
- package/dist/views/metadata-admin/external/ValidationPanel.d.ts +16 -0
- package/dist/views/metadata-admin/external/ValidationPanel.js +68 -0
- package/dist/views/metadata-admin/external/api.d.ts +100 -0
- package/dist/views/metadata-admin/external/api.js +124 -0
- package/dist/views/metadata-admin/i18n.d.ts +1 -0
- package/dist/views/metadata-admin/i18n.js +1166 -2
- package/dist/views/metadata-admin/index.d.ts +8 -5
- package/dist/views/metadata-admin/index.js +12 -2
- package/dist/views/metadata-admin/inspector-registry.d.ts +51 -0
- package/dist/views/metadata-admin/inspector-registry.js +11 -0
- package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.d.ts +30 -0
- package/dist/views/metadata-admin/inspectors/ActionDefaultInspector.js +180 -0
- package/dist/views/metadata-admin/inspectors/AppNavInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/AppNavInspector.js +110 -0
- package/dist/views/metadata-admin/inspectors/ConditionBuilder.d.ts +29 -0
- package/dist/views/metadata-admin/inspectors/ConditionBuilder.js +154 -0
- package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.d.ts +28 -0
- package/dist/views/metadata-admin/inspectors/DashboardDefaultInspector.js +110 -0
- package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.d.ts +18 -0
- package/dist/views/metadata-admin/inspectors/DashboardWidgetInspector.js +139 -0
- package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/DatasetDefaultInspector.js +107 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +45 -0
- package/dist/views/metadata-admin/inspectors/FlowInspector.d.ts +12 -0
- package/dist/views/metadata-admin/inspectors/FlowInspector.js +9 -0
- package/dist/views/metadata-admin/inspectors/FlowKeyValueField.d.ts +30 -0
- package/dist/views/metadata-admin/inspectors/FlowKeyValueField.js +125 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.d.ts +18 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeConfigField.js +40 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeInspector.d.ts +14 -0
- package/dist/views/metadata-admin/inspectors/FlowNodeInspector.js +140 -0
- package/dist/views/metadata-admin/inspectors/FlowObjectListField.d.ts +26 -0
- package/dist/views/metadata-admin/inspectors/FlowObjectListField.js +105 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.d.ts +83 -0
- package/dist/views/metadata-admin/inspectors/FlowReferenceField.js +181 -0
- package/dist/views/metadata-admin/inspectors/FlowStringListField.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/FlowStringListField.js +60 -0
- package/dist/views/metadata-admin/inspectors/InspectorComboField.d.ts +40 -0
- package/dist/views/metadata-admin/inspectors/InspectorComboField.js +61 -0
- package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.d.ts +21 -0
- package/dist/views/metadata-admin/inspectors/ObjectDefaultInspector.js +54 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +330 -0
- package/dist/views/metadata-admin/inspectors/PageBlockInspector.d.ts +48 -0
- package/dist/views/metadata-admin/inspectors/PageBlockInspector.js +332 -0
- package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.d.ts +58 -0
- package/dist/views/metadata-admin/inspectors/ReportDefaultInspector.js +160 -0
- package/dist/views/metadata-admin/inspectors/ViewColumnInspector.d.ts +19 -0
- package/dist/views/metadata-admin/inspectors/ViewColumnInspector.js +144 -0
- package/dist/views/metadata-admin/inspectors/ViewInspector.d.ts +19 -0
- package/dist/views/metadata-admin/inspectors/ViewInspector.js +21 -0
- package/dist/views/metadata-admin/inspectors/ViewVariantInspector.d.ts +54 -0
- package/dist/views/metadata-admin/inspectors/ViewVariantInspector.js +191 -0
- package/dist/views/metadata-admin/inspectors/_shared.d.ts +124 -0
- package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
- package/dist/views/metadata-admin/inspectors/expression-validate.d.ts +26 -0
- package/dist/views/metadata-admin/inspectors/expression-validate.js +66 -0
- package/dist/views/metadata-admin/inspectors/flow-node-config.d.ts +143 -0
- package/dist/views/metadata-admin/inspectors/flow-node-config.js +461 -0
- package/dist/views/metadata-admin/inspectors/index.d.ts +1 -0
- package/dist/views/metadata-admin/inspectors/index.js +45 -0
- package/dist/views/metadata-admin/inspectors/json-schema-to-fields.d.ts +40 -0
- package/dist/views/metadata-admin/inspectors/json-schema-to-fields.js +227 -0
- package/dist/views/metadata-admin/inspectors/useDatasetFields.d.ts +72 -0
- package/dist/views/metadata-admin/inspectors/useDatasetFields.js +0 -0
- package/dist/views/metadata-admin/mergeServerFields.d.ts +65 -0
- package/dist/views/metadata-admin/mergeServerFields.js +56 -0
- package/dist/views/metadata-admin/preview-registry.d.ts +55 -0
- package/dist/views/metadata-admin/previews/ActionPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/ActionPreview.js +238 -0
- package/dist/views/metadata-admin/previews/AddWidgetPicker.d.ts +12 -0
- package/dist/views/metadata-admin/previews/AddWidgetPicker.js +56 -0
- package/dist/views/metadata-admin/previews/AgentPreview.d.ts +24 -0
- package/dist/views/metadata-admin/previews/AgentPreview.js +100 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.d.ts +31 -0
- package/dist/views/metadata-admin/previews/AppNavCanvas.js +260 -0
- package/dist/views/metadata-admin/previews/AppPreview.d.ts +16 -1
- package/dist/views/metadata-admin/previews/AppPreview.js +23 -14
- package/dist/views/metadata-admin/previews/BookPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/BookPreview.js +132 -0
- package/dist/views/metadata-admin/previews/DashboardPreview.d.ts +16 -1
- package/dist/views/metadata-admin/previews/DashboardPreview.js +110 -8
- package/dist/views/metadata-admin/previews/DatasetPreview.d.ts +18 -0
- package/dist/views/metadata-admin/previews/DatasetPreview.js +89 -0
- package/dist/views/metadata-admin/previews/DatasourcePreview.d.ts +23 -0
- package/dist/views/metadata-admin/previews/DatasourcePreview.js +68 -0
- package/dist/views/metadata-admin/previews/EmailTemplatePreview.d.ts +14 -1
- package/dist/views/metadata-admin/previews/FieldStub.d.ts +30 -0
- package/dist/views/metadata-admin/previews/FieldStub.js +104 -0
- package/dist/views/metadata-admin/previews/FieldsListEditor.d.ts +50 -0
- package/dist/views/metadata-admin/previews/FieldsListEditor.js +97 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.d.ts +43 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.js +328 -0
- package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/FlowPreview.js +92 -0
- package/dist/views/metadata-admin/previews/FlowRunsPanel.d.ts +46 -0
- package/dist/views/metadata-admin/previews/FlowRunsPanel.js +97 -0
- package/dist/views/metadata-admin/previews/FlowSimulatorPanel.d.ts +25 -0
- package/dist/views/metadata-admin/previews/FlowSimulatorPanel.js +170 -0
- package/dist/views/metadata-admin/previews/JobPreview.d.ts +28 -0
- package/dist/views/metadata-admin/previews/JobPreview.js +290 -0
- package/dist/views/metadata-admin/previews/ObjectFormCanvas.d.ts +30 -0
- package/dist/views/metadata-admin/previews/ObjectFormCanvas.js +547 -0
- package/dist/views/metadata-admin/previews/ObjectPreview.d.ts +14 -1
- package/dist/views/metadata-admin/previews/ObjectPreview.js +5 -30
- package/dist/views/metadata-admin/previews/OutlineStrip.d.ts +32 -0
- package/dist/views/metadata-admin/previews/OutlineStrip.js +8 -0
- package/dist/views/metadata-admin/previews/PageBlockCanvas.d.ts +49 -0
- package/dist/views/metadata-admin/previews/PageBlockCanvas.js +510 -0
- package/dist/views/metadata-admin/previews/PagePreview.d.ts +10 -1
- package/dist/views/metadata-admin/previews/PagePreview.js +90 -4
- package/dist/views/metadata-admin/previews/PermissionPreview.d.ts +27 -0
- package/dist/views/metadata-admin/previews/PermissionPreview.js +115 -0
- package/dist/views/metadata-admin/previews/PreviewShell.d.ts +29 -6
- package/dist/views/metadata-admin/previews/PreviewShell.js +16 -3
- package/dist/views/metadata-admin/previews/ReportPreview.d.ts +18 -1
- package/dist/views/metadata-admin/previews/ReportPreview.js +23 -15
- package/dist/views/metadata-admin/previews/RolePreview.d.ts +19 -0
- package/dist/views/metadata-admin/previews/RolePreview.js +14 -0
- package/dist/views/metadata-admin/previews/SkillPreview.d.ts +22 -0
- package/dist/views/metadata-admin/previews/SkillPreview.js +34 -0
- package/dist/views/metadata-admin/previews/ToolPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/ToolPreview.js +122 -0
- package/dist/views/metadata-admin/previews/TranslationPreview.d.ts +25 -0
- package/dist/views/metadata-admin/previews/TranslationPreview.js +52 -0
- package/dist/views/metadata-admin/previews/ValidationPreview.d.ts +27 -0
- package/dist/views/metadata-admin/previews/ValidationPreview.js +110 -0
- package/dist/views/metadata-admin/previews/ViewColumnPanes.d.ts +62 -0
- package/dist/views/metadata-admin/previews/ViewColumnPanes.js +140 -0
- package/dist/views/metadata-admin/previews/ViewPreview.d.ts +23 -1
- package/dist/views/metadata-admin/previews/ViewPreview.js +101 -73
- package/dist/views/metadata-admin/previews/block-config.d.ts +82 -0
- package/dist/views/metadata-admin/previews/block-config.js +324 -0
- package/dist/views/metadata-admin/previews/block-types.d.ts +40 -0
- package/dist/views/metadata-admin/previews/block-types.js +110 -0
- package/dist/views/metadata-admin/previews/field-types.d.ts +53 -0
- package/dist/views/metadata-admin/previews/field-types.js +97 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.d.ts +88 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.js +190 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +88 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.js +358 -0
- package/dist/views/metadata-admin/previews/form-preview.d.ts +24 -0
- package/dist/views/metadata-admin/previews/form-preview.js +29 -0
- package/dist/views/metadata-admin/previews/index.js +43 -0
- package/dist/views/metadata-admin/previews/object-fields-bridge.d.ts +66 -0
- package/dist/views/metadata-admin/previews/object-fields-bridge.js +171 -0
- package/dist/views/metadata-admin/previews/object-fields-io.d.ts +109 -0
- package/dist/views/metadata-admin/previews/object-fields-io.js +208 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +91 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.js +2 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.d.ts +8 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +113 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +44 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +316 -0
- package/dist/views/metadata-admin/previews/useDatasetCatalog.d.ts +47 -0
- package/dist/views/metadata-admin/previews/useDatasetCatalog.js +133 -0
- package/dist/views/metadata-admin/previews/useFlowNodePalette.d.ts +44 -0
- package/dist/views/metadata-admin/previews/useFlowNodePalette.js +124 -0
- package/dist/views/metadata-admin/previews/useMetaOptions.d.ts +8 -0
- package/dist/views/metadata-admin/previews/useMetaOptions.js +50 -0
- package/dist/views/metadata-admin/previews/useObjectFields.d.ts +23 -0
- package/dist/views/metadata-admin/previews/useObjectFields.js +79 -0
- package/dist/views/metadata-admin/previews/useObjectOptions.d.ts +8 -0
- package/dist/views/metadata-admin/previews/useObjectOptions.js +43 -0
- package/dist/views/metadata-admin/previews/view-column-io.d.ts +42 -0
- package/dist/views/metadata-admin/previews/view-column-io.js +73 -0
- package/dist/views/metadata-admin/previews/widget-types.d.ts +24 -0
- package/dist/views/metadata-admin/previews/widget-types.js +40 -0
- package/dist/views/metadata-admin/registry.d.ts +140 -19
- package/dist/views/metadata-admin/report-schema.d.ts +26 -0
- package/dist/views/metadata-admin/report-schema.js +121 -0
- package/dist/views/metadata-admin/useMetadata.d.ts +100 -2
- package/dist/views/metadata-admin/useMetadata.js +155 -4
- package/dist/views/metadata-admin/view-item-normalize.d.ts +20 -0
- package/dist/views/metadata-admin/view-item-normalize.js +68 -0
- package/dist/views/metadata-admin/view-schema.d.ts +16 -0
- package/dist/views/metadata-admin/view-schema.js +107 -0
- package/dist/views/metadata-admin/view-variant-model.d.ts +23 -0
- package/dist/views/metadata-admin/view-variant-model.js +64 -0
- package/dist/views/metadata-admin/widgets.d.ts +89 -1
- package/dist/views/metadata-admin/widgets.js +491 -17
- package/dist/views/runtime-metadata-persistence.d.ts +78 -0
- package/dist/views/runtime-metadata-persistence.js +89 -0
- package/dist/views/useOpenRecordList.d.ts +18 -0
- package/dist/views/useOpenRecordList.js +36 -0
- package/dist/views/userFilterUrlState.d.ts +15 -0
- package/dist/views/userFilterUrlState.js +53 -0
- package/dist/views/view-config-adapter.d.ts +38 -0
- package/dist/views/view-config-adapter.js +80 -0
- package/package.json +52 -34
- package/dist/views/DesignDrawer.d.ts +0 -28
- package/dist/views/DesignDrawer.js +0 -51
- package/dist/views/metadata-admin/DesignerEditorWrapper.d.ts +0 -68
- package/dist/views/metadata-admin/DesignerEditorWrapper.js +0 -158
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* DatasourceResourcePage — the `datasource` metadata type's custom ListPage,
|
|
5
|
+
* registered into the metadata-admin engine (`registerMetadataResource`) and
|
|
6
|
+
* reached via the engine route `…/component/metadata/resource?type=datasource`
|
|
7
|
+
* (and the setup left-nav "Datasources" item → `system/metadata/datasource`).
|
|
8
|
+
*
|
|
9
|
+
* datasource is a *side-effectful* metadata type: its records are managed by
|
|
10
|
+
* the framework `datasource-admin` service (secret encryption + connection-pool
|
|
11
|
+
* registration + origin gating), so create/edit/delete + test go through that
|
|
12
|
+
* service's REST (`/api/v1/datasources/*`) rather than the generic sys_metadata
|
|
13
|
+
* write path. The engine still owns the route, shell, and registry slot.
|
|
14
|
+
*
|
|
15
|
+
* Capabilities:
|
|
16
|
+
* - **List** datasources (driver/status/origin).
|
|
17
|
+
* - **Create / edit** a connection with a typed form generated from the
|
|
18
|
+
* selected driver's JSON-Schema `configSchema` (`GET /datasources/drivers`).
|
|
19
|
+
* Credential fields (`format: 'password'`) are routed to the top-level
|
|
20
|
+
* `secret` so they are encrypted into `sys_secret` and never persisted in
|
|
21
|
+
* `config` metadata. Edit prefills from `GET /datasources/:name` (which
|
|
22
|
+
* returns `config` + a `hasSecret` flag, never the credential itself).
|
|
23
|
+
* - **Test** a connection (saved → `POST …/:name/test`; draft in the editor →
|
|
24
|
+
* `POST …/test`).
|
|
25
|
+
* - **Sync objects**: introspect remote tables (`GET …/remote-tables`), pick
|
|
26
|
+
* which to import, generate an object definition for each (`POST …/object-draft`),
|
|
27
|
+
* and create it through the normal metadata channel (`MetadataClient.save('object', …)`).
|
|
28
|
+
* - **Delete** a runtime datasource (`DELETE …/:name`; blocked by the backend
|
|
29
|
+
* while objects are still bound).
|
|
30
|
+
*
|
|
31
|
+
* Code-defined (`origin: 'code'`) datasources are read-only: edit/delete are
|
|
32
|
+
* hidden for them.
|
|
33
|
+
*/
|
|
34
|
+
import * as React from 'react';
|
|
35
|
+
import { toast } from 'sonner';
|
|
36
|
+
import { Loader2, Database, RefreshCw, Plug, Boxes, Plus, Pencil, Trash2, CheckCircle2, XCircle, } from 'lucide-react';
|
|
37
|
+
import { Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Input, Label, Switch, Select, SelectTrigger, SelectContent, SelectItem, SelectValue, } from '@object-ui/components';
|
|
38
|
+
import { createAuthenticatedFetch } from '@object-ui/auth';
|
|
39
|
+
import { useMetadataClient } from '../useMetadata';
|
|
40
|
+
const SCHEMA_MODES = [
|
|
41
|
+
{ value: 'managed', label: 'Managed (ObjectStack owns the schema)' },
|
|
42
|
+
{ value: 'external', label: 'External (read existing schema as-is)' },
|
|
43
|
+
{ value: 'validate-only', label: 'Validate only' },
|
|
44
|
+
];
|
|
45
|
+
const SERVER = (import.meta.env?.VITE_SERVER_URL || '').replace(/\/+$/, '');
|
|
46
|
+
const isPassword = (p) => p.format === 'password';
|
|
47
|
+
/** Build the default config (password props excluded — they live in `secret`). */
|
|
48
|
+
function defaultConfig(driver) {
|
|
49
|
+
const props = driver?.configSchema?.properties ?? {};
|
|
50
|
+
const cfg = {};
|
|
51
|
+
for (const [key, prop] of Object.entries(props)) {
|
|
52
|
+
if (isPassword(prop))
|
|
53
|
+
continue;
|
|
54
|
+
if (prop.default !== undefined)
|
|
55
|
+
cfg[key] = prop.default;
|
|
56
|
+
}
|
|
57
|
+
return cfg;
|
|
58
|
+
}
|
|
59
|
+
export function DatasourceResourcePage(_props) {
|
|
60
|
+
const authFetch = React.useMemo(() => createAuthenticatedFetch(), []);
|
|
61
|
+
const metaClient = useMetadataClient();
|
|
62
|
+
const [rows, setRows] = React.useState([]);
|
|
63
|
+
const [loading, setLoading] = React.useState(true);
|
|
64
|
+
const [busy, setBusy] = React.useState(null);
|
|
65
|
+
const api = React.useCallback(async (path, init) => {
|
|
66
|
+
const res = await authFetch(`${SERVER}${path}`, { credentials: 'include', headers: { 'Content-Type': 'application/json' }, ...init });
|
|
67
|
+
const text = await res.text();
|
|
68
|
+
let body = text;
|
|
69
|
+
try {
|
|
70
|
+
body = JSON.parse(text);
|
|
71
|
+
}
|
|
72
|
+
catch { /* keep text */ }
|
|
73
|
+
if (!res.ok)
|
|
74
|
+
throw new Error((body && (body.message || body.error)) || `HTTP ${res.status}`);
|
|
75
|
+
return body;
|
|
76
|
+
}, [authFetch]);
|
|
77
|
+
const load = React.useCallback(async () => {
|
|
78
|
+
setLoading(true);
|
|
79
|
+
try {
|
|
80
|
+
const data = await api('/api/v1/datasources');
|
|
81
|
+
setRows(Array.isArray(data?.datasources) ? data.datasources : []);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
toast.error(`Load datasources: ${err.message}`);
|
|
85
|
+
setRows([]);
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
setLoading(false);
|
|
89
|
+
}
|
|
90
|
+
}, [api]);
|
|
91
|
+
React.useEffect(() => { void load(); }, [load]);
|
|
92
|
+
const test = async (name) => {
|
|
93
|
+
setBusy(`test:${name}`);
|
|
94
|
+
try {
|
|
95
|
+
const r = await api(`/api/v1/datasources/${encodeURIComponent(name)}/test`, { method: 'POST', body: '{}' });
|
|
96
|
+
toast.success(r?.ok === false ? `${name}: ${r?.error ?? 'failed'}` : `${name}: connection ok${r?.latencyMs != null ? ` (${r.latencyMs}ms)` : ''}`);
|
|
97
|
+
void load();
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
toast.error(`${name}: ${err.message}`);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
setBusy(null);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const remove = async (name) => {
|
|
107
|
+
if (!window.confirm(`Delete datasource “${name}”? This cannot be undone.`))
|
|
108
|
+
return;
|
|
109
|
+
setBusy(`del:${name}`);
|
|
110
|
+
try {
|
|
111
|
+
await api(`/api/v1/datasources/${encodeURIComponent(name)}`, { method: 'DELETE' });
|
|
112
|
+
toast.success(`Deleted ${name}.`);
|
|
113
|
+
void load();
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
toast.error(`Delete ${name}: ${err.message}`);
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
setBusy(null);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
// ── Connection editor (create / edit) ─────────────────────────────────────
|
|
123
|
+
const [drivers, setDrivers] = React.useState([]);
|
|
124
|
+
const [editorOpen, setEditorOpen] = React.useState(false);
|
|
125
|
+
const [editing, setEditing] = React.useState(null);
|
|
126
|
+
const [form, setForm] = React.useState(null);
|
|
127
|
+
const [hasSecret, setHasSecret] = React.useState(false);
|
|
128
|
+
const [savingEditor, setSavingEditor] = React.useState(false);
|
|
129
|
+
const [testMsg, setTestMsg] = React.useState(null);
|
|
130
|
+
const [testingDraft, setTestingDraft] = React.useState(false);
|
|
131
|
+
const ensureDrivers = React.useCallback(async () => {
|
|
132
|
+
if (drivers.length)
|
|
133
|
+
return drivers;
|
|
134
|
+
try {
|
|
135
|
+
const data = await api('/api/v1/datasources/drivers');
|
|
136
|
+
const list = Array.isArray(data?.drivers) ? data.drivers : [];
|
|
137
|
+
setDrivers(list);
|
|
138
|
+
return list;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
toast.error(`Load drivers: ${err.message}`);
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
}, [api, drivers]);
|
|
145
|
+
const selectedDriver = React.useMemo(() => drivers.find((d) => d.id === form?.driver), [drivers, form?.driver]);
|
|
146
|
+
const openCreate = async () => {
|
|
147
|
+
const list = await ensureDrivers();
|
|
148
|
+
const first = list.find((d) => d.id !== 'memory') ?? list[0];
|
|
149
|
+
setEditing(null);
|
|
150
|
+
setHasSecret(false);
|
|
151
|
+
setTestMsg(null);
|
|
152
|
+
setForm({
|
|
153
|
+
name: '',
|
|
154
|
+
label: '',
|
|
155
|
+
driver: first?.id ?? '',
|
|
156
|
+
schemaMode: 'managed',
|
|
157
|
+
config: defaultConfig(first),
|
|
158
|
+
secret: '',
|
|
159
|
+
});
|
|
160
|
+
setEditorOpen(true);
|
|
161
|
+
};
|
|
162
|
+
const openEdit = async (row) => {
|
|
163
|
+
const list = await ensureDrivers();
|
|
164
|
+
setBusy(`edit:${row.name}`);
|
|
165
|
+
try {
|
|
166
|
+
const data = await api(`/api/v1/datasources/${encodeURIComponent(row.name)}`);
|
|
167
|
+
const ds = data?.datasource ?? {};
|
|
168
|
+
setEditing(row.name);
|
|
169
|
+
setHasSecret(Boolean(ds.hasSecret));
|
|
170
|
+
setTestMsg(null);
|
|
171
|
+
setForm({
|
|
172
|
+
name: ds.name ?? row.name,
|
|
173
|
+
label: ds.label ?? '',
|
|
174
|
+
driver: ds.driver ?? row.driver ?? (list[0]?.id ?? ''),
|
|
175
|
+
schemaMode: ds.schemaMode ?? 'managed',
|
|
176
|
+
config: { ...(ds.config ?? {}) },
|
|
177
|
+
secret: '',
|
|
178
|
+
});
|
|
179
|
+
setEditorOpen(true);
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
toast.error(`Open ${row.name}: ${err.message}`);
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
setBusy(null);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const onDriverChange = (id) => {
|
|
189
|
+
setForm((f) => (f ? { ...f, driver: id, config: defaultConfig(drivers.find((d) => d.id === id)), secret: '' } : f));
|
|
190
|
+
setTestMsg(null);
|
|
191
|
+
};
|
|
192
|
+
const setConfigValue = (key, value) => setForm((f) => (f ? { ...f, config: { ...f.config, [key]: value } } : f));
|
|
193
|
+
/** Assemble the request body, splitting the credential into `secret`. */
|
|
194
|
+
const draftBody = (f) => {
|
|
195
|
+
const body = {
|
|
196
|
+
label: f.label || undefined,
|
|
197
|
+
driver: f.driver,
|
|
198
|
+
schemaMode: f.schemaMode,
|
|
199
|
+
config: f.config,
|
|
200
|
+
};
|
|
201
|
+
if (f.secret)
|
|
202
|
+
body.secret = f.secret;
|
|
203
|
+
return body;
|
|
204
|
+
};
|
|
205
|
+
const testDraft = async () => {
|
|
206
|
+
if (!form)
|
|
207
|
+
return;
|
|
208
|
+
setTestingDraft(true);
|
|
209
|
+
setTestMsg(null);
|
|
210
|
+
try {
|
|
211
|
+
const r = await api('/api/v1/datasources/test', { method: 'POST', body: JSON.stringify({ driver: form.driver, config: form.config, ...(form.secret ? { secret: form.secret } : {}) }) });
|
|
212
|
+
const res = r?.result ?? r;
|
|
213
|
+
if (res?.ok === false)
|
|
214
|
+
setTestMsg({ ok: false, text: res?.error ?? 'Connection failed' });
|
|
215
|
+
else
|
|
216
|
+
setTestMsg({ ok: true, text: `Connection ok${res?.latencyMs != null ? ` (${res.latencyMs}ms)` : ''}` });
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
setTestMsg({ ok: false, text: err.message });
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
setTestingDraft(false);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
const saveEditor = async () => {
|
|
226
|
+
if (!form)
|
|
227
|
+
return;
|
|
228
|
+
setSavingEditor(true);
|
|
229
|
+
try {
|
|
230
|
+
if (editing) {
|
|
231
|
+
await api(`/api/v1/datasources/${encodeURIComponent(editing)}`, { method: 'PATCH', body: JSON.stringify(draftBody(form)) });
|
|
232
|
+
toast.success(`Updated ${editing}.`);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
await api('/api/v1/datasources', { method: 'POST', body: JSON.stringify({ name: form.name, ...draftBody(form) }) });
|
|
236
|
+
toast.success(`Created ${form.name}.`);
|
|
237
|
+
}
|
|
238
|
+
setEditorOpen(false);
|
|
239
|
+
void load();
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
toast.error(`Save: ${err.message}`);
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
setSavingEditor(false);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
const nameValid = editing ? true : /^[a-z_][a-z0-9_]*$/.test(form?.name ?? '');
|
|
249
|
+
const canSave = !!form && !!form.driver && nameValid && !savingEditor;
|
|
250
|
+
// ── Sync dialog ──────────────────────────────────────────────────────────
|
|
251
|
+
const [syncName, setSyncName] = React.useState(null);
|
|
252
|
+
const [tables, setTables] = React.useState(null);
|
|
253
|
+
const [selected, setSelected] = React.useState(new Set());
|
|
254
|
+
const [syncing, setSyncing] = React.useState(false);
|
|
255
|
+
const openSync = async (name) => {
|
|
256
|
+
setSyncName(name);
|
|
257
|
+
setTables(null);
|
|
258
|
+
setSelected(new Set());
|
|
259
|
+
try {
|
|
260
|
+
const data = await api(`/api/v1/datasources/${encodeURIComponent(name)}/remote-tables`);
|
|
261
|
+
setTables(Array.isArray(data?.tables) ? data.tables : []);
|
|
262
|
+
}
|
|
263
|
+
catch (err) {
|
|
264
|
+
toast.error(`Introspect ${name}: ${err.message}`);
|
|
265
|
+
setTables([]);
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
const toggle = (t) => setSelected((prev) => {
|
|
269
|
+
const next = new Set(prev);
|
|
270
|
+
if (next.has(t))
|
|
271
|
+
next.delete(t);
|
|
272
|
+
else
|
|
273
|
+
next.add(t);
|
|
274
|
+
return next;
|
|
275
|
+
});
|
|
276
|
+
const runSync = async () => {
|
|
277
|
+
if (!syncName || selected.size === 0)
|
|
278
|
+
return;
|
|
279
|
+
setSyncing(true);
|
|
280
|
+
let ok = 0;
|
|
281
|
+
const failures = [];
|
|
282
|
+
for (const table of selected) {
|
|
283
|
+
try {
|
|
284
|
+
const { draft } = await api(`/api/v1/datasources/${encodeURIComponent(syncName)}/object-draft`, {
|
|
285
|
+
method: 'POST',
|
|
286
|
+
body: JSON.stringify({ table }),
|
|
287
|
+
});
|
|
288
|
+
await metaClient.save('object', draft.name, draft.definition);
|
|
289
|
+
ok += 1;
|
|
290
|
+
}
|
|
291
|
+
catch (err) {
|
|
292
|
+
failures.push(`${table}: ${err.message}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
setSyncing(false);
|
|
296
|
+
if (ok)
|
|
297
|
+
toast.success(`Synced ${ok} object${ok > 1 ? 's' : ''} from ${syncName}.`);
|
|
298
|
+
if (failures.length)
|
|
299
|
+
toast.error(`Failed: ${failures.join('; ')}`);
|
|
300
|
+
setSyncName(null);
|
|
301
|
+
};
|
|
302
|
+
const renderField = (key, prop) => {
|
|
303
|
+
const label = prop.title || key;
|
|
304
|
+
const required = (selectedDriver?.configSchema?.required ?? []).includes(key);
|
|
305
|
+
if (isPassword(prop)) {
|
|
306
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "text-xs", children: [label, required && !editing ? ' *' : ''] }), _jsx(Input, { type: "password", value: form?.secret ?? '', placeholder: editing && hasSecret ? '•••••••• (leave blank to keep)' : '', onChange: (e) => setForm((f) => (f ? { ...f, secret: e.target.value } : f)) }), prop.description && _jsx("p", { className: "text-[11px] text-muted-foreground", children: prop.description })] }, key));
|
|
307
|
+
}
|
|
308
|
+
const value = form?.config[key];
|
|
309
|
+
if (prop.type === 'boolean') {
|
|
310
|
+
return (_jsxs("div", { className: "flex items-center justify-between gap-2 py-1", children: [_jsxs("div", { children: [_jsx(Label, { className: "text-xs", children: label }), prop.description && _jsx("p", { className: "text-[11px] text-muted-foreground", children: prop.description })] }), _jsx(Switch, { checked: Boolean(value), onCheckedChange: (c) => setConfigValue(key, c) })] }, key));
|
|
311
|
+
}
|
|
312
|
+
if (Array.isArray(prop.enum)) {
|
|
313
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "text-xs", children: [label, required ? ' *' : ''] }), _jsxs(Select, { value: value != null ? String(value) : '', onValueChange: (v) => setConfigValue(key, v), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Select\u2026" }) }), _jsx(SelectContent, { children: prop.enum.map((opt) => _jsx(SelectItem, { value: String(opt), children: String(opt) }, String(opt))) })] })] }, key));
|
|
314
|
+
}
|
|
315
|
+
const isNum = prop.type === 'number' || prop.type === 'integer';
|
|
316
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "text-xs", children: [label, required ? ' *' : ''] }), _jsx(Input, { type: isNum ? 'number' : 'text', value: value != null ? String(value) : '', onChange: (e) => setConfigValue(key, isNum ? (e.target.value === '' ? undefined : Number(e.target.value)) : e.target.value) }), prop.description && _jsx("p", { className: "text-[11px] text-muted-foreground", children: prop.description })] }, key));
|
|
317
|
+
};
|
|
318
|
+
return (_jsxs("div", { className: "mx-auto max-w-4xl px-6 py-8", children: [_jsxs("div", { className: "mb-6 flex items-center justify-between", children: [_jsxs("div", { children: [_jsxs("h1", { className: "flex items-center gap-2 text-xl font-semibold", children: [_jsx(Database, { className: "h-5 w-5" }), " Datasources"] }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Connect external databases and sync their tables in as objects." })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => void load(), disabled: loading, children: [_jsx(RefreshCw, { className: 'mr-1.5 h-4 w-4' + (loading ? ' animate-spin' : '') }), " Refresh"] }), _jsxs(Button, { size: "sm", onClick: () => void openCreate(), children: [_jsx(Plus, { className: "mr-1.5 h-4 w-4" }), " New datasource"] })] })] }), loading ? (_jsxs("div", { className: "flex items-center gap-2 py-12 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Loading\u2026"] })) : rows.length === 0 ? (_jsxs("div", { className: "rounded-lg border border-dashed bg-muted/20 py-16 text-center text-sm text-muted-foreground", children: ["No datasources yet. Click ", _jsx("span", { className: "font-medium", children: "New datasource" }), " to connect one."] })) : (_jsx("div", { className: "divide-y rounded-lg border bg-card", children: rows.map((ds) => {
|
|
319
|
+
const isCode = ds.origin === 'code';
|
|
320
|
+
return (_jsxs("div", { className: "flex items-center gap-3 px-4 py-3", children: [_jsx(Database, { className: "h-4 w-4 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium", children: ds.label || ds.name }), _jsx("code", { className: "text-[11px] text-muted-foreground", children: ds.name })] }), _jsxs("div", { className: "mt-0.5 flex items-center gap-2 text-[11px] text-muted-foreground", children: [_jsx("span", { className: "rounded bg-muted px-1.5 py-0.5 font-mono", children: ds.driver }), ds.status && _jsxs("span", { children: ["\u00B7 ", ds.status] }), ds.origin && _jsxs("span", { children: ["\u00B7 ", ds.origin] })] })] }), _jsxs(Button, { variant: "ghost", size: "sm", disabled: busy === `test:${ds.name}`, onClick: () => void test(ds.name), children: [busy === `test:${ds.name}` ? _jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : _jsx(Plug, { className: "mr-1.5 h-4 w-4" }), " Test"] }), _jsxs(Button, { variant: "secondary", size: "sm", onClick: () => void openSync(ds.name), children: [_jsx(Boxes, { className: "mr-1.5 h-4 w-4" }), " Sync objects"] }), !isCode && (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8", title: "Edit", disabled: busy === `edit:${ds.name}`, onClick: () => void openEdit(ds), children: busy === `edit:${ds.name}` ? _jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : _jsx(Pencil, { className: "h-4 w-4" }) }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 text-destructive hover:text-destructive", title: "Delete", disabled: busy === `del:${ds.name}`, onClick: () => void remove(ds.name), children: busy === `del:${ds.name}` ? _jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : _jsx(Trash2, { className: "h-4 w-4" }) })] }))] }, ds.name));
|
|
321
|
+
}) })), _jsx(Dialog, { open: editorOpen, onOpenChange: (o) => { if (!o)
|
|
322
|
+
setEditorOpen(false); }, children: _jsxs(DialogContent, { className: "max-w-lg", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: editing ? `Edit “${editing}”` : 'New datasource' }), _jsx(DialogDescription, { children: editing ? 'Update the connection. Leave the credential blank to keep the current one.' : 'Connect an external database. Credentials are encrypted and never stored in metadata.' })] }), form && (_jsxs("div", { className: "max-h-[60vh] space-y-3 overflow-y-auto pr-1", children: [!editing && (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Name *" }), _jsx(Input, { value: form.name, placeholder: "my_database", onChange: (e) => setForm((f) => (f ? { ...f, name: e.target.value } : f)) }), !nameValid && form.name.length > 0 && (_jsx("p", { className: "text-[11px] text-destructive", children: "Lowercase letters, digits, and underscores; must not start with a digit." }))] })), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Label" }), _jsx(Input, { value: form.label, placeholder: "Human-friendly name", onChange: (e) => setForm((f) => (f ? { ...f, label: e.target.value } : f)) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Driver *" }), _jsxs(Select, { value: form.driver, onValueChange: onDriverChange, disabled: !!editing, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Choose a driver" }) }), _jsx(SelectContent, { children: drivers.map((d) => _jsx(SelectItem, { value: d.id, children: d.label }, d.id)) })] }), selectedDriver?.description && _jsx("p", { className: "text-[11px] text-muted-foreground", children: selectedDriver.description })] }), Object.entries(selectedDriver?.configSchema?.properties ?? {}).map(([k, p]) => renderField(k, p)), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Schema mode" }), _jsxs(Select, { value: form.schemaMode, onValueChange: (v) => setForm((f) => (f ? { ...f, schemaMode: v } : f)), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: SCHEMA_MODES.map((m) => _jsx(SelectItem, { value: m.value, children: m.label }, m.value)) })] })] }), testMsg && (_jsxs("div", { className: 'flex items-center gap-1.5 text-xs ' + (testMsg.ok ? 'text-emerald-600' : 'text-destructive'), children: [testMsg.ok ? _jsx(CheckCircle2, { className: "h-3.5 w-3.5" }) : _jsx(XCircle, { className: "h-3.5 w-3.5" }), testMsg.text] }))] })), _jsxs(DialogFooter, { className: "gap-2 sm:justify-between", children: [_jsxs(Button, { variant: "ghost", size: "sm", disabled: !form?.driver || testingDraft, onClick: () => void testDraft(), children: [testingDraft ? _jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : _jsx(Plug, { className: "mr-1.5 h-4 w-4" }), " Test connection"] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setEditorOpen(false), children: "Cancel" }), _jsxs(Button, { size: "sm", disabled: !canSave, onClick: () => void saveEditor(), children: [savingEditor && _jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }), editing ? 'Save changes' : 'Create datasource'] })] })] })] }) }), _jsx(Dialog, { open: !!syncName, onOpenChange: (o) => { if (!o)
|
|
323
|
+
setSyncName(null); }, children: _jsxs(DialogContent, { className: "max-w-lg", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Sync objects from \u201C", syncName, "\u201D"] }), _jsx(DialogDescription, { children: "Pick the remote tables to import as objects. Each becomes an object definition." })] }), tables == null ? (_jsxs("div", { className: "flex items-center gap-2 py-8 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Introspecting\u2026"] })) : tables.length === 0 ? (_jsx("p", { className: "py-8 text-center text-sm text-muted-foreground", children: "No remote tables found on this datasource." })) : (_jsx("div", { className: "max-h-[50vh] space-y-1 overflow-y-auto", children: tables.map((t) => {
|
|
324
|
+
const key = t.schema ? `${t.schema}.${t.name}` : t.name;
|
|
325
|
+
return (_jsxs("label", { className: "flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-sm hover:bg-accent", children: [_jsx("input", { type: "checkbox", checked: selected.has(t.name), onChange: () => toggle(t.name), className: "h-4 w-4" }), _jsx("span", { className: "flex-1", children: key }), t.columnCount != null && _jsxs("span", { className: "text-[11px] text-muted-foreground", children: [t.columnCount, " cols"] })] }, key));
|
|
326
|
+
}) })), _jsxs("div", { className: "mt-2 flex items-center justify-end gap-2", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setSyncName(null), children: "Cancel" }), _jsxs(Button, { size: "sm", disabled: syncing || selected.size === 0, onClick: () => void runSync(), children: [syncing ? _jsx(Loader2, { className: "mr-1.5 h-4 w-4 animate-spin" }) : _jsx(Boxes, { className: "mr-1.5 h-4 w-4" }), "Create ", selected.size || '', " object", selected.size === 1 ? '' : 's'] })] })] }) })] }));
|
|
327
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerDatasourceResource(): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Registers the `datasource` metadata type as a custom-rendered resource in the
|
|
4
|
+
* metadata-admin engine. datasource is a *side-effectful* type (secret +
|
|
5
|
+
* connection pool + introspection), so it ships a bespoke ListPage that talks
|
|
6
|
+
* to the framework `datasource-admin` REST — but it lives inside the engine
|
|
7
|
+
* (engine route + registry slot + shell), reachable from the setup left-nav
|
|
8
|
+
* "Datasources" item and the `…/component/metadata/resource?type=datasource`
|
|
9
|
+
* route, instead of a separate hand-written System page.
|
|
10
|
+
*/
|
|
11
|
+
import { registerMetadataResource } from '../registry';
|
|
12
|
+
import { DatasourceResourcePage } from './DatasourceResourcePage';
|
|
13
|
+
let registered = false;
|
|
14
|
+
export function registerDatasourceResource() {
|
|
15
|
+
if (registered)
|
|
16
|
+
return;
|
|
17
|
+
registered = true;
|
|
18
|
+
registerMetadataResource({
|
|
19
|
+
type: 'datasource',
|
|
20
|
+
label: 'Datasources',
|
|
21
|
+
domain: 'data',
|
|
22
|
+
ListPage: DatasourceResourcePage,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetadataDefaultInspectorRegistry — "home" inspectors shown when the
|
|
3
|
+
* preview has NO active selection.
|
|
4
|
+
*
|
|
5
|
+
* The scoped {@link MetadataInspectorRegistry} only kicks in once the
|
|
6
|
+
* preview emits a selection. Before that, the right panel falls back to
|
|
7
|
+
* the generic whole-draft `SchemaForm`. For some types that generic form
|
|
8
|
+
* is a poor authoring surface (e.g. a View, where authors want a curated
|
|
9
|
+
* "pick a view type, manage which fields show" panel — Airtable style).
|
|
10
|
+
*
|
|
11
|
+
* Registering a default inspector here lets the host render a curated,
|
|
12
|
+
* selection-less panel instead of the generic form. Selecting a
|
|
13
|
+
* sub-element (a column) still swaps in the scoped inspector.
|
|
14
|
+
*/
|
|
15
|
+
import type { ComponentType } from 'react';
|
|
16
|
+
import type { SupportedLocale } from './i18n';
|
|
17
|
+
import type { MetadataSelection } from './preview-registry';
|
|
18
|
+
export interface MetadataDefaultInspectorProps {
|
|
19
|
+
/** Metadata type, e.g. 'view'. */
|
|
20
|
+
type: string;
|
|
21
|
+
/** Item primary-key name (may be empty in create mode). */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Current draft from the editor. Treat as immutable. */
|
|
24
|
+
draft: Record<string, unknown>;
|
|
25
|
+
/** Apply a shallow patch to the draft. */
|
|
26
|
+
onPatch: (patch: Record<string, unknown>) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Emit a selection. The default inspector uses this to drill into a
|
|
29
|
+
* sub-element (e.g. focus one column), which makes the host swap in the
|
|
30
|
+
* scoped inspector for that selection.
|
|
31
|
+
*/
|
|
32
|
+
onSelectionChange?: (next: MetadataSelection | null) => void;
|
|
33
|
+
/** Whether the host is in edit mode. False → disable inputs. */
|
|
34
|
+
readOnly: boolean;
|
|
35
|
+
/** Active UI locale for i18n. */
|
|
36
|
+
locale: SupportedLocale;
|
|
37
|
+
/**
|
|
38
|
+
* The live server JSONSchema for this type (`RichMetadataTypeEntry.schema`,
|
|
39
|
+
* from `/meta/types`). Curated inspectors graft any server-only top-level
|
|
40
|
+
* fields onto the bundled-spec form so new server fields (e.g. a report's
|
|
41
|
+
* `dataset`/`rows`/`values`) are directly editable even when objectui's
|
|
42
|
+
* bundled `@objectstack/spec` lags the running server. Undefined when no
|
|
43
|
+
* server schema is available (offline / older server).
|
|
44
|
+
*/
|
|
45
|
+
serverSchema?: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
export type MetadataDefaultInspector = ComponentType<MetadataDefaultInspectorProps>;
|
|
48
|
+
export declare function registerMetadataDefaultInspector(type: string, component: MetadataDefaultInspector): void;
|
|
49
|
+
export declare function getMetadataDefaultInspector(type: string): MetadataDefaultInspector | undefined;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
const REGISTRY = new Map();
|
|
3
|
+
export function registerMetadataDefaultInspector(type, component) {
|
|
4
|
+
REGISTRY.set(type, component);
|
|
5
|
+
}
|
|
6
|
+
export function getMetadataDefaultInspector(type) {
|
|
7
|
+
return REGISTRY.get(type);
|
|
8
|
+
}
|
|
@@ -73,13 +73,60 @@ const SCHEMAS = {
|
|
|
73
73
|
},
|
|
74
74
|
permission: {
|
|
75
75
|
type: 'object',
|
|
76
|
-
title: 'Permission
|
|
77
|
-
required: ['
|
|
76
|
+
title: 'Permission',
|
|
77
|
+
required: ['id', 'resource', 'actions', 'description'],
|
|
78
78
|
properties: {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
id: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
title: 'ID',
|
|
82
|
+
description: 'Stable identifier (e.g. crm.account.read).',
|
|
83
|
+
},
|
|
84
|
+
resource: {
|
|
85
|
+
type: 'string',
|
|
86
|
+
title: 'Resource',
|
|
87
|
+
description: 'What this permission applies to.',
|
|
88
|
+
enum: [
|
|
89
|
+
'data.object', 'data.record', 'data.field',
|
|
90
|
+
'ui.view', 'ui.dashboard', 'ui.report',
|
|
91
|
+
'system.config', 'system.plugin', 'system.api', 'system.service',
|
|
92
|
+
'storage.file', 'storage.database',
|
|
93
|
+
'network.http', 'network.websocket',
|
|
94
|
+
'process.spawn', 'process.env',
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
actions: {
|
|
98
|
+
type: 'array',
|
|
99
|
+
title: 'Actions',
|
|
100
|
+
description: 'Permitted operations on the resource.',
|
|
101
|
+
items: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
enum: [
|
|
104
|
+
'create', 'read', 'update', 'delete',
|
|
105
|
+
'execute', 'admin', 'manage', 'configure',
|
|
106
|
+
'import', 'export', 'share',
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
description: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
title: 'Description',
|
|
113
|
+
description: 'Why this permission exists (shown in admin UIs).',
|
|
114
|
+
},
|
|
115
|
+
scope: {
|
|
116
|
+
type: 'string',
|
|
117
|
+
title: 'Scope',
|
|
118
|
+
enum: ['tenant', 'user', 'plugin', 'global', 'resource'],
|
|
119
|
+
default: 'tenant',
|
|
120
|
+
},
|
|
121
|
+
required: {
|
|
122
|
+
type: 'boolean',
|
|
123
|
+
title: 'Required',
|
|
124
|
+
description: 'Must be present for the holder to function.',
|
|
125
|
+
},
|
|
126
|
+
justification: {
|
|
127
|
+
type: 'string',
|
|
128
|
+
title: 'Justification',
|
|
129
|
+
},
|
|
83
130
|
},
|
|
84
131
|
},
|
|
85
132
|
translation: {
|
|
@@ -179,15 +226,73 @@ const SCHEMAS = {
|
|
|
179
226
|
filters: { type: 'array', title: 'Filters', items: { type: 'object' } },
|
|
180
227
|
},
|
|
181
228
|
},
|
|
229
|
+
book: {
|
|
230
|
+
type: 'object',
|
|
231
|
+
title: 'Documentation Book',
|
|
232
|
+
required: ['name', 'groups'],
|
|
233
|
+
properties: {
|
|
234
|
+
...headerProps,
|
|
235
|
+
slug: {
|
|
236
|
+
type: 'string',
|
|
237
|
+
title: 'Slug',
|
|
238
|
+
description: 'Portal URL segment; defaults to the name without its package prefix.',
|
|
239
|
+
},
|
|
240
|
+
icon: { type: 'string', title: 'Icon' },
|
|
241
|
+
order: {
|
|
242
|
+
type: 'number',
|
|
243
|
+
title: 'Order',
|
|
244
|
+
description: 'Orders books within the portal.',
|
|
245
|
+
},
|
|
246
|
+
audience: {
|
|
247
|
+
title: 'Audience',
|
|
248
|
+
description: "Access audience. 'org' (default) inherits the package grant; 'public' is anonymously readable; { profile } gates by role.",
|
|
249
|
+
// Union of the two scalar literals and the { profile } object — kept lax
|
|
250
|
+
// so the role-gated object form round-trips untouched through the form.
|
|
251
|
+
oneOf: [
|
|
252
|
+
{ type: 'string', enum: ['org', 'public'] },
|
|
253
|
+
{ type: 'object', title: 'Role-gated', properties: { profile: { type: 'string', title: 'Profile' } }, required: ['profile'] },
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
groups: {
|
|
257
|
+
type: 'array',
|
|
258
|
+
title: 'Groups (spine)',
|
|
259
|
+
description: 'Ordered sections. Membership is derived from each group\'s include rule — edit the structure visually in the Preview tab.',
|
|
260
|
+
items: {
|
|
261
|
+
type: 'object',
|
|
262
|
+
required: ['key', 'label'],
|
|
263
|
+
properties: {
|
|
264
|
+
key: { type: 'string', title: 'Key', pattern: '^[a-z][a-z0-9_]*$' },
|
|
265
|
+
label: { type: 'string', title: 'Label' },
|
|
266
|
+
order: { type: 'number', title: 'Order' },
|
|
267
|
+
include: { title: 'Include rule', description: 'Glob over doc names (e.g. crm_guide_*) or { tag }.' },
|
|
268
|
+
package: { type: 'string', title: 'Package scope' },
|
|
269
|
+
pages: { type: 'array', title: 'Explicit pages (override)', items: {} },
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
182
275
|
email_template: {
|
|
183
276
|
type: 'object',
|
|
184
277
|
title: 'Email Template',
|
|
185
|
-
required: ['name'],
|
|
278
|
+
required: ['name', 'label', 'subject', 'bodyHtml'],
|
|
186
279
|
properties: {
|
|
187
280
|
...headerProps,
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
281
|
+
category: {
|
|
282
|
+
type: 'string',
|
|
283
|
+
title: 'Category',
|
|
284
|
+
enum: ['auth', 'notification', 'workflow', 'marketing', 'custom'],
|
|
285
|
+
default: 'custom',
|
|
286
|
+
},
|
|
287
|
+
locale: { type: 'string', title: 'Locale', default: 'en-US', description: 'BCP-47 tag (en-US, zh-CN, …)' },
|
|
288
|
+
subject: { type: 'string', title: 'Subject', description: 'Supports {{var.path}} interpolation' },
|
|
289
|
+
bodyHtml: { type: 'string', title: 'HTML Body', format: 'multiline' },
|
|
290
|
+
bodyText: { type: 'string', title: 'Plain-Text Body', format: 'multiline' },
|
|
291
|
+
variables: { type: 'array', title: 'Variables', items: { type: 'object' } },
|
|
292
|
+
fromOverride: { type: 'object', title: 'From Override' },
|
|
293
|
+
replyTo: { type: 'string', title: 'Reply-To' },
|
|
294
|
+
active: { type: 'boolean', title: 'Active', default: true },
|
|
295
|
+
isSystem: { type: 'boolean', title: 'System Template', default: false },
|
|
191
296
|
},
|
|
192
297
|
},
|
|
193
298
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExternalDatasourcePanel — the Studio home for an External Datasource
|
|
3
|
+
* Federation datasource (ADR-0015 §6.4).
|
|
4
|
+
*
|
|
5
|
+
* Rendered inside `DatasourcePreview` whenever a datasource is federated
|
|
6
|
+
* (`schemaMode !== 'managed'`). It groups the buildable P5 surfaces:
|
|
7
|
+
*
|
|
8
|
+
* • Tables — browse remote tables + import them as Objects.
|
|
9
|
+
* • Validation — check declared objects against the live remote schema
|
|
10
|
+
* (doubles as on-demand drift detection).
|
|
11
|
+
*
|
|
12
|
+
* A header strip offers "Refresh catalog" (re-introspect + persist the
|
|
13
|
+
* `external_catalog` snapshot) and shows when the snapshot was last taken.
|
|
14
|
+
*
|
|
15
|
+
* The connection wizard (drivers / credentials / secrets) intentionally lives
|
|
16
|
+
* in System Settings, not here — this surface is metadata-design work.
|
|
17
|
+
*/
|
|
18
|
+
import * as React from 'react';
|
|
19
|
+
export interface ExternalDatasourcePanelProps {
|
|
20
|
+
/** The datasource's saved name. Empty while the datasource is unsaved. */
|
|
21
|
+
datasource: string;
|
|
22
|
+
/** The datasource's `schemaMode` (only `external` / `validate-only` here). */
|
|
23
|
+
schemaMode?: string;
|
|
24
|
+
/** Whether the datasource permits writes (`external.allowWrites`). */
|
|
25
|
+
allowWrites?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function ExternalDatasourcePanel({ datasource, schemaMode, allowWrites, }: ExternalDatasourcePanelProps): React.JSX.Element;
|