@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
|
@@ -15,14 +15,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
15
15
|
* into a type. Pre-fetching all 27 counts on page load is wasteful.
|
|
16
16
|
*/
|
|
17
17
|
import * as React from 'react';
|
|
18
|
-
import { Link } from 'react-router-dom';
|
|
19
|
-
import { Search, Database, Layers, Workflow, Sparkles, Settings, ShieldCheck, Box } from 'lucide-react';
|
|
18
|
+
import { Link, useSearchParams } from 'react-router-dom';
|
|
19
|
+
import { Search, Database, Layers, Workflow, Sparkles, Settings, ShieldCheck, Box, AlertTriangle, Lock } from 'lucide-react';
|
|
20
20
|
import { Input } from '@object-ui/components';
|
|
21
21
|
import { Button } from '@object-ui/components';
|
|
22
22
|
import { Badge } from '@object-ui/components';
|
|
23
23
|
import { Kbd } from '@object-ui/components';
|
|
24
24
|
import { Empty, EmptyTitle, EmptyDescription } from '@object-ui/components';
|
|
25
|
-
import { useMetadataClient, useMetadataTypes, } from './useMetadata';
|
|
25
|
+
import { useMetadataClient, useMetadataTypes, useGlobalDiagnostics, } from './useMetadata';
|
|
26
26
|
import { MetadataQuickFind } from './QuickFind';
|
|
27
27
|
import { translateMetadataType, translateMetadataDomain, t, tFormat, detectLocale, } from './i18n';
|
|
28
28
|
const DOMAIN_ICONS = {
|
|
@@ -52,8 +52,12 @@ const DOMAIN_ORDER = [
|
|
|
52
52
|
* `field` is managed in-context via the parent object's edit form
|
|
53
53
|
* (master-detail widget). A flat global list of every field across
|
|
54
54
|
* every object is rarely useful and clutters the admin surface.
|
|
55
|
+
*
|
|
56
|
+
* `package` is the Studio scope container itself. It has a dedicated
|
|
57
|
+
* management surface for create/publish/import/export flows, so exposing it
|
|
58
|
+
* as scoped metadata would mean "view packages inside a package".
|
|
55
59
|
*/
|
|
56
|
-
const HIDDEN_TYPES = new Set(['field']);
|
|
60
|
+
const HIDDEN_TYPES = new Set(['field', 'package']);
|
|
57
61
|
export function MetadataDirectoryPage() {
|
|
58
62
|
const client = useMetadataClient();
|
|
59
63
|
const { loading, error, entries } = useMetadataTypes(client);
|
|
@@ -61,21 +65,94 @@ export function MetadataDirectoryPage() {
|
|
|
61
65
|
const [query, setQuery] = React.useState('');
|
|
62
66
|
const [domainFilter, setDomainFilter] = React.useState('all');
|
|
63
67
|
const [writableOnly, setWritableOnly] = React.useState(false);
|
|
68
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
69
|
+
// Studio is scoped to a single *project* package at a time (the sidebar
|
|
70
|
+
// `active_package` selector owns the scope via `?package=`). Load the
|
|
71
|
+
// installed packages and keep only project-scoped ones — anything not
|
|
72
|
+
// tagged `system`/`cloud` (a missing scope counts as project). System
|
|
73
|
+
// metadata therefore never appears on the directory landing.
|
|
74
|
+
const [projectPackages, setProjectPackages] = React.useState(null);
|
|
75
|
+
React.useEffect(() => {
|
|
76
|
+
let cancelled = false;
|
|
77
|
+
(async () => {
|
|
78
|
+
try {
|
|
79
|
+
const list = await client.list('package');
|
|
80
|
+
if (cancelled)
|
|
81
|
+
return;
|
|
82
|
+
const SYSTEM_SCOPES = new Set(['system', 'cloud']);
|
|
83
|
+
const rows = (list ?? [])
|
|
84
|
+
.map((raw) => {
|
|
85
|
+
const item = raw && typeof raw === 'object' && 'item' in raw ? raw.item : raw;
|
|
86
|
+
const m = (item?.manifest ?? item ?? {});
|
|
87
|
+
return {
|
|
88
|
+
id: m.id,
|
|
89
|
+
scope: m.scope,
|
|
90
|
+
name: m.name || m.id,
|
|
91
|
+
};
|
|
92
|
+
})
|
|
93
|
+
.filter((p) => p.id && !SYSTEM_SCOPES.has(p.scope));
|
|
94
|
+
rows.sort((a, b) => a.name.localeCompare(b.name));
|
|
95
|
+
setProjectPackages(rows.map((p) => ({ id: p.id, name: p.name })));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
if (!cancelled)
|
|
99
|
+
setProjectPackages([]);
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
return () => {
|
|
103
|
+
cancelled = true;
|
|
104
|
+
};
|
|
105
|
+
}, [client]);
|
|
106
|
+
// Resolve the active package from the URL, validated against the project
|
|
107
|
+
// package set. `null` while packages are still loading (fail closed).
|
|
108
|
+
const urlPackage = searchParams.get('package');
|
|
109
|
+
const activePackage = React.useMemo(() => {
|
|
110
|
+
if (!projectPackages)
|
|
111
|
+
return null;
|
|
112
|
+
if (urlPackage && projectPackages.some((p) => p.id === urlPackage))
|
|
113
|
+
return urlPackage;
|
|
114
|
+
return projectPackages[0]?.id ?? null;
|
|
115
|
+
}, [projectPackages, urlPackage]);
|
|
116
|
+
// Repair `?package=` so the sidebar selector and deep-links agree on the
|
|
117
|
+
// active scope. Runs once packages resolve and the URL holds no valid
|
|
118
|
+
// project package.
|
|
119
|
+
React.useEffect(() => {
|
|
120
|
+
if (!projectPackages || projectPackages.length === 0)
|
|
121
|
+
return;
|
|
122
|
+
if (urlPackage && projectPackages.some((p) => p.id === urlPackage))
|
|
123
|
+
return;
|
|
124
|
+
const next = new URLSearchParams(searchParams);
|
|
125
|
+
next.set('package', projectPackages[0].id);
|
|
126
|
+
setSearchParams(next, { replace: true });
|
|
127
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
128
|
+
}, [projectPackages, urlPackage]);
|
|
129
|
+
// Scope the diagnostics sweep to the active project package so tile
|
|
130
|
+
// counts (and locked/invalid badges) reflect *that package only* and
|
|
131
|
+
// match what the scoped list pages show. `undefined` while packages are
|
|
132
|
+
// still resolving keeps the page in its loading state below.
|
|
133
|
+
const { byType: invalidByType, warnByType, summary: diagSummary, countsByType, lockedByType, packagesByType, loading: diagLoading, } = useGlobalDiagnostics(client, 'warning', activePackage ?? undefined);
|
|
134
|
+
// Base set: visible (non-hidden) metadata types contributed by the active
|
|
135
|
+
// project package. Fail closed — show nothing until a concrete project
|
|
136
|
+
// package is active, so system-only types never surface.
|
|
137
|
+
const scopedEntries = React.useMemo(() => entries.filter((e) => {
|
|
138
|
+
if (HIDDEN_TYPES.has(e.type))
|
|
139
|
+
return false;
|
|
140
|
+
if (!activePackage)
|
|
141
|
+
return false;
|
|
142
|
+
return (packagesByType[e.type] ?? []).includes(activePackage);
|
|
143
|
+
}), [entries, activePackage, packagesByType]);
|
|
64
144
|
// Counts per domain for the filter chip bar.
|
|
65
145
|
const domainCounts = React.useMemo(() => {
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
for (const e of visible) {
|
|
146
|
+
const c = { all: scopedEntries.length };
|
|
147
|
+
for (const e of scopedEntries) {
|
|
69
148
|
const d = e.domain ?? 'other';
|
|
70
149
|
c[d] = (c[d] ?? 0) + 1;
|
|
71
150
|
}
|
|
72
151
|
return c;
|
|
73
|
-
}, [
|
|
74
|
-
const writableCount =
|
|
75
|
-
const filtered =
|
|
76
|
-
if (
|
|
77
|
-
return false;
|
|
78
|
-
if (writableOnly && !e.allowOrgOverride)
|
|
152
|
+
}, [scopedEntries]);
|
|
153
|
+
const writableCount = scopedEntries.filter((e) => e.allowOrgOverride || e.allowRuntimeCreate).length;
|
|
154
|
+
const filtered = scopedEntries.filter((e) => {
|
|
155
|
+
if (writableOnly && !(e.allowOrgOverride || e.allowRuntimeCreate))
|
|
79
156
|
return false;
|
|
80
157
|
if (domainFilter !== 'all' && (e.domain ?? 'other') !== domainFilter)
|
|
81
158
|
return false;
|
|
@@ -83,6 +160,7 @@ export function MetadataDirectoryPage() {
|
|
|
83
160
|
const q = query.toLowerCase();
|
|
84
161
|
const hit = e.type.toLowerCase().includes(q) ||
|
|
85
162
|
(e.label ?? '').toLowerCase().includes(q) ||
|
|
163
|
+
translateMetadataType(e.type, locale, e.label).toLowerCase().includes(q) ||
|
|
86
164
|
(e.description ?? '').toLowerCase().includes(q);
|
|
87
165
|
if (!hit)
|
|
88
166
|
return false;
|
|
@@ -101,7 +179,7 @@ export function MetadataDirectoryPage() {
|
|
|
101
179
|
return (ai === -1 ? 99 : ai) - (bi === -1 ? 99 : bi);
|
|
102
180
|
});
|
|
103
181
|
}, [filtered]);
|
|
104
|
-
if (loading) {
|
|
182
|
+
if (loading || projectPackages === null || (activePackage && diagLoading)) {
|
|
105
183
|
return _jsx("div", { className: "p-6 text-sm text-muted-foreground", children: t('engine.directory.loading', locale) });
|
|
106
184
|
}
|
|
107
185
|
if (error) {
|
|
@@ -109,12 +187,17 @@ export function MetadataDirectoryPage() {
|
|
|
109
187
|
}
|
|
110
188
|
return (_jsxs("div", { className: "flex flex-col h-full overflow-hidden", children: [_jsxs("div", { className: "px-6 pt-5 pb-4 border-b bg-background", children: [_jsx("h1", { className: "text-xl font-semibold", children: t('engine.directory.title', locale) }), _jsx("p", { className: "text-sm text-muted-foreground mt-1 max-w-3xl", dangerouslySetInnerHTML: {
|
|
111
189
|
__html: tFormat('engine.directory.description', locale, {
|
|
112
|
-
count: `<strong class="text-foreground">${
|
|
190
|
+
count: `<strong class="text-foreground">${scopedEntries.length}</strong>`,
|
|
113
191
|
writable: writableCount,
|
|
114
192
|
}),
|
|
115
|
-
} }), _jsxs("div", { className: "flex items-center gap-3 mt-4 flex-wrap", children: [_jsxs("div", { className: "relative flex-1 min-w-[240px] max-w-lg", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }), _jsx(Input, { className: "pl-8", placeholder: t('engine.directory.search', locale), value: query, onChange: (e) => setQuery(e.target.value) })] }), _jsxs(Button, { variant: writableOnly ? 'default' : 'outline', size: "sm", onClick: () => setWritableOnly((w) => !w), children: [t('engine.directory.writableOnly', locale), " (", writableCount, ")"] }), _jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-1.5", children: [t('engine.directory.quickFind', locale), " ", _jsx(Kbd, { children: "\u2318" }), _jsx(Kbd, { children: "\u21E7" }), _jsx(Kbd, { children: "M" })] })] }), _jsxs("div", { className: "flex items-center gap-1.5 mt-3 flex-wrap", children: [_jsx(DomainChip, { domain: "all", label: t('engine.directory.all', locale), active: domainFilter === 'all', count: domainCounts.all ?? 0, onClick: () => setDomainFilter('all') }), DOMAIN_ORDER.filter((d) => domainCounts[d]).map((d) => (_jsx(DomainChip, { domain: d, label: translateMetadataDomain(d, locale), active: domainFilter === d, count: domainCounts[d] ?? 0, onClick: () => setDomainFilter(d) }, d)))] })] }), _jsxs("div", { className: "flex-1 overflow-auto p-6 space-y-6", children: [filtered.length === 0 && (_jsxs(Empty, { children: [_jsx(EmptyTitle, { children: t('engine.directory.noMatches', locale) }), _jsx(EmptyDescription, { children: t('engine.directory.noMatchesHint', locale) })] })), grouped.map(([domain, group]) => {
|
|
193
|
+
} }), _jsxs("div", { className: "flex items-center gap-3 mt-4 flex-wrap", children: [_jsxs("div", { className: "relative flex-1 min-w-[240px] max-w-lg", children: [_jsx(Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground" }), _jsx(Input, { className: "pl-8", placeholder: t('engine.directory.search', locale), value: query, onChange: (e) => setQuery(e.target.value) })] }), _jsxs(Button, { variant: writableOnly ? 'default' : 'outline', size: "sm", onClick: () => setWritableOnly((w) => !w), children: [t('engine.directory.writableOnly', locale), " (", writableCount, ")"] }), diagSummary.total > 0 && (_jsx(Button, { asChild: true, variant: "outline", size: "sm", className: "border-destructive/40 text-destructive hover:bg-destructive/10 hover:text-destructive", children: _jsxs(Link, { to: "./_diagnostics", children: [_jsx(AlertTriangle, { className: "h-3.5 w-3.5 mr-1" }), tFormat('engine.directory.diagnosticsLink', locale, { count: diagSummary.total })] }) })), _jsxs("div", { className: "text-xs text-muted-foreground flex items-center gap-1.5", children: [t('engine.directory.quickFind', locale), " ", _jsx(Kbd, { children: "\u2318" }), _jsx(Kbd, { children: "\u21E7" }), _jsx(Kbd, { children: "M" })] })] }), _jsxs("div", { className: "flex items-center gap-1.5 mt-3 flex-wrap", children: [_jsx(DomainChip, { domain: "all", label: t('engine.directory.all', locale), active: domainFilter === 'all', count: domainCounts.all ?? 0, onClick: () => setDomainFilter('all') }), DOMAIN_ORDER.filter((d) => domainCounts[d]).map((d) => (_jsx(DomainChip, { domain: d, label: translateMetadataDomain(d, locale), active: domainFilter === d, count: domainCounts[d] ?? 0, onClick: () => setDomainFilter(d) }, d)))] })] }), _jsxs("div", { className: "flex-1 overflow-auto p-6 space-y-6", children: [projectPackages.length === 0 && (_jsxs(Empty, { children: [_jsx(EmptyTitle, { children: "No project packages installed" }), _jsx(EmptyDescription, { children: "Studio only shows metadata that belongs to a project software package. Install or create a project package to manage its metadata here." })] })), projectPackages.length > 0 && filtered.length === 0 && (_jsxs(Empty, { children: [_jsx(EmptyTitle, { children: t('engine.directory.noMatches', locale) }), _jsx(EmptyDescription, { children: t('engine.directory.noMatchesHint', locale) })] })), grouped.map(([domain, group]) => {
|
|
116
194
|
const Icon = DOMAIN_ICONS[domain] ?? Box;
|
|
117
|
-
return (_jsxs("section", { className: "space-y-2", children: [_jsxs("h2", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground flex items-center gap-1.5", children: [_jsx(Icon, { className: "h-3.5 w-3.5" }), translateMetadataDomain(domain, locale), " (", group.length, ")"] }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: group.map((e) =>
|
|
195
|
+
return (_jsxs("section", { className: "space-y-2", children: [_jsxs("h2", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground flex items-center gap-1.5", children: [_jsx(Icon, { className: "h-3.5 w-3.5" }), translateMetadataDomain(domain, locale), " (", group.length, ")"] }), _jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: group.map((e) => {
|
|
196
|
+
// Carry the active project package into the list-page
|
|
197
|
+
// deep-link so scope survives navigation.
|
|
198
|
+
const totalCount = countsByType[e.type] ?? 0;
|
|
199
|
+
return (_jsx(TypeTile, { entry: e, locale: locale, invalidCount: invalidByType[e.type] ?? 0, warnCount: warnByType[e.type] ?? 0, lockedCount: lockedByType[e.type] ?? 0, itemCount: totalCount, packageFilter: activePackage ?? undefined }, e.type));
|
|
200
|
+
}) })] }, domain));
|
|
118
201
|
})] }), _jsx(MetadataQuickFind, {})] }));
|
|
119
202
|
}
|
|
120
203
|
function DomainChip({ domain, label, active, count, onClick, }) {
|
|
@@ -123,13 +206,19 @@ function DomainChip({ domain, label, active, count, onClick, }) {
|
|
|
123
206
|
? 'bg-primary text-primary-foreground border-primary'
|
|
124
207
|
: 'bg-background hover:bg-accent border-border text-muted-foreground'), children: [label ?? domain, " ", _jsxs("span", { className: "opacity-70 ml-0.5", children: ["(", count, ")"] })] }));
|
|
125
208
|
}
|
|
126
|
-
function TypeTile({ entry, locale }) {
|
|
209
|
+
function TypeTile({ entry, locale, invalidCount = 0, warnCount = 0, itemCount = 0, lockedCount = 0, packageFilter, }) {
|
|
127
210
|
// Prefer the locale-table translation; fall back to server's `label` (typically English).
|
|
128
211
|
const label = translateMetadataType(entry.type, locale, entry.label);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
212
|
+
const href = packageFilter
|
|
213
|
+
? `./${encodeURIComponent(entry.type)}?package=${encodeURIComponent(packageFilter)}`
|
|
214
|
+
: `./${encodeURIComponent(entry.type)}`;
|
|
215
|
+
return (_jsxs(Link, { to: href, className: 'block p-4 border rounded-lg hover:bg-accent transition-colors ' +
|
|
216
|
+
(invalidCount > 0
|
|
217
|
+
? 'border-destructive/40 hover:border-destructive'
|
|
218
|
+
: 'hover:border-primary'), children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "font-medium truncate flex items-center gap-1.5", children: [invalidCount > 0 && (_jsx("span", { title: tFormat('engine.directory.invalidTooltip', locale ?? 'en', { count: invalidCount }), "aria-label": tFormat('engine.directory.invalidTooltip', locale ?? 'en', { count: invalidCount }), children: _jsx(AlertTriangle, { className: "h-3.5 w-3.5 text-destructive shrink-0" }) })), label] }), _jsx("code", { className: "text-xs text-muted-foreground font-mono", children: entry.type })] }), _jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [_jsx(Badge, { variant: "secondary", className: "text-[10px] tabular-nums", title: tFormat('engine.directory.itemCountTooltip', locale ?? 'en', { count: itemCount }), children: itemCount }), invalidCount > 0 && (_jsx(Badge, { variant: "outline", className: "text-[10px] border-destructive/40 text-destructive bg-destructive/[0.06]", title: tFormat('engine.directory.invalidTooltip', locale ?? 'en', { count: invalidCount }), children: invalidCount })), warnCount > 0 && (_jsx(Badge, { variant: "outline", className: "text-[10px] border-amber-500/40 text-amber-700 dark:text-amber-300 bg-amber-500/[0.06]", title: tFormat('engine.directory.warnTooltip', locale ?? 'en', { count: warnCount }), children: warnCount })), lockedCount > 0 && (_jsxs(Badge, { variant: "outline", className: "text-[10px] border-amber-500/40 text-amber-700 dark:text-amber-300 bg-amber-500/[0.06] inline-flex items-center gap-0.5 px-1.5", title: `${lockedCount} locked item${lockedCount === 1 ? '' : 's'} — see ADR-0010`, "aria-label": `${lockedCount} locked items`, children: [_jsx(Lock, { className: "h-2.5 w-2.5" }), lockedCount] })), entry.allowOrgOverride ? (_jsx(Badge, { className: 'text-[10px] ' +
|
|
219
|
+
(entry.overrideSource === 'env'
|
|
220
|
+
? 'bg-amber-100 text-amber-800 hover:bg-amber-100'
|
|
221
|
+
: 'bg-emerald-100 text-emerald-800 hover:bg-emerald-100'), title: entry.overrideSource === 'env'
|
|
222
|
+
? 'Writable via OBJECTSTACK_METADATA_WRITABLE env var'
|
|
223
|
+
: 'Writable per ADR-0005 overlay opt-in', children: t('engine.badge.writable', locale) })) : entry.allowRuntimeCreate ? (_jsx(Badge, { className: "text-[10px] bg-sky-100 text-sky-800 hover:bg-sky-100", title: "Code-shipped items are locked; new items can be created at runtime", children: t('engine.badge.createOnly', locale) })) : (_jsx(Badge, { variant: "outline", className: "text-[10px] text-muted-foreground", children: t('engine.badge.readOnly', locale) }))] })] }), entry.description && (_jsx("div", { className: "text-xs text-muted-foreground mt-2 line-clamp-2", children: entry.description }))] }));
|
|
135
224
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*
|
|
8
|
+
* DraftReviewPanel — ADR-0033 Phase B, §5.
|
|
9
|
+
*
|
|
10
|
+
* A GENERIC, type-agnostic review/diff: it compares a pending DRAFT against the
|
|
11
|
+
* last-published value and lists added / changed / removed top-level keys. It
|
|
12
|
+
* works for ANY metadata type (view, dashboard, flow, …) — the object designer
|
|
13
|
+
* keeps its richer per-field review (`ObjectFormCanvas`); this is the host-level
|
|
14
|
+
* fallback so every type gets a real "what will publishing change" view.
|
|
15
|
+
*
|
|
16
|
+
* It deliberately reuses {@link computeDiffRows} from `LayeredDiff` — the same
|
|
17
|
+
* structural diff engine the Layers tab uses — fed `(published, draft)` so
|
|
18
|
+
* "added" = in the draft but not yet published, "removed" = published key the
|
|
19
|
+
* draft drops, "modified" = value changed.
|
|
20
|
+
*/
|
|
21
|
+
import React from 'react';
|
|
22
|
+
import { type SupportedLocale } from './i18n';
|
|
23
|
+
/** Number of top-level keys that differ between the draft and the published value. */
|
|
24
|
+
export declare function computeDraftChangeCount(published: unknown, draft: unknown): number;
|
|
25
|
+
export interface DraftReviewPanelProps {
|
|
26
|
+
/** The last-published (effective) value — the diff baseline. */
|
|
27
|
+
published: unknown;
|
|
28
|
+
/** The pending draft body being reviewed. */
|
|
29
|
+
draft: unknown;
|
|
30
|
+
locale?: SupportedLocale | string;
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function DraftReviewPanel({ published, draft, locale, className }: DraftReviewPanelProps): React.JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectUI
|
|
4
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*
|
|
9
|
+
* DraftReviewPanel — ADR-0033 Phase B, §5.
|
|
10
|
+
*
|
|
11
|
+
* A GENERIC, type-agnostic review/diff: it compares a pending DRAFT against the
|
|
12
|
+
* last-published value and lists added / changed / removed top-level keys. It
|
|
13
|
+
* works for ANY metadata type (view, dashboard, flow, …) — the object designer
|
|
14
|
+
* keeps its richer per-field review (`ObjectFormCanvas`); this is the host-level
|
|
15
|
+
* fallback so every type gets a real "what will publishing change" view.
|
|
16
|
+
*
|
|
17
|
+
* It deliberately reuses {@link computeDiffRows} from `LayeredDiff` — the same
|
|
18
|
+
* structural diff engine the Layers tab uses — fed `(published, draft)` so
|
|
19
|
+
* "added" = in the draft but not yet published, "removed" = published key the
|
|
20
|
+
* draft drops, "modified" = value changed.
|
|
21
|
+
*/
|
|
22
|
+
import React from 'react';
|
|
23
|
+
import { computeDiffRows } from './LayeredDiff';
|
|
24
|
+
import { t } from './i18n';
|
|
25
|
+
const STATUS_BADGE = {
|
|
26
|
+
modified: 'bg-amber-100 text-amber-900 border border-amber-300 dark:bg-amber-950/60 dark:text-amber-200 dark:border-amber-800',
|
|
27
|
+
added: 'bg-emerald-100 text-emerald-900 border border-emerald-300 dark:bg-emerald-950/60 dark:text-emerald-200 dark:border-emerald-800',
|
|
28
|
+
removed: 'bg-rose-100 text-rose-900 border border-rose-300 dark:bg-rose-950/60 dark:text-rose-200 dark:border-rose-800',
|
|
29
|
+
};
|
|
30
|
+
const STATUS_ROW = {
|
|
31
|
+
modified: 'bg-amber-50/50 dark:bg-amber-950/20',
|
|
32
|
+
added: 'bg-emerald-50/50 dark:bg-emerald-950/20',
|
|
33
|
+
removed: 'bg-rose-50/50 dark:bg-rose-950/20',
|
|
34
|
+
};
|
|
35
|
+
function statusLabel(status, locale) {
|
|
36
|
+
if (status === 'added')
|
|
37
|
+
return t('designer.canvas.diffAdded', locale);
|
|
38
|
+
if (status === 'removed')
|
|
39
|
+
return t('designer.canvas.diffRemoved', locale);
|
|
40
|
+
return t('designer.canvas.diffChanged', locale);
|
|
41
|
+
}
|
|
42
|
+
function formatValue(v) {
|
|
43
|
+
if (v === undefined)
|
|
44
|
+
return '—';
|
|
45
|
+
if (v === null)
|
|
46
|
+
return 'null';
|
|
47
|
+
if (typeof v === 'string')
|
|
48
|
+
return v.length > 200 ? `${v.slice(0, 200)}…` : v;
|
|
49
|
+
if (typeof v === 'number' || typeof v === 'boolean')
|
|
50
|
+
return String(v);
|
|
51
|
+
try {
|
|
52
|
+
const s = JSON.stringify(v);
|
|
53
|
+
return s.length > 200 ? `${s.slice(0, 200)}…` : s;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return String(v);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Number of top-level keys that differ between the draft and the published value. */
|
|
60
|
+
export function computeDraftChangeCount(published, draft) {
|
|
61
|
+
let n = 0;
|
|
62
|
+
for (const row of computeDiffRows(published, draft)) {
|
|
63
|
+
if (row.status !== 'unchanged')
|
|
64
|
+
n += 1;
|
|
65
|
+
}
|
|
66
|
+
return n;
|
|
67
|
+
}
|
|
68
|
+
export function DraftReviewPanel({ published, draft, locale, className }) {
|
|
69
|
+
const rows = React.useMemo(() => computeDiffRows(published, draft).filter((r) => r.status !== 'unchanged'), [published, draft]);
|
|
70
|
+
if (rows.length === 0) {
|
|
71
|
+
return (_jsx("div", { className: `p-4 text-sm text-muted-foreground ${className ?? ''}`, children: t('designer.draftReview.empty', locale) }));
|
|
72
|
+
}
|
|
73
|
+
return (_jsx("div", { className: `flex flex-col gap-1.5 ${className ?? ''}`, "data-testid": "draft-review-panel", children: rows.map((row) => {
|
|
74
|
+
const status = row.status;
|
|
75
|
+
return (_jsxs("div", { className: `flex flex-wrap items-baseline gap-2 rounded-md px-2.5 py-1.5 text-xs ${STATUS_ROW[status]}`, children: [_jsx("span", { className: `inline-flex shrink-0 items-center rounded px-1.5 py-px text-[10px] font-medium uppercase tracking-wide ${STATUS_BADGE[status]}`, children: statusLabel(status, locale) }), _jsx("code", { className: "font-mono font-medium text-foreground", children: row.key }), status === 'added' ? (_jsx("ins", { className: "text-emerald-700 no-underline dark:text-emerald-400", children: formatValue(row.effectiveValue) })) : status === 'removed' ? (_jsx("del", { className: "text-rose-700 dark:text-rose-400", children: formatValue(row.codeValue) })) : (_jsxs("span", { className: "inline-flex items-baseline gap-1.5 text-muted-foreground", children: [_jsx("del", { className: "text-rose-700 dark:text-rose-400", children: formatValue(row.codeValue) }), _jsx("span", { "aria-hidden": "true", children: "\u2192" }), _jsx("ins", { className: "text-emerald-700 no-underline dark:text-emerald-400", children: formatValue(row.effectiveValue) })] }))] }, row.key));
|
|
76
|
+
}) }));
|
|
77
|
+
}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmbeddedItemEditor — full-form editor for items that live INSIDE a
|
|
3
|
+
* parent metadata body (e.g. `object.fields.email`).
|
|
4
|
+
*
|
|
5
|
+
* Embedded items don't have their own HTTP endpoint (`PUT /meta/field/email`
|
|
6
|
+
* does NOT exist for object-scoped fields) — so we:
|
|
7
|
+
* 1. Re-fetch the parent's effective body.
|
|
8
|
+
* 2. Render a SchemaForm using the registered sub-type's schema / form
|
|
9
|
+
* (e.g. `field` for `object.fields`).
|
|
10
|
+
* 3. On save: deep-clone the parent, splice the modified item back
|
|
11
|
+
* under `parent.<embeddedPath>.<itemName>`, and PUT the parent.
|
|
12
|
+
*
|
|
13
|
+
* If the sub-type isn't registered (e.g. `index` has no `editAs`), we
|
|
14
|
+
* fall back to a raw-JSON editor so users can still hand-edit and save.
|
|
15
|
+
*/
|
|
16
|
+
import * as React from 'react';
|
|
1
17
|
export interface EmbeddedItemEditorProps {
|
|
2
18
|
parentType: string;
|
|
3
19
|
parentName: string;
|
|
@@ -12,4 +28,4 @@ export interface EmbeddedItemEditorProps {
|
|
|
12
28
|
/** Called after a successful save with the freshly-saved item. */
|
|
13
29
|
onSaved?: (item: Record<string, unknown>) => void;
|
|
14
30
|
}
|
|
15
|
-
export declare function EmbeddedItemEditor({ parentType, parentName, embeddedPath, itemName, editAs, initialRaw, onSaved, }: EmbeddedItemEditorProps):
|
|
31
|
+
export declare function EmbeddedItemEditor({ parentType, parentName, embeddedPath, itemName, editAs, initialRaw, onSaved, }: EmbeddedItemEditorProps): React.JSX.Element;
|
|
@@ -20,7 +20,9 @@ import { Loader2, Save, AlertTriangle } from 'lucide-react';
|
|
|
20
20
|
import { Button } from '@object-ui/components';
|
|
21
21
|
import { SchemaForm } from './SchemaForm';
|
|
22
22
|
import { useMetadataClient, useMetadataTypes } from './useMetadata';
|
|
23
|
+
import { detectLocale, t, tFormat, translateValidationMessage } from './i18n';
|
|
23
24
|
export function EmbeddedItemEditor({ parentType, parentName, embeddedPath, itemName, editAs, initialRaw, onSaved, }) {
|
|
25
|
+
const locale = React.useMemo(() => detectLocale(), []);
|
|
24
26
|
const client = useMetadataClient();
|
|
25
27
|
const { entries } = useMetadataTypes(client);
|
|
26
28
|
const subEntry = editAs ? entries.find((e) => e.type === editAs) : undefined;
|
|
@@ -44,10 +46,10 @@ export function EmbeddedItemEditor({ parentType, parentName, embeddedPath, itemN
|
|
|
44
46
|
setIssues([]);
|
|
45
47
|
setSavedAt(null);
|
|
46
48
|
}, [initialRaw, itemName, parentType, parentName]);
|
|
47
|
-
const readOnly = subEntry != null && !subEntry.allowOrgOverride;
|
|
49
|
+
const readOnly = subEntry != null && !subEntry.allowOrgOverride && !subEntry.allowRuntimeCreate;
|
|
48
50
|
async function doSave() {
|
|
49
51
|
if (!embeddedPath) {
|
|
50
|
-
setError('
|
|
52
|
+
setError(t('engine.embedded.saveNoPath', locale));
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
55
|
setSaving(true);
|
|
@@ -77,10 +79,12 @@ export function EmbeddedItemEditor({ parentType, parentName, embeddedPath, itemN
|
|
|
77
79
|
const trimmed = fullPath.startsWith(prefix)
|
|
78
80
|
? fullPath.slice(prefix.length)
|
|
79
81
|
: fullPath;
|
|
80
|
-
return { path: trimmed, message: String(x.message ?? 'Invalid') };
|
|
82
|
+
return { path: trimmed, message: translateValidationMessage(String(x.message ?? 'Invalid'), locale) };
|
|
81
83
|
});
|
|
82
84
|
setIssues(mapped);
|
|
83
|
-
setError(
|
|
85
|
+
setError(mapped.length === 1
|
|
86
|
+
? t('engine.validation.failedOne', locale)
|
|
87
|
+
: tFormat('engine.validation.failed', locale, { count: mapped.length }));
|
|
84
88
|
}
|
|
85
89
|
else {
|
|
86
90
|
setError(err?.message ?? String(err));
|
|
@@ -92,17 +96,20 @@ export function EmbeddedItemEditor({ parentType, parentName, embeddedPath, itemN
|
|
|
92
96
|
}
|
|
93
97
|
// No schema registered for this sub-type: fall back to JSON editing.
|
|
94
98
|
if (!schema) {
|
|
95
|
-
return (_jsxs("div", { className: "p-4 space-y-3", children: [
|
|
99
|
+
return (_jsxs("div", { className: "p-4 space-y-3", children: [_jsx("div", { className: "text-xs text-muted-foreground", children: tFormat('engine.embedded.noSchema', locale, {
|
|
100
|
+
type: editAs ?? 'this item',
|
|
101
|
+
target: `${parentType}/${parentName}.${embeddedPath}.${itemName}`,
|
|
102
|
+
}) }), _jsx("textarea", { className: "w-full h-[60vh] font-mono text-xs border rounded p-3 bg-muted/30", value: JSON.stringify(draft, null, 2), onChange: (e) => {
|
|
96
103
|
try {
|
|
97
104
|
setDraft(JSON.parse(e.target.value));
|
|
98
105
|
setError(null);
|
|
99
106
|
}
|
|
100
107
|
catch (err) {
|
|
101
|
-
setError(
|
|
108
|
+
setError(`${t('engine.form.invalidJson', locale)}: ${err.message}`);
|
|
102
109
|
}
|
|
103
|
-
} }), error && (_jsxs("div", { className: "text-sm text-destructive border border-destructive/30 rounded p-2 bg-destructive/5", children: [_jsx(AlertTriangle, { className: "h-4 w-4 inline mr-1" }), " ", error] })), _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { onClick: doSave, disabled: saving || !embeddedPath, children: [saving ? (_jsx(Loader2, { className: "h-4 w-4 mr-1 animate-spin" })) : (_jsx(Save, { className: "h-4 w-4 mr-1" })),
|
|
110
|
+
} }), error && (_jsxs("div", { className: "text-sm text-destructive border border-destructive/30 rounded p-2 bg-destructive/5", children: [_jsx(AlertTriangle, { className: "h-4 w-4 inline mr-1" }), " ", error] })), _jsx("div", { className: "flex justify-end", children: _jsxs(Button, { onClick: doSave, disabled: saving || !embeddedPath, children: [saving ? (_jsx(Loader2, { className: "h-4 w-4 mr-1 animate-spin" })) : (_jsx(Save, { className: "h-4 w-4 mr-1" })), tFormat('engine.embedded.saveIntoParent', locale, { parentType: 'parent' })] }) })] }));
|
|
104
111
|
}
|
|
105
|
-
return (_jsxs("div", { className: "p-4 space-y-4", children: [error && (_jsx("div", { className: "text-sm text-destructive border border-destructive/30 rounded p-3 bg-destructive/5", children: error })), savedAt != null && !error && (_jsx("div", { className: "text-sm text-emerald-700 border border-emerald-300 bg-emerald-50 rounded p-2", children:
|
|
112
|
+
return (_jsxs("div", { className: "p-4 space-y-4", children: [error && (_jsx("div", { className: "text-sm text-destructive border border-destructive/30 rounded p-3 bg-destructive/5", children: error })), savedAt != null && !error && (_jsx("div", { className: "text-sm text-emerald-700 border border-emerald-300 bg-emerald-50 rounded p-2", children: t('engine.embedded.saved', locale) })), readOnly && (_jsx("div", { className: "text-xs text-amber-800 border border-amber-300 bg-amber-50 rounded p-2", children: t('engine.embedded.readOnlyParent', locale) })), _jsx(SchemaForm, { schema: schema, form: form, value: draft, onChange: setDraft, issues: issues }), _jsx("div", { className: "flex justify-end gap-2 pt-2 border-t", children: _jsxs(Button, { onClick: doSave, disabled: saving || !embeddedPath, children: [saving ? (_jsx(Loader2, { className: "h-4 w-4 mr-1 animate-spin" })) : (_jsx(Save, { className: "h-4 w-4 mr-1" })), tFormat('engine.embedded.saveIntoParent', locale, { parentType })] }) }), !embeddedPath && (_jsxs("div", { className: "text-xs text-muted-foreground border rounded p-3", children: [_jsx("div", { className: "font-medium", children: t('engine.embedded.readOnly', locale) }), _jsx("div", { children: t('engine.embedded.noPathHint', locale) })] }))] }));
|
|
106
113
|
}
|
|
107
114
|
/**
|
|
108
115
|
* Return a NEW parent object with the embedded item replaced. The
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* JsonSourceEditor — Monaco-backed JSON editor for the metadata
|
|
10
|
+
* designer's "Source" tab. Replaces the old textarea so power users
|
|
11
|
+
* get syntax highlighting, bracket matching, folding, and inline
|
|
12
|
+
* error squigglies driven by the server-side `_diagnostics` payload.
|
|
13
|
+
*
|
|
14
|
+
* Markers: `issues[]` use dotted (or array) JSON paths matching the
|
|
15
|
+
* Zod issue shape. We resolve each path to a Monaco range with
|
|
16
|
+
* `jsonc-parser` so the squiggle lands on the offending value (or
|
|
17
|
+
* the property key when the value is absent). Unresolved paths fall
|
|
18
|
+
* back to a marker on line 1, so nothing is silently lost.
|
|
19
|
+
*/
|
|
20
|
+
import React from 'react';
|
|
21
|
+
export interface JsonIssue {
|
|
22
|
+
/** Dotted path (e.g. `fields.owner.type`) or empty for root. */
|
|
23
|
+
path: string;
|
|
24
|
+
message: string;
|
|
25
|
+
/** Defaults to `'error'`. */
|
|
26
|
+
severity?: 'error' | 'warning';
|
|
27
|
+
}
|
|
28
|
+
export interface JsonSourceEditorProps {
|
|
29
|
+
value: unknown;
|
|
30
|
+
onChange: (next: Record<string, unknown>) => void;
|
|
31
|
+
readOnly?: boolean;
|
|
32
|
+
issues?: JsonIssue[];
|
|
33
|
+
/** Pixel or CSS-length height. Defaults to `60vh`. */
|
|
34
|
+
height?: string | number;
|
|
35
|
+
}
|
|
36
|
+
export declare function JsonSourceEditor({ value, onChange, readOnly, issues, height, }: JsonSourceEditorProps): React.JSX.Element;
|
|
37
|
+
export default JsonSourceEditor;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ObjectUI
|
|
4
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* JsonSourceEditor — Monaco-backed JSON editor for the metadata
|
|
11
|
+
* designer's "Source" tab. Replaces the old textarea so power users
|
|
12
|
+
* get syntax highlighting, bracket matching, folding, and inline
|
|
13
|
+
* error squigglies driven by the server-side `_diagnostics` payload.
|
|
14
|
+
*
|
|
15
|
+
* Markers: `issues[]` use dotted (or array) JSON paths matching the
|
|
16
|
+
* Zod issue shape. We resolve each path to a Monaco range with
|
|
17
|
+
* `jsonc-parser` so the squiggle lands on the offending value (or
|
|
18
|
+
* the property key when the value is absent). Unresolved paths fall
|
|
19
|
+
* back to a marker on line 1, so nothing is silently lost.
|
|
20
|
+
*/
|
|
21
|
+
import React from 'react';
|
|
22
|
+
import { Skeleton } from '@object-ui/components';
|
|
23
|
+
import * as jsonc from 'jsonc-parser';
|
|
24
|
+
import { detectLocale, t } from './i18n';
|
|
25
|
+
// Lazy: Monaco's React wrapper itself pulls in the editor core
|
|
26
|
+
// (~3MB), so we keep it out of the initial app-shell chunk.
|
|
27
|
+
const LazyMonaco = React.lazy(async () => {
|
|
28
|
+
const mod = await import('@monaco-editor/react');
|
|
29
|
+
return { default: mod.default };
|
|
30
|
+
});
|
|
31
|
+
function stringify(v) {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.stringify(v ?? {}, null, 2);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return '{}';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Parse a dotted JSON path like `fields.owner.0.type` to segments. */
|
|
40
|
+
function splitPath(p) {
|
|
41
|
+
if (!p)
|
|
42
|
+
return [];
|
|
43
|
+
return p.split('.').map((seg) => {
|
|
44
|
+
const n = Number(seg);
|
|
45
|
+
return Number.isInteger(n) && String(n) === seg ? n : seg;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function JsonSourceEditor({ value, onChange, readOnly, issues, height = '60vh', }) {
|
|
49
|
+
const locale = React.useMemo(() => detectLocale(), []);
|
|
50
|
+
const [text, setText] = React.useState(() => stringify(value));
|
|
51
|
+
const [parseError, setParseError] = React.useState(null);
|
|
52
|
+
const lastCommittedRef = React.useRef(text);
|
|
53
|
+
// Hold onto Monaco's editor + namespace so we can repaint markers
|
|
54
|
+
// when either the source text or the issues prop changes.
|
|
55
|
+
const editorRef = React.useRef(null);
|
|
56
|
+
const monacoRef = React.useRef(null);
|
|
57
|
+
// Match against the dark class our app-shell toggles on <html>; pick
|
|
58
|
+
// a Monaco theme that doesn't fight the rest of the chrome.
|
|
59
|
+
const [theme, setTheme] = React.useState(() => {
|
|
60
|
+
if (typeof document === 'undefined')
|
|
61
|
+
return 'light';
|
|
62
|
+
return document.documentElement.classList.contains('dark') ? 'vs-dark' : 'light';
|
|
63
|
+
});
|
|
64
|
+
React.useEffect(() => {
|
|
65
|
+
if (typeof document === 'undefined')
|
|
66
|
+
return;
|
|
67
|
+
const root = document.documentElement;
|
|
68
|
+
const update = () => setTheme(root.classList.contains('dark') ? 'vs-dark' : 'light');
|
|
69
|
+
const obs = new MutationObserver(update);
|
|
70
|
+
obs.observe(root, { attributes: true, attributeFilter: ['class'] });
|
|
71
|
+
return () => obs.disconnect();
|
|
72
|
+
}, []);
|
|
73
|
+
// Push markers from `issues` onto Monaco's model. We rebuild on
|
|
74
|
+
// every relevant change rather than diffing — sweeping `setModelMarkers`
|
|
75
|
+
// is cheap and avoids stale squigglies when issues drop off.
|
|
76
|
+
const applyMarkers = React.useCallback(() => {
|
|
77
|
+
const editor = editorRef.current;
|
|
78
|
+
const monaco = monacoRef.current;
|
|
79
|
+
if (!editor || !monaco)
|
|
80
|
+
return;
|
|
81
|
+
const model = editor.getModel();
|
|
82
|
+
if (!model)
|
|
83
|
+
return;
|
|
84
|
+
if (!issues || issues.length === 0) {
|
|
85
|
+
monaco.editor.setModelMarkers(model, 'objectui-diagnostics', []);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
let tree;
|
|
89
|
+
try {
|
|
90
|
+
tree = jsonc.parseTree(text);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
tree = undefined;
|
|
94
|
+
}
|
|
95
|
+
const markers = issues.map((iss) => {
|
|
96
|
+
const segs = splitPath(iss.path);
|
|
97
|
+
let startLine = 1;
|
|
98
|
+
let startCol = 1;
|
|
99
|
+
let endLine = 1;
|
|
100
|
+
let endCol = 2;
|
|
101
|
+
const node = tree ? jsonc.findNodeAtLocation(tree, segs) : undefined;
|
|
102
|
+
if (node) {
|
|
103
|
+
const start = model.getPositionAt(node.offset);
|
|
104
|
+
const end = model.getPositionAt(node.offset + node.length);
|
|
105
|
+
startLine = start.lineNumber;
|
|
106
|
+
startCol = start.column;
|
|
107
|
+
endLine = end.lineNumber;
|
|
108
|
+
endCol = end.column;
|
|
109
|
+
}
|
|
110
|
+
const sev = iss.severity === 'warning'
|
|
111
|
+
? monaco.MarkerSeverity.Warning
|
|
112
|
+
: monaco.MarkerSeverity.Error;
|
|
113
|
+
return {
|
|
114
|
+
severity: sev,
|
|
115
|
+
message: iss.path ? `${iss.path}: ${iss.message}` : iss.message,
|
|
116
|
+
startLineNumber: startLine,
|
|
117
|
+
startColumn: startCol,
|
|
118
|
+
endLineNumber: endLine,
|
|
119
|
+
endColumn: endCol,
|
|
120
|
+
source: 'metadata',
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
monaco.editor.setModelMarkers(model, 'objectui-diagnostics', markers);
|
|
124
|
+
}, [issues, text]);
|
|
125
|
+
React.useEffect(() => {
|
|
126
|
+
applyMarkers();
|
|
127
|
+
}, [applyMarkers]);
|
|
128
|
+
// Resync the buffer when the parent draft changes externally (Save,
|
|
129
|
+
// Reset, inspector-driven patches). Only sync when the upstream
|
|
130
|
+
// value differs from what we last committed so user keystrokes
|
|
131
|
+
// aren't clobbered while typing.
|
|
132
|
+
React.useEffect(() => {
|
|
133
|
+
const next = stringify(value);
|
|
134
|
+
if (next !== lastCommittedRef.current) {
|
|
135
|
+
setText(next);
|
|
136
|
+
lastCommittedRef.current = next;
|
|
137
|
+
setParseError(null);
|
|
138
|
+
}
|
|
139
|
+
}, [value]);
|
|
140
|
+
const handleChange = (next) => {
|
|
141
|
+
const v = next ?? '';
|
|
142
|
+
setText(v);
|
|
143
|
+
try {
|
|
144
|
+
const parsed = JSON.parse(v);
|
|
145
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
146
|
+
setParseError(null);
|
|
147
|
+
lastCommittedRef.current = v;
|
|
148
|
+
onChange(parsed);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
setParseError(t('engine.form.rootJsonObject', locale));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
setParseError(err?.message ?? t('engine.form.invalidJson', locale));
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const handleMount = (editor, monaco) => {
|
|
159
|
+
editorRef.current = editor;
|
|
160
|
+
monacoRef.current = monaco;
|
|
161
|
+
// Defer one tick so the model has settled before the first paint.
|
|
162
|
+
setTimeout(applyMarkers, 0);
|
|
163
|
+
};
|
|
164
|
+
return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "border rounded overflow-hidden bg-background", style: { height: typeof height === 'number' ? `${height}px` : height }, children: _jsx(React.Suspense, { fallback: _jsx(Skeleton, { className: "w-full h-full" }), children: _jsx(LazyMonaco, { value: text, language: "json", theme: theme, onChange: handleChange, onMount: handleMount, options: {
|
|
165
|
+
readOnly,
|
|
166
|
+
minimap: { enabled: false },
|
|
167
|
+
fontSize: 12,
|
|
168
|
+
lineNumbers: 'on',
|
|
169
|
+
scrollBeyondLastLine: false,
|
|
170
|
+
automaticLayout: true,
|
|
171
|
+
folding: true,
|
|
172
|
+
wordWrap: 'on',
|
|
173
|
+
tabSize: 2,
|
|
174
|
+
renderLineHighlight: 'line',
|
|
175
|
+
scrollbar: { verticalScrollbarSize: 10, horizontalScrollbarSize: 10 },
|
|
176
|
+
} }) }) }), parseError && (_jsxs("div", { className: "text-xs text-destructive flex items-start gap-1.5", children: [_jsx("span", { "aria-hidden": true, children: "\u26A0" }), _jsx("span", { children: parseError })] }))] }));
|
|
177
|
+
}
|
|
178
|
+
export default JsonSourceEditor;
|