@object-ui/app-shell 6.2.3 → 7.1.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 +1229 -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 +184 -39
- 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 +747 -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 +28 -0
- package/dist/console/ai/LiveCanvas.js +80 -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 +137 -4
- package/dist/hooks/useChatConversation.js +316 -25
- package/dist/hooks/useConsoleActionRuntime.d.ts +70 -0
- package/dist/hooks/useConsoleActionRuntime.js +564 -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 +18 -8
- package/dist/index.js +17 -5
- 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 +34 -2
- package/dist/layout/ConsoleFloatingChatbot.js +391 -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 +242 -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/layout/agentPicker.d.ts +56 -0
- package/dist/layout/agentPicker.js +40 -0
- 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/CommitTimeline.d.ts +15 -0
- package/dist/preview/CommitTimeline.js +82 -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 +83 -0
- package/dist/preview/commitHistory.d.ts +28 -0
- package/dist/preview/commitHistory.js +48 -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 +192 -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 +31 -0
- package/dist/views/FlowRunner.js +121 -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/ScreenView.d.ts +70 -0
- package/dist/views/ScreenView.js +73 -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 +101 -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 +39 -0
- package/dist/views/metadata-admin/JsonSourceEditor.js +196 -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 +403 -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 +1250 -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 +258 -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 +205 -0
- package/dist/views/metadata-admin/anchors.js +255 -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 +1252 -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 +221 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.d.ts +16 -0
- package/dist/views/metadata-admin/inspectors/FlowEdgeInspector.js +126 -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 +205 -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 +55 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.d.ts +23 -0
- package/dist/views/metadata-admin/inspectors/ObjectFieldInspector.js +365 -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 +218 -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 +128 -0
- package/dist/views/metadata-admin/inspectors/_shared.js +113 -0
- package/dist/views/metadata-admin/inspectors/datasetFilterCondition.d.ts +24 -0
- package/dist/views/metadata-admin/inspectors/datasetFilterCondition.js +97 -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 +506 -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/issuePath.d.ts +22 -0
- package/dist/views/metadata-admin/issuePath.js +65 -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/package-scope.d.ts +26 -0
- package/dist/views/metadata-admin/package-scope.js +43 -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 +105 -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 +49 -0
- package/dist/views/metadata-admin/previews/FlowCanvas.js +416 -0
- package/dist/views/metadata-admin/previews/FlowPreview.d.ts +20 -0
- package/dist/views/metadata-admin/previews/FlowPreview.js +120 -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 +204 -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 +200 -5
- 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/ScreenPreview.d.ts +38 -0
- package/dist/views/metadata-admin/previews/ScreenPreview.js +61 -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 +102 -0
- package/dist/views/metadata-admin/previews/flow-canvas-layout.js +227 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.d.ts +96 -0
- package/dist/views/metadata-admin/previews/flow-canvas-parts.js +373 -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 +130 -0
- package/dist/views/metadata-admin/previews/object-fields-io.js +243 -0
- package/dist/views/metadata-admin/previews/screen-spec.d.ts +43 -0
- package/dist/views/metadata-admin/previews/screen-spec.js +108 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-types.d.ts +102 -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 +15 -0
- package/dist/views/metadata-admin/previews/simulator/flow-sim-validate.js +185 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.d.ts +73 -0
- package/dist/views/metadata-admin/previews/simulator/flow-simulator.js +426 -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
|
@@ -39,4 +39,4 @@ export interface RecordFormPageProps {
|
|
|
39
39
|
* `formType: 'simple'` (i.e. a flat in-page form), wrapped in a page header
|
|
40
40
|
* that mirrors the look of `RecordDetailView`.
|
|
41
41
|
*/
|
|
42
|
-
export declare function RecordFormPage({ mode }: RecordFormPageProps): import("react
|
|
42
|
+
export declare function RecordFormPage({ mode }: RecordFormPageProps): import("react").JSX.Element;
|
|
@@ -174,9 +174,29 @@ export function RecordFormPage({ mode }) {
|
|
|
174
174
|
if (!objectDef) {
|
|
175
175
|
return (_jsx("div", { className: "flex h-full items-center justify-center p-4", children: _jsxs(Empty, { children: [_jsx("div", { className: "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted", children: _jsx(Database, { className: "h-6 w-6 text-muted-foreground" }) }), _jsx(EmptyTitle, { children: t('empty.objectNotFound') }), _jsx(EmptyDescription, { children: t('empty.objectNotFoundDescription', { name: objectName }) }), _jsx("div", { className: "mt-4", children: _jsxs(Button, { variant: "outline", onClick: () => navigate(baseUrl), children: [_jsx(ArrowLeft, { className: "mr-2 h-4 w-4" }), t('empty.back')] }) })] }) }));
|
|
176
176
|
}
|
|
177
|
+
// Honour the object's form view layout (#1890): wire the declared `type`
|
|
178
|
+
// (simple/tabbed/wizard/split) + `sections` through to ObjectForm, which
|
|
179
|
+
// already renders each variant. Page-level layouts only — `drawer`/`modal`
|
|
180
|
+
// are presentation/open-modes, not record-page layouts, so they fall back to
|
|
181
|
+
// `simple` here (see the form-layout-vs-presentation modelling note in #1890).
|
|
182
|
+
const formDef = objectDef.form ?? objectDef.formViews?.default ?? {};
|
|
183
|
+
const pageFormType = ['tabbed', 'wizard', 'split'].includes(formDef.type) ? formDef.type : 'simple';
|
|
184
|
+
const formLayoutProps = pageFormType !== 'simple' && Array.isArray(formDef.sections)
|
|
185
|
+
? {
|
|
186
|
+
sections: formDef.sections,
|
|
187
|
+
defaultTab: formDef.defaultTab,
|
|
188
|
+
tabPosition: formDef.tabPosition,
|
|
189
|
+
allowSkip: formDef.allowSkip,
|
|
190
|
+
showStepIndicator: formDef.showStepIndicator,
|
|
191
|
+
splitDirection: formDef.splitDirection,
|
|
192
|
+
splitSize: formDef.splitSize,
|
|
193
|
+
splitResizable: formDef.splitResizable,
|
|
194
|
+
}
|
|
195
|
+
: {};
|
|
177
196
|
return (_jsx(ExpressionProvider, { user: expressionUser, app: { name: appName }, data: {}, features: features, children: _jsxs("div", { className: "flex flex-col h-full overflow-hidden bg-background", "data-testid": "record-form-page", "data-mode": mode, children: [_jsxs("header", { className: "sticky top-0 z-10 flex items-center gap-3 border-b bg-background px-4 py-3 sm:px-6", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: goBack, "data-testid": "record-form-page-back", "aria-label": t('common.back', { defaultValue: 'Back' }), children: _jsx(ArrowLeft, { className: "h-4 w-4" }) }), _jsxs("nav", { "aria-label": "Breadcrumb", className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Link, { to: objectListUrl, className: "hover:text-foreground transition-colors", children: label }), _jsx("span", { "aria-hidden": "true", children: "/" }), _jsx("span", { className: "text-foreground font-medium", "data-testid": "record-form-page-title", children: pageTitle }), _jsx(ManagedByBadge, { managedBy: objectDef?.managedBy, className: "ml-1" })] })] }), _jsx("div", { className: "flex-1 overflow-auto p-4 sm:p-6", children: _jsx("div", { className: "mx-auto max-w-4xl", children: _jsx(ObjectForm, { schema: {
|
|
178
197
|
type: 'object-form',
|
|
179
|
-
formType:
|
|
198
|
+
formType: pageFormType,
|
|
199
|
+
...formLayoutProps,
|
|
180
200
|
objectName: objectDef.name,
|
|
181
201
|
mode,
|
|
182
202
|
recordId: mode === 'edit' ? recordId : undefined,
|
|
@@ -193,6 +213,11 @@ export function RecordFormPage({ mode }) {
|
|
|
193
213
|
}),
|
|
194
214
|
layout: 'vertical',
|
|
195
215
|
fields,
|
|
216
|
+
// Master-detail by config: if the object's form view declares
|
|
217
|
+
// inline child collections, ObjectForm renders them as an atomic
|
|
218
|
+
// master-detail form on this page — no bespoke page needed.
|
|
219
|
+
subforms: objectDef.form?.subforms
|
|
220
|
+
?? objectDef.formViews?.default?.subforms,
|
|
196
221
|
onSuccess: handleSuccess,
|
|
197
222
|
onCancel: handleCancel,
|
|
198
223
|
showSubmit: true,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Field option shape the host (ReportView) already computes. */
|
|
2
|
+
interface AvailableField {
|
|
3
|
+
value: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ReportConfigPanelProps {
|
|
8
|
+
/** Whether the panel is open. */
|
|
9
|
+
open: boolean;
|
|
10
|
+
/** Close callback. */
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
/** The current report definition (flat spec Report document). */
|
|
13
|
+
config: Record<string, any> | null;
|
|
14
|
+
/** Persist all draft changes. */
|
|
15
|
+
onSave: (config: Record<string, any>) => void;
|
|
16
|
+
/** Called on every field change so the host can drive a live preview. */
|
|
17
|
+
onFieldChange?: (key: string, value: any, draft?: Record<string, any>) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Legacy field catalog for the pre-9.0 object-bound report editor. Kept for
|
|
20
|
+
* prop compatibility; a 9.0 report binds a dataset, so the inspector now
|
|
21
|
+
* sources its pickers from the dataset catalog instead.
|
|
22
|
+
*/
|
|
23
|
+
availableFields?: AvailableField[];
|
|
24
|
+
/** Reserved for parity with the legacy panel; unused by the inspector. */
|
|
25
|
+
getFieldsForObject?: (objectName: string | undefined) => AvailableField[] | undefined;
|
|
26
|
+
/** Report artifact name — the `:name` for the ADR-0034 draft/publish chrome. */
|
|
27
|
+
name?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Studio metadata client — drives the draft/publish chrome
|
|
30
|
+
* ({@link RuntimeDraftBar}).
|
|
31
|
+
*/
|
|
32
|
+
metadataClient?: any;
|
|
33
|
+
/** Called after a publish / discard so the host can refresh its read. */
|
|
34
|
+
onAfterChange?: () => void;
|
|
35
|
+
}
|
|
36
|
+
export declare function ReportConfigPanel({ open, onClose, config, onSave, onFieldChange, name, metadataClient, onAfterChange, }: ReportConfigPanelProps): import("react").JSX.Element | null;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* ReportConfigPanel — the runtime ReportView's right-rail "report editor".
|
|
5
|
+
*
|
|
6
|
+
* MIGRATED: this panel hosts the studio's spec-driven
|
|
7
|
+
* {@link ReportDefaultInspector} instead of the legacy
|
|
8
|
+
* `buildReportSchema` / `ConfigPanelRenderer` engine in `plugin-report`, so the
|
|
9
|
+
* runtime and the metadata studio share ONE report-editing surface. The
|
|
10
|
+
* inspector renders the report config fields straight from `@objectstack/spec`
|
|
11
|
+
* (`reportForm` / `ReportSchema`) plus a curated type / dataset / values /
|
|
12
|
+
* rows layer (ADR-0021 single-form).
|
|
13
|
+
*
|
|
14
|
+
* It lives in `app-shell` (next to the studio inspector) rather than in
|
|
15
|
+
* `plugin-report`: `app-shell` depends on `plugin-report`, so hosting the
|
|
16
|
+
* inspector here avoids the circular import a plugin-side panel would need.
|
|
17
|
+
*
|
|
18
|
+
* The Report document is FLAT (label / dataset / type / values / rows / … at
|
|
19
|
+
* the top level), so — unlike the View migration — no shape adapter is
|
|
20
|
+
* required: the report config IS the inspector draft. The dataset catalog
|
|
21
|
+
* (binding options + measure/dimension pickers) loads through the shared
|
|
22
|
+
* MetadataClient.
|
|
23
|
+
*
|
|
24
|
+
* Props mirror the legacy `plugin-report` panel so it is a drop-in replacement
|
|
25
|
+
* for ReportView.
|
|
26
|
+
*/
|
|
27
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
28
|
+
import { Button } from '@object-ui/components';
|
|
29
|
+
import { useObjectTranslation } from '@object-ui/i18n';
|
|
30
|
+
import { X } from 'lucide-react';
|
|
31
|
+
import { ReportDefaultInspector } from './metadata-admin/inspectors/ReportDefaultInspector';
|
|
32
|
+
import { RuntimeDraftBar } from './RuntimeDraftBar';
|
|
33
|
+
import { detectLocale } from './metadata-admin/i18n';
|
|
34
|
+
export function ReportConfigPanel({ open, onClose, config, onSave, onFieldChange, name, metadataClient, onAfterChange, }) {
|
|
35
|
+
const { t } = useObjectTranslation();
|
|
36
|
+
const locale = useMemo(() => detectLocale(), []);
|
|
37
|
+
// Unsaved-edits flag — gates Publish (mirrors studio's "save first").
|
|
38
|
+
const [dirty, setDirty] = useState(false);
|
|
39
|
+
// Draft state seeded from `config`. Rebuilt only when the source identity
|
|
40
|
+
// changes (the host stabilizes `config` and bumps it on open / save) — never
|
|
41
|
+
// on every live field change — so in-flight edits are not clobbered.
|
|
42
|
+
const initialDraft = useMemo(() => ({ ...(config ?? {}) }), [config]);
|
|
43
|
+
const [draft, setDraft] = useState(initialDraft);
|
|
44
|
+
const draftRef = useRef(draft);
|
|
45
|
+
const lastSourceRef = useRef(initialDraft);
|
|
46
|
+
if (lastSourceRef.current !== initialDraft) {
|
|
47
|
+
lastSourceRef.current = initialDraft;
|
|
48
|
+
draftRef.current = initialDraft;
|
|
49
|
+
setDraft(initialDraft);
|
|
50
|
+
setDirty(false);
|
|
51
|
+
}
|
|
52
|
+
// Shallow-merge an inspector patch into the draft, then mirror each changed
|
|
53
|
+
// field back to the host so the live preview reflects the edit.
|
|
54
|
+
const handlePatch = useCallback((patch) => {
|
|
55
|
+
const next = { ...draftRef.current, ...patch };
|
|
56
|
+
draftRef.current = next;
|
|
57
|
+
setDraft(next);
|
|
58
|
+
setDirty(true);
|
|
59
|
+
if (onFieldChange) {
|
|
60
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
61
|
+
onFieldChange(key, value, next);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}, [onFieldChange]);
|
|
65
|
+
const handleSave = useCallback(() => {
|
|
66
|
+
onSave(draftRef.current);
|
|
67
|
+
setDirty(false);
|
|
68
|
+
onClose();
|
|
69
|
+
}, [onSave, onClose]);
|
|
70
|
+
// ADR-0034 (#1515): resume a pending draft into the inspector on open
|
|
71
|
+
// (flag-ON only). The report document IS the inspector draft, so seed it
|
|
72
|
+
// directly.
|
|
73
|
+
const handleResumeDraft = useCallback((body) => {
|
|
74
|
+
const next = { ...body };
|
|
75
|
+
draftRef.current = next;
|
|
76
|
+
setDraft(next);
|
|
77
|
+
setDirty(false);
|
|
78
|
+
}, []);
|
|
79
|
+
const handleDiscard = useCallback(() => {
|
|
80
|
+
onClose();
|
|
81
|
+
}, [onClose]);
|
|
82
|
+
if (!open)
|
|
83
|
+
return null;
|
|
84
|
+
return (_jsxs("aside", { className: "hidden sm:flex w-[440px] shrink-0 flex-col border-l bg-background h-full", "data-testid": "report-config-panel", role: "complementary", "aria-label": t('report.editor.title', { defaultValue: 'Edit report' }), children: [_jsxs("div", { className: "flex items-center justify-between gap-2 border-b px-4 py-2.5 shrink-0", children: [_jsx("div", { className: "text-sm font-medium truncate", children: t('report.editor.title', { defaultValue: 'Edit report' }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, className: "h-7 w-7 p-0", "aria-label": t('common.close', { defaultValue: 'Close' }), "data-testid": "report-config-close", children: _jsx(X, { className: "h-4 w-4" }) })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-auto", children: _jsx(ReportDefaultInspector, { type: "report", name: typeof draft.name === 'string' ? draft.name : '', draft: draft, readOnly: false, locale: locale, onPatch: handlePatch }) }), _jsxs("div", { "data-testid": "report-config-footer", className: "flex items-center justify-end gap-2 border-t px-4 py-2.5 shrink-0", children: [_jsx(RuntimeDraftBar, { type: "report", name: name, metadataClient: metadataClient, dirty: dirty, onResume: handleResumeDraft, onAfterChange: onAfterChange }), _jsx(Button, { variant: "ghost", size: "sm", onClick: handleDiscard, "data-testid": "report-config-discard", children: t('common.cancel', { defaultValue: 'Cancel' }) }), _jsx(Button, { size: "sm", onClick: handleSave, "data-testid": "report-config-save", children: t('common.save', { defaultValue: 'Save' }) })] })] }));
|
|
85
|
+
}
|
package/dist/views/ReportView.js
CHANGED
|
@@ -3,13 +3,23 @@ import { useState, useEffect, useCallback, useMemo, lazy, Suspense } from 'react
|
|
|
3
3
|
import { useParams } from 'react-router-dom';
|
|
4
4
|
const ReportViewer = lazy(() => import('@object-ui/plugin-report').then((m) => ({ default: m.ReportViewer })));
|
|
5
5
|
const ReportRenderer = lazy(() => import('@object-ui/plugin-report').then((m) => ({ default: m.ReportRenderer })));
|
|
6
|
-
const ReportConfigPanel = lazy(() => import('@object-ui/plugin-report').then((m) => ({ default: m.ReportConfigPanel })));
|
|
7
6
|
import { Empty, EmptyTitle, EmptyDescription } from '@object-ui/components';
|
|
7
|
+
// Runtime report editor — hosts the studio's spec-driven report inspector
|
|
8
|
+
// (lives in app-shell to avoid a circular dep on plugin-report).
|
|
9
|
+
import { ReportConfigPanel } from './ReportConfigPanel';
|
|
8
10
|
import { Pencil, BarChart3, Loader2 } from 'lucide-react';
|
|
9
11
|
import { useObjectTranslation } from '@object-ui/i18n';
|
|
10
12
|
import { MetadataPanel, useMetadataInspector } from './MetadataInspector';
|
|
11
13
|
import { useMetadata } from '../providers/MetadataProvider';
|
|
14
|
+
import { useExpressionContext } from '../providers/ExpressionProvider';
|
|
15
|
+
import { preferLocal } from '../utils/preferLocal';
|
|
12
16
|
import { useAdapter } from '../providers/AdapterProvider';
|
|
17
|
+
import { useMetadataClient } from './metadata-admin/useMetadata';
|
|
18
|
+
import { persistRuntimeMetadata } from './runtime-metadata-persistence';
|
|
19
|
+
import { useAuth } from '@object-ui/auth';
|
|
20
|
+
import { DrillDownDrawer } from '@object-ui/plugin-dashboard';
|
|
21
|
+
import { DrillNavigationProvider } from '@object-ui/react';
|
|
22
|
+
import { useOpenRecordList } from './useOpenRecordList';
|
|
13
23
|
// Fallback fields when no schema is available
|
|
14
24
|
const FALLBACK_FIELDS = [
|
|
15
25
|
{ value: 'month', label: 'Month', type: 'text' },
|
|
@@ -26,18 +36,31 @@ export function ReportView({ dataSource }) {
|
|
|
26
36
|
const { reportName } = useParams();
|
|
27
37
|
const { showDebug } = useMetadataInspector();
|
|
28
38
|
const adapter = useAdapter();
|
|
39
|
+
// ADR-0034: report edits persist via the metadata draft/publish model.
|
|
40
|
+
const metadataClient = useMetadataClient();
|
|
41
|
+
// Editing a report mutates the SHARED definition, so it is an admin-only
|
|
42
|
+
// quick-edit affordance (mirrors ObjectView's view-config gate).
|
|
43
|
+
const { user } = useAuth();
|
|
44
|
+
const isAdmin = user?.role === 'admin';
|
|
29
45
|
const [configPanelOpen, setConfigPanelOpen] = useState(false);
|
|
30
46
|
// Version counter — incremented on save to refresh the stable config reference
|
|
31
47
|
const [configVersion, setConfigVersion] = useState(0);
|
|
32
48
|
// Find report definition from API-driven metadata
|
|
33
49
|
const { reports, objects, loading, refresh } = useMetadata();
|
|
34
|
-
|
|
50
|
+
// ADR-0048 Phase 2 — prefer the report owned by the current app's package.
|
|
51
|
+
const { app: activeApp } = useExpressionContext();
|
|
52
|
+
const initialReport = preferLocal(reports, reportName, activeApp?._packageId);
|
|
35
53
|
const [reportData, setReportData] = useState(initialReport);
|
|
36
54
|
// Local schema state for live preview — initialized from metadata
|
|
37
55
|
const [editSchema, setEditSchema] = useState(null);
|
|
38
56
|
// State for report runtime data
|
|
39
57
|
const [reportRuntimeData, setReportRuntimeData] = useState([]);
|
|
40
58
|
const [dataLoading, setDataLoading] = useState(false);
|
|
59
|
+
// Drill-through (ADR-0021 D2): clicking an aggregated row/cell opens the
|
|
60
|
+
// underlying records in an in-place drawer (peek without leaving the report),
|
|
61
|
+
// with an "Open in list →" escape hatch to the full object list page.
|
|
62
|
+
const openRecordList = useOpenRecordList();
|
|
63
|
+
const [drill, setDrill] = useState(null);
|
|
41
64
|
const getFieldsForObject = useCallback((objName) => {
|
|
42
65
|
if (!objName || !objects?.length)
|
|
43
66
|
return undefined;
|
|
@@ -56,6 +79,78 @@ export function ReportView({ dataSource }) {
|
|
|
56
79
|
type: def.type || 'text',
|
|
57
80
|
}));
|
|
58
81
|
}, [objects]);
|
|
82
|
+
// ADR-0021 D2 drill-down: open the dataset's object list scoped by
|
|
83
|
+
// `?filter[<field>]=<value>` (the same equality-filter contract the
|
|
84
|
+
// related-list "View All" buttons use).
|
|
85
|
+
//
|
|
86
|
+
// Preferred: the renderer hands us the base `object` + an exact field→RAW
|
|
87
|
+
// `objectFilter` (built from the server's drillRawRows), so we navigate
|
|
88
|
+
// straight away — correct for select/lookup dims, no metadata round-trip.
|
|
89
|
+
//
|
|
90
|
+
// Fallback (older server with no drill metadata): only dimension NAMES +
|
|
91
|
+
// DISPLAY-label bucket values arrive, so resolve them through the dataset
|
|
92
|
+
// definition and reverse-map labels to stored values before filtering:
|
|
93
|
+
// - select fields → reverse-map label → option value
|
|
94
|
+
// - lookup fields → the label is a record name, not the FK id; skip the
|
|
95
|
+
// dim (the drill lands on a superset rather than filtering wrongly)
|
|
96
|
+
// - granularity-bucketed dates → need a range, not equality; skip too
|
|
97
|
+
const handleDatasetDrill = useCallback(async ({ dataset, groupKey, object, objectFilter }) => {
|
|
98
|
+
try {
|
|
99
|
+
// Drawer header: the clicked group's display values (e.g. "West / Q3").
|
|
100
|
+
const titleParts = Object.values(groupKey).filter((v) => v != null).map((v) => String(v));
|
|
101
|
+
const title = titleParts.join(' / ')
|
|
102
|
+
|| String(reportData?.label ?? reportData?.name ?? 'Details');
|
|
103
|
+
// Fast path (ADR-0021 D2): the renderer already resolved the dataset's
|
|
104
|
+
// base object + an exact object FIELD → RAW value filter from the
|
|
105
|
+
// server's drillRawRows — correct for select/lookup dims (a stored
|
|
106
|
+
// value, not a display label) with NO dataset-definition round-trip.
|
|
107
|
+
if (object && objectFilter) {
|
|
108
|
+
setDrill({ object, filter: objectFilter, title });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Fallback (older server with no drill metadata): resolve the dataset's
|
|
112
|
+
// object and reverse-map dimension labels → stored values ourselves.
|
|
113
|
+
const def = await metadataClient.get('dataset', dataset);
|
|
114
|
+
const objectName = typeof def?.object === 'string' ? def.object : undefined;
|
|
115
|
+
if (!objectName)
|
|
116
|
+
return;
|
|
117
|
+
const dims = Array.isArray(def?.dimensions) ? def.dimensions : [];
|
|
118
|
+
const dimByName = new Map(dims.filter((d) => d?.name).map((d) => [d.name, d]));
|
|
119
|
+
// Field defs of the dataset's object — the option value↔label source.
|
|
120
|
+
const objDef = objects?.find((o) => o.name === objectName);
|
|
121
|
+
const rawFields = objDef?.fields;
|
|
122
|
+
const fieldDef = (field) => {
|
|
123
|
+
if (Array.isArray(rawFields))
|
|
124
|
+
return rawFields.find((f) => f?.name === field);
|
|
125
|
+
if (rawFields && typeof rawFields === 'object')
|
|
126
|
+
return rawFields[field];
|
|
127
|
+
return undefined;
|
|
128
|
+
};
|
|
129
|
+
const filter = {};
|
|
130
|
+
for (const [dim, value] of Object.entries(groupKey)) {
|
|
131
|
+
if (value == null)
|
|
132
|
+
continue;
|
|
133
|
+
const dimDef = dimByName.get(dim);
|
|
134
|
+
if (dimDef?.dateGranularity)
|
|
135
|
+
continue;
|
|
136
|
+
const field = dimDef?.field || dim;
|
|
137
|
+
const fd = fieldDef(field);
|
|
138
|
+
if (fd?.type === 'lookup' || fd?.type === 'master_detail')
|
|
139
|
+
continue;
|
|
140
|
+
let stored = value;
|
|
141
|
+
if (Array.isArray(fd?.options)) {
|
|
142
|
+
const opt = fd.options.find((o) => o?.label === value || o?.value === value);
|
|
143
|
+
if (opt && opt.value != null)
|
|
144
|
+
stored = opt.value;
|
|
145
|
+
}
|
|
146
|
+
filter[field] = stored;
|
|
147
|
+
}
|
|
148
|
+
setDrill({ object: objectName, filter, title });
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
console.warn('ReportView: drill failed', err);
|
|
152
|
+
}
|
|
153
|
+
}, [metadataClient, objects, reportData]);
|
|
59
154
|
// Derive available fields from object schema for filter/sort editors
|
|
60
155
|
// Uses live editSchema when available to respond to objectName changes
|
|
61
156
|
const availableFields = useMemo(() => {
|
|
@@ -66,15 +161,19 @@ export function ReportView({ dataSource }) {
|
|
|
66
161
|
// ---- Save helper --------------------------------------------------------
|
|
67
162
|
const saveSchema = useCallback(async (schema) => {
|
|
68
163
|
try {
|
|
69
|
-
if (
|
|
70
|
-
|
|
164
|
+
if (metadataClient) {
|
|
165
|
+
// ADR-0034: save stages a per-item draft; an explicit Publish
|
|
166
|
+
// promotes it (RuntimeDraftBar). `sys_report` is retired.
|
|
167
|
+
await persistRuntimeMetadata('report', reportName, schema, {
|
|
168
|
+
metadataClient,
|
|
169
|
+
});
|
|
71
170
|
refresh().catch(() => { });
|
|
72
171
|
}
|
|
73
172
|
}
|
|
74
173
|
catch (err) {
|
|
75
174
|
console.warn('[ReportView] Auto-save failed:', err);
|
|
76
175
|
}
|
|
77
|
-
}, [
|
|
176
|
+
}, [metadataClient, reportName, refresh]);
|
|
78
177
|
// ---- Open / close config panel ------------------------------------------
|
|
79
178
|
const handleOpenConfigPanel = useCallback(() => {
|
|
80
179
|
setEditSchema(reportData);
|
|
@@ -334,7 +433,17 @@ export function ReportView({ dataSource }) {
|
|
|
334
433
|
// and drill protocol end-to-end. The legacy ReportViewer is only used as a
|
|
335
434
|
// last resort for fully-legacy schemas that lack `objectName` (e.g. inline
|
|
336
435
|
// `fields` + `data` arrays from older app code).
|
|
337
|
-
|
|
436
|
+
// ADR-0021 single-form: a report bound to a semantic-layer `dataset` (no
|
|
437
|
+
// `objectName`/`columns`) still routes through the spec ReportRenderer, which
|
|
438
|
+
// dispatches it to the dataset path (queryDataset + grouped table / joined
|
|
439
|
+
// blocks). Without this it would fall to the legacy ReportViewer, which has no
|
|
440
|
+
// data source to fetch from → a blank page.
|
|
441
|
+
const isDatasetBound = Boolean(previewReport &&
|
|
442
|
+
(typeof previewReport.dataset === 'string' ||
|
|
443
|
+
(previewReport.type === 'joined' &&
|
|
444
|
+
Array.isArray(previewReport.blocks) &&
|
|
445
|
+
previewReport.blocks.some((b) => typeof b?.dataset === 'string'))));
|
|
446
|
+
const useSpecRenderer = isDatasetBound || Boolean(previewReport &&
|
|
338
447
|
previewReport.objectName &&
|
|
339
448
|
(previewReport.type === 'matrix' ||
|
|
340
449
|
previewReport.type === 'joined' ||
|
|
@@ -352,5 +461,5 @@ export function ReportView({ dataSource }) {
|
|
|
352
461
|
allowExport: true,
|
|
353
462
|
loading: dataLoading, // Loading state for data fetching
|
|
354
463
|
};
|
|
355
|
-
return (_jsxs("div", { className: "flex flex-col h-full overflow-hidden bg-background", children: [_jsxs("div", { className: "flex flex-col sm:flex-row justify-between sm:items-center gap-3 sm:gap-4 p-4 sm:p-6 border-b shrink-0", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h1", { className: "text-lg sm:text-xl md:text-2xl font-bold tracking-tight truncate", children: previewReport.title || previewReport.label || 'Report Viewer' }), previewReport.description && (_jsx("p", { className: "text-sm text-muted-foreground mt-1 line-clamp-2", children: previewReport.description }))] }), _jsx("div", { className: "shrink-0 flex items-center gap-1.5", children: _jsxs("button", { type: "button", onClick: handleOpenConfigPanel, className: "inline-flex items-center gap-1.5 rounded-md border border-input bg-background px-2.5 py-1.5 text-xs font-medium text-muted-foreground shadow-sm hover:bg-accent hover:text-accent-foreground", "data-testid": "report-edit-button", children: [_jsx(Pencil, { className: "h-3.5 w-3.5" }), t('common.edit')] }) })] }), _jsxs("div", { className: "flex-1 overflow-hidden flex flex-col sm:flex-row relative", children: [_jsx("div", { className: "flex-1 min-w-0 overflow-auto p-4 sm:p-6 lg:p-8 bg-muted/5", children: _jsx("div", { className: "w-full shadow-sm border rounded-lg sm:rounded-xl bg-background overflow-hidden min-h-150", children: _jsx(Suspense, { fallback: _jsx("div", { className: "p-8 text-sm text-muted-foreground", children: t('common.loading', { defaultValue: 'Loading…' }) }), children: useSpecRenderer ? (_jsx("div", { className: "p-4 sm:p-6", children: _jsx(ReportRenderer, { schema: previewReport, dataSource: dataSource }) })) : (_jsx(ReportViewer, { schema: viewerSchema })) }) }) }), _jsx(
|
|
464
|
+
return (_jsxs(DrillNavigationProvider, { value: { openRecordList }, children: [_jsxs("div", { className: "flex flex-col h-full overflow-hidden bg-background", children: [_jsxs("div", { className: "flex flex-col sm:flex-row justify-between sm:items-center gap-3 sm:gap-4 p-4 sm:p-6 border-b shrink-0", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h1", { className: "text-lg sm:text-xl md:text-2xl font-bold tracking-tight truncate", children: previewReport.title || previewReport.label || 'Report Viewer' }), previewReport.description && (_jsx("p", { className: "text-sm text-muted-foreground mt-1 line-clamp-2", children: previewReport.description }))] }), _jsx("div", { className: "shrink-0 flex items-center gap-1.5", children: isAdmin && (_jsxs("button", { type: "button", onClick: handleOpenConfigPanel, className: "inline-flex items-center gap-1.5 rounded-md border border-input bg-background px-2.5 py-1.5 text-xs font-medium text-muted-foreground shadow-sm hover:bg-accent hover:text-accent-foreground", "data-testid": "report-edit-button", children: [_jsx(Pencil, { className: "h-3.5 w-3.5" }), t('common.edit')] })) })] }), _jsxs("div", { className: "flex-1 overflow-hidden flex flex-col sm:flex-row relative", children: [_jsx("div", { className: "flex-1 min-w-0 overflow-auto p-4 sm:p-6 lg:p-8 bg-muted/5", children: _jsx("div", { className: "w-full shadow-sm border rounded-lg sm:rounded-xl bg-background overflow-hidden min-h-150", children: _jsx(Suspense, { fallback: _jsx("div", { className: "p-8 text-sm text-muted-foreground", children: t('common.loading', { defaultValue: 'Loading…' }) }), children: useSpecRenderer ? (_jsx("div", { className: "p-4 sm:p-6", children: _jsx(ReportRenderer, { schema: previewReport, dataSource: dataSource, rows: reportRuntimeData, onDrill: handleDatasetDrill }) })) : (_jsx(ReportViewer, { schema: viewerSchema })) }) }) }), _jsx(ReportConfigPanel, { open: configPanelOpen && isAdmin, onClose: handleCloseConfigPanel, config: reportConfig, onSave: handleReportConfigSave, onFieldChange: handleReportFieldChange, availableFields: availableFields, getFieldsForObject: getFieldsForObject, name: reportName, metadataClient: metadataClient, onAfterChange: () => refresh().catch(() => { }) }), _jsx(MetadataPanel, { open: showDebug, sections: [{ title: 'Report Configuration', data: previewReport }] })] })] }), _jsx(DrillDownDrawer, { open: !!drill, onClose: () => setDrill(null), title: drill?.title ?? '', objectName: drill?.object ?? '', filter: drill?.filter, dataSource: dataSource })] }));
|
|
356
465
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type RuntimeArtifactType } from './runtime-metadata-persistence';
|
|
2
|
+
export interface RuntimeDraftBarProps {
|
|
3
|
+
/** Artifact type — the `:type` in `/meta/:type/:name`. */
|
|
4
|
+
type: RuntimeArtifactType;
|
|
5
|
+
/** Artifact name — the `:name`. Chrome stays inert until this is known. */
|
|
6
|
+
name?: string;
|
|
7
|
+
/** Studio metadata client (flag-ON path). */
|
|
8
|
+
metadataClient: any;
|
|
9
|
+
/**
|
|
10
|
+
* Disable Publish while the panel has unsaved local edits, mirroring
|
|
11
|
+
* studio's "save first, then publish" rule.
|
|
12
|
+
*/
|
|
13
|
+
dirty?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Seed an existing draft back into the editor when the panel opens, so a
|
|
16
|
+
* half-finished edit is restored. Called at most once per `name` per mount.
|
|
17
|
+
*/
|
|
18
|
+
onResume?: (body: Record<string, unknown>) => void;
|
|
19
|
+
/** Called after a successful publish / discard so the host can refresh. */
|
|
20
|
+
onAfterChange?: () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Monotonic counter the host bumps right after it saves a draft. The bar
|
|
23
|
+
* reads the pending draft only on open, so without this a save in an
|
|
24
|
+
* already-open panel wouldn't surface the indicator until reopen. Bumping
|
|
25
|
+
* this marks the indicator immediately (a save just created a draft) — no
|
|
26
|
+
* dependence on the fire-and-forget write's timing.
|
|
27
|
+
*/
|
|
28
|
+
savedSignal?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function RuntimeDraftBar({ type, name, metadataClient, dirty, onResume, onAfterChange, savedSignal, }: RuntimeDraftBarProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
3
|
+
/**
|
|
4
|
+
* RuntimeDraftBar — ADR-0034 step 3 (#1515): the draft/publish chrome for the
|
|
5
|
+
* runtime config panels (ViewConfigPanel / ReportConfigPanel /
|
|
6
|
+
* DashboardConfigPanel).
|
|
7
|
+
*
|
|
8
|
+
* It mirrors studio's `ResourceEditPage` affordances: on open it reads the
|
|
9
|
+
* pending draft (`?state=draft`), shows an "unpublished changes" indicator when
|
|
10
|
+
* one exists, resumes it into the editor (`onResume`), and exposes **Publish**
|
|
11
|
+
* and **Discard draft**. It renders nothing until there is a pending draft.
|
|
12
|
+
*/
|
|
13
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
14
|
+
import { Button } from '@object-ui/components';
|
|
15
|
+
import { Loader2, Send, Undo2 } from 'lucide-react';
|
|
16
|
+
import { publishRuntimeMetadata, discardRuntimeDraft, readRuntimeDraft, } from './runtime-metadata-persistence';
|
|
17
|
+
import { detectLocale, t, tFormat } from './metadata-admin/i18n';
|
|
18
|
+
export function RuntimeDraftBar({ type, name, metadataClient, dirty, onResume, onAfterChange, savedSignal, }) {
|
|
19
|
+
const locale = detectLocale();
|
|
20
|
+
const [hasDraft, setHasDraft] = useState(false);
|
|
21
|
+
const [busy, setBusy] = useState(false);
|
|
22
|
+
// Track the `name` we've already resumed so reopening the same item doesn't
|
|
23
|
+
// clobber in-flight edits with the stored draft on every effect run.
|
|
24
|
+
const resumedRef = useRef(null);
|
|
25
|
+
const refresh = useCallback(async () => {
|
|
26
|
+
if (!name || !metadataClient) {
|
|
27
|
+
setHasDraft(false);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let body;
|
|
31
|
+
try {
|
|
32
|
+
body = await readRuntimeDraft(type, name, {
|
|
33
|
+
metadataClient,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// A failed draft read must not break the editor — treat as "no draft".
|
|
38
|
+
setHasDraft(false);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
setHasDraft(!!body);
|
|
42
|
+
// Resume is best-effort: a failure to seed the editor must NOT hide the
|
|
43
|
+
// "unpublished changes" indicator (the draft still exists on the server).
|
|
44
|
+
if (body && onResume && resumedRef.current !== name) {
|
|
45
|
+
resumedRef.current = name;
|
|
46
|
+
try {
|
|
47
|
+
onResume(body);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.error('[RuntimeDraftBar] Resume draft failed:', err);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, [type, name, metadataClient, onResume]);
|
|
54
|
+
// Read the pending draft on open / when the edited item changes.
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
void refresh();
|
|
57
|
+
}, [refresh]);
|
|
58
|
+
// A host save just wrote a draft → surface the indicator immediately,
|
|
59
|
+
// without waiting for a reopen or racing the fire-and-forget write.
|
|
60
|
+
// Skip the initial mount (savedSignal === 0 / undefined).
|
|
61
|
+
const lastSavedSignal = useRef(savedSignal);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (savedSignal === lastSavedSignal.current)
|
|
64
|
+
return;
|
|
65
|
+
lastSavedSignal.current = savedSignal;
|
|
66
|
+
if (savedSignal)
|
|
67
|
+
setHasDraft(true);
|
|
68
|
+
}, [savedSignal]);
|
|
69
|
+
const handlePublish = useCallback(async () => {
|
|
70
|
+
if (!name)
|
|
71
|
+
return;
|
|
72
|
+
setBusy(true);
|
|
73
|
+
try {
|
|
74
|
+
await publishRuntimeMetadata(type, name, { metadataClient });
|
|
75
|
+
setHasDraft(false);
|
|
76
|
+
onAfterChange?.();
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.error('[RuntimeDraftBar] Publish failed:', err);
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
setBusy(false);
|
|
83
|
+
}
|
|
84
|
+
}, [type, name, metadataClient, onAfterChange]);
|
|
85
|
+
const handleDiscard = useCallback(async () => {
|
|
86
|
+
if (!name)
|
|
87
|
+
return;
|
|
88
|
+
if (typeof confirm === 'function' &&
|
|
89
|
+
!confirm(tFormat('engine.edit.discardDraftConfirm', locale, { type, name }))) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
setBusy(true);
|
|
93
|
+
try {
|
|
94
|
+
await discardRuntimeDraft(type, name, { metadataClient });
|
|
95
|
+
setHasDraft(false);
|
|
96
|
+
onAfterChange?.();
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error('[RuntimeDraftBar] Discard draft failed:', err);
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
setBusy(false);
|
|
103
|
+
}
|
|
104
|
+
}, [type, name, metadataClient, onAfterChange, locale]);
|
|
105
|
+
// flag OFF, or nothing pending → render nothing (zero DOM, zero layout shift).
|
|
106
|
+
// Nothing pending → render nothing (no indicator, no buttons).
|
|
107
|
+
if (!hasDraft)
|
|
108
|
+
return null;
|
|
109
|
+
return (_jsxs("div", { className: "mr-auto flex items-center gap-2", "data-testid": "runtime-draft-bar", children: [_jsxs("span", { className: "text-xs text-amber-700 dark:text-amber-400", title: t('engine.edit.draftPending', locale), "data-testid": "runtime-draft-indicator", children: ["\u25CF ", t('engine.edit.draftPending', locale)] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: handleDiscard, disabled: busy, className: "h-7 w-7 p-0 text-muted-foreground", title: t('engine.edit.discardDraft', locale), "aria-label": t('engine.edit.discardDraft', locale), "data-testid": "runtime-draft-discard", children: _jsx(Undo2, { className: "h-3.5 w-3.5" }) }), _jsx(Button, { size: "sm", onClick: handlePublish, disabled: busy || dirty, className: "h-7 px-2 bg-emerald-600 hover:bg-emerald-700 text-emerald-50", title: dirty
|
|
110
|
+
? t('engine.edit.publishBlockedDirty', locale)
|
|
111
|
+
: t('engine.edit.publish', locale), "data-testid": "runtime-draft-publish", children: busy ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsxs(_Fragment, { children: [_jsx(Send, { className: "h-3.5 w-3.5 mr-1" }), t('engine.edit.publish', locale)] })) })] }));
|
|
112
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export interface ScreenFieldSpec {
|
|
2
|
+
name: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
options?: Array<{
|
|
7
|
+
value: unknown;
|
|
8
|
+
label: string;
|
|
9
|
+
}>;
|
|
10
|
+
defaultValue?: unknown;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ScreenSpec {
|
|
14
|
+
nodeId: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
fields: ScreenFieldSpec[];
|
|
18
|
+
/**
|
|
19
|
+
* `'object-form'` renders the named object's FULL create/edit form — incl.
|
|
20
|
+
* inline master-detail child grids — as a wizard step (vs. the flat `fields`
|
|
21
|
+
* list). The form persists the record (and its children, atomically) itself,
|
|
22
|
+
* then resumes the run with the saved id bound to `idVariable`.
|
|
23
|
+
*/
|
|
24
|
+
kind?: 'fields' | 'object-form';
|
|
25
|
+
objectName?: string;
|
|
26
|
+
mode?: 'create' | 'edit';
|
|
27
|
+
recordId?: string;
|
|
28
|
+
defaults?: Record<string, unknown>;
|
|
29
|
+
idVariable?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Whether a screen renders the object-form body rather than the flat fields. */
|
|
32
|
+
export declare function isObjectFormScreen(screen: ScreenSpec): boolean;
|
|
33
|
+
/** Seed flat-field values from each field's `defaultValue`. */
|
|
34
|
+
export declare function initialScreenValues(screen: ScreenSpec): Record<string, unknown>;
|
|
35
|
+
/** Submit/cancel wiring for the object-form body — runtime persists & resumes;
|
|
36
|
+
* the design preview hides the bar (`showSubmit`/`showCancel` false). */
|
|
37
|
+
export interface ScreenObjectFormActions {
|
|
38
|
+
showSubmit?: boolean;
|
|
39
|
+
showCancel?: boolean;
|
|
40
|
+
submitText?: string;
|
|
41
|
+
cancelText?: string;
|
|
42
|
+
onSuccess?: (saved: any) => void;
|
|
43
|
+
onCancel?: () => void;
|
|
44
|
+
/** Overrides the "no data source" copy (the preview phrases it for authors). */
|
|
45
|
+
noDataSourceMessage?: React.ReactNode;
|
|
46
|
+
}
|
|
47
|
+
export interface ScreenViewProps {
|
|
48
|
+
screen: ScreenSpec;
|
|
49
|
+
/** Controlled values for the flat-fields body. */
|
|
50
|
+
values: Record<string, unknown>;
|
|
51
|
+
onValueChange: (name: string, value: unknown) => void;
|
|
52
|
+
/**
|
|
53
|
+
* Data source — required to render the `object-form` body. ObjectForm fetches
|
|
54
|
+
* the object schema (and persists) through this adapter.
|
|
55
|
+
*/
|
|
56
|
+
dataSource?: any;
|
|
57
|
+
/**
|
|
58
|
+
* Object definitions — used to derive an `object-form` step's inline
|
|
59
|
+
* master-detail `subforms` (mirrors RecordFormPage's create form).
|
|
60
|
+
*/
|
|
61
|
+
objects?: any[];
|
|
62
|
+
objectForm?: ScreenObjectFormActions;
|
|
63
|
+
className?: string;
|
|
64
|
+
}
|
|
65
|
+
export declare function ScreenView({ screen, values, onValueChange, dataSource, objects, objectForm, className }: ScreenViewProps): import("react").JSX.Element;
|
|
66
|
+
export declare function FieldInput({ field, value, onChange }: {
|
|
67
|
+
field: ScreenFieldSpec;
|
|
68
|
+
value: unknown;
|
|
69
|
+
onChange: (v: unknown) => void;
|
|
70
|
+
}): import("react").JSX.Element;
|