@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
package/dist/layout/AppHeader.js
CHANGED
|
@@ -8,7 +8,8 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
8
8
|
* Variants:
|
|
9
9
|
* - `app` (default when `appName` is present): sidebar trigger + AppSwitcher
|
|
10
10
|
* + breadcrumb path. Used by `ConsoleLayout` inside `/apps/:appName/*`.
|
|
11
|
-
* - `home` : no breadcrumb; displays the
|
|
11
|
+
* - `home` : no breadcrumb; displays the product wordmark (from
|
|
12
|
+
* `getProductName()`, default "ObjectOS") next to the brand
|
|
12
13
|
* logo. Used by `/home`.
|
|
13
14
|
* - `orgs` : no breadcrumb; logo + "Organizations" title. Used by the
|
|
14
15
|
* `/organizations` landing page.
|
|
@@ -18,8 +19,8 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
18
19
|
* @module
|
|
19
20
|
*/
|
|
20
21
|
import { useLocation, useParams, Link, useNavigate } from 'react-router-dom';
|
|
21
|
-
import {
|
|
22
|
-
import { Search, HelpCircle, ChevronDown, Check, Lock,
|
|
22
|
+
import { Button, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup, Avatar, AvatarImage, AvatarFallback, cn, } from '@object-ui/components';
|
|
23
|
+
import { Search, HelpCircle, ChevronDown, Check, Lock, LogOut, Boxes, Layers, Bot, User, BookOpen, ExternalLink, Keyboard, } from 'lucide-react';
|
|
23
24
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
24
25
|
import { useOffline } from '@object-ui/react';
|
|
25
26
|
import { PresenceAvatars, useTenantPresence } from '@object-ui/collaboration';
|
|
@@ -32,8 +33,14 @@ import { useAdapter } from '../providers/AdapterProvider';
|
|
|
32
33
|
import { useObjectTranslation, useObjectLabel } from '@object-ui/i18n';
|
|
33
34
|
import { useAuth, getUserInitials } from '@object-ui/auth';
|
|
34
35
|
import { useMetadata } from '../providers/MetadataProvider';
|
|
36
|
+
import { resolveI18nLabel, preferLocal, matchAppBySegment, appRouteSegment } from '../utils';
|
|
37
|
+
import { getIcon } from '../utils/getIcon';
|
|
35
38
|
import { useMobileViewSwitcher } from './MobileViewSwitcherContext';
|
|
36
39
|
import { useNavigationContext } from '../context/NavigationContext';
|
|
40
|
+
import { useCommandPalette } from '../context/CommandPaletteProvider';
|
|
41
|
+
import { useUrlOverlay } from '../hooks/useUrlOverlay';
|
|
42
|
+
import { getProductName } from '../runtime-config';
|
|
43
|
+
import { LocalizedSidebarTrigger } from './LocalizedSidebarTrigger';
|
|
37
44
|
function humanizeSlug(slug) {
|
|
38
45
|
return slug.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
39
46
|
}
|
|
@@ -51,21 +58,85 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
51
58
|
const params = useParams();
|
|
52
59
|
const navigate = useNavigate();
|
|
53
60
|
const { isOnline } = useOffline();
|
|
61
|
+
// Idempotent, direct open of the ⌘K command palette (ADR-0054 C1). Replaces a
|
|
62
|
+
// synthetic `⌘K` KeyboardEvent re-dispatch that did nothing under automation.
|
|
63
|
+
const { openCommandPalette } = useCommandPalette();
|
|
64
|
+
// Click-reachable entry for the keyboard-shortcuts dialog (was `?`-key only).
|
|
65
|
+
// Shares the `?shortcuts=1` URL param with KeyboardShortcutsDialog (C2/C3).
|
|
66
|
+
const { openOverlay: openShortcuts } = useUrlOverlay('shortcuts');
|
|
54
67
|
const { user, signOut, isAuthEnabled, organizations, activeOrganization, isOrganizationsLoading, } = useAuth();
|
|
55
68
|
const dataSource = useAdapter();
|
|
56
69
|
const { t } = useObjectTranslation();
|
|
57
|
-
const { objectLabel, dashboardLabel, pageLabel, reportLabel, viewLabel } = useObjectLabel();
|
|
70
|
+
const { objectLabel, dashboardLabel, pageLabel, reportLabel, viewLabel, appLabel } = useObjectLabel();
|
|
58
71
|
const { apps: metadataApps, dashboards: metadataDashboards, pages: metadataPages, reports: metadataReports } = useMetadata();
|
|
59
72
|
const { currentAppName, recordTitle } = useNavigationContext();
|
|
60
73
|
const mobileSwitcher = useMobileViewSwitcher();
|
|
74
|
+
/**
|
|
75
|
+
* Help menu — lazily-loaded `doc` metadata (ADR-0046) so the "?" menu can
|
|
76
|
+
* surface a contextual "This app's docs" entry. Fetched once on first menu
|
|
77
|
+
* open (names/labels only — `content` is omitted from the list response);
|
|
78
|
+
* `null` = not yet loaded, `[]` = loaded-but-empty.
|
|
79
|
+
*/
|
|
80
|
+
const [helpDocs, setHelpDocs] = useState(null);
|
|
81
|
+
const loadHelpDocs = useCallback(async () => {
|
|
82
|
+
if (helpDocs !== null)
|
|
83
|
+
return; // fetch at most once per mount
|
|
84
|
+
try {
|
|
85
|
+
const client = dataSource?.getClient?.();
|
|
86
|
+
if (!client?.meta?.getItems) {
|
|
87
|
+
setHelpDocs([]);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const result = await client.meta.getItems('doc');
|
|
91
|
+
const items = Array.isArray(result)
|
|
92
|
+
? result
|
|
93
|
+
: Array.isArray(result?.items)
|
|
94
|
+
? result.items
|
|
95
|
+
: Array.isArray(result?.value)
|
|
96
|
+
? result.value
|
|
97
|
+
: [];
|
|
98
|
+
setHelpDocs(items
|
|
99
|
+
.map((it) => ({ name: it?.name, label: it?.label, _packageId: it?._packageId }))
|
|
100
|
+
.filter((d) => d.name));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Soft-degrade: docs are an optional feature — a failed fetch just
|
|
104
|
+
// means the menu shows the static entries (All docs / Online docs).
|
|
105
|
+
setHelpDocs([]);
|
|
106
|
+
}
|
|
107
|
+
}, [helpDocs, dataSource]);
|
|
61
108
|
const [apiActivities, setApiActivities] = useState(null);
|
|
62
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* In-header notifications (ADR-0030). Polled from `sys_inbox_message` (the L5
|
|
111
|
+
* in-app materialization, `mine` scope) joined with `sys_notification_receipt`
|
|
112
|
+
* for read-state — the bell no longer reads the re-modeled `sys_notification`
|
|
113
|
+
* L2 event (which carries no recipient/read columns).
|
|
114
|
+
*/
|
|
63
115
|
const [notifications, setNotifications] = useState([]);
|
|
64
116
|
// Once the server returns 404 for these collections we stop retrying for
|
|
65
117
|
// the lifetime of the page — they're optional features and re-requesting
|
|
66
118
|
// on every navigation creates console noise + wasted round trips.
|
|
67
119
|
const activityUnavailableRef = useRef(false);
|
|
68
120
|
const notificationsUnavailableRef = useRef(false);
|
|
121
|
+
// Tracks whether the component is still mounted. Used by the pollers to
|
|
122
|
+
// decide whether to apply an in-flight fetch's result, independent of any
|
|
123
|
+
// single effect run's `cancelled` flag — so a fetch that outlives the
|
|
124
|
+
// effect run that started it (because deps settled mid-flight during
|
|
125
|
+
// bootstrap) still populates state instead of being silently dropped.
|
|
126
|
+
const mountedRef = useRef(true);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
// Reset on (re)mount too, so StrictMode's mount→cleanup→mount cycle
|
|
129
|
+
// doesn't leave it latched false and silence the pollers.
|
|
130
|
+
mountedRef.current = true;
|
|
131
|
+
return () => { mountedRef.current = false; };
|
|
132
|
+
}, []);
|
|
133
|
+
// In-flight guards: during bootstrap the poller effects re-run several
|
|
134
|
+
// times as `dataSource` / `isApp` / `user.id` settle, and each run kicks
|
|
135
|
+
// an immediate fetch. Without these the same query fired 5× concurrently
|
|
136
|
+
// (nothing cached yet) and flooded the backend. They coalesce to one.
|
|
137
|
+
const notifInFlightRef = useRef(false);
|
|
138
|
+
const approvalsInFlightRef = useRef(false);
|
|
139
|
+
const activityInFlightRef = useRef(false);
|
|
69
140
|
/** M11.C15: pending approvals count for the topbar shortcut. */
|
|
70
141
|
const [pendingApprovalsCount, setPendingApprovalsCount] = useState(0);
|
|
71
142
|
const approvalsUnavailableRef = useRef(false);
|
|
@@ -84,6 +155,12 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
84
155
|
// wired — see ROADMAP for the realtime plan.
|
|
85
156
|
if (activityUnavailableRef.current)
|
|
86
157
|
return;
|
|
158
|
+
// In-flight dedupe: this callback's identity changes as dataSource/isApp
|
|
159
|
+
// settle during bootstrap, re-firing the mount effect below; coalesce the
|
|
160
|
+
// immediate fetches into one instead of N (sys_activity fired 3×+).
|
|
161
|
+
if (activityInFlightRef.current)
|
|
162
|
+
return;
|
|
163
|
+
activityInFlightRef.current = true;
|
|
87
164
|
try {
|
|
88
165
|
const activityResult = await dataSource
|
|
89
166
|
.find('sys_activity', { $orderby: { timestamp: 'desc' }, $top: 20 })
|
|
@@ -99,25 +176,31 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
99
176
|
}
|
|
100
177
|
}
|
|
101
178
|
catch { /* fallback below */ }
|
|
179
|
+
finally {
|
|
180
|
+
activityInFlightRef.current = false;
|
|
181
|
+
}
|
|
102
182
|
}, [dataSource, isApp]);
|
|
103
183
|
useEffect(() => { fetchPresenceAndActivities(); }, [fetchPresenceAndActivities]);
|
|
104
184
|
/**
|
|
105
|
-
*
|
|
185
|
+
* Poll the signed-in user's in-app inbox (ADR-0030 L5).
|
|
186
|
+
*
|
|
187
|
+
* Two scoped reads, joined client-side:
|
|
188
|
+
* - `sys_inbox_message` filtered by `user_id` (the `mine` materialization),
|
|
189
|
+
* 20 most-recent — the notification rows themselves.
|
|
190
|
+
* - `sys_notification_receipt` filtered by `user_id` + `channel:'inbox'` —
|
|
191
|
+
* the read-state spine. A message is unread until its event has a
|
|
192
|
+
* `read`/`clicked`/`dismissed` receipt; the unread count drives the badge.
|
|
106
193
|
*
|
|
107
|
-
* -
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* -
|
|
112
|
-
*
|
|
113
|
-
* - On transient errors, switches to exponential backoff (cap 2 min) and
|
|
114
|
-
* resets on the first successful fetch.
|
|
115
|
-
* - Tolerates 404 so deployments without sys_notification degrade silently.
|
|
194
|
+
* - Adaptive interval: 10s while the tab is foregrounded so the bell reflects
|
|
195
|
+
* mentions / assignments within seconds without a server-push transport.
|
|
196
|
+
* - Immediate refetch on `visibilitychange` when the user returns to the tab.
|
|
197
|
+
* - On transient errors, exponential backoff (cap 2 min), reset on success.
|
|
198
|
+
* - Tolerates 404 so deployments without the messaging pipeline degrade
|
|
199
|
+
* silently.
|
|
116
200
|
*
|
|
117
|
-
* Full server-push (SSE / WebSocket) is tracked separately
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* pilots up to ~50 concurrent users.
|
|
201
|
+
* Full server-push (SSE / WebSocket) is tracked separately; this adaptive
|
|
202
|
+
* poll keeps perceived latency ~5s and is sufficient for pilots up to ~50
|
|
203
|
+
* concurrent users.
|
|
121
204
|
*/
|
|
122
205
|
useEffect(() => {
|
|
123
206
|
if (!dataSource || !isApp || !user?.id)
|
|
@@ -131,17 +214,57 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
131
214
|
const MAX_BACKOFF_MS = 120000;
|
|
132
215
|
let backoffMs = ACTIVE_INTERVAL_MS;
|
|
133
216
|
const isMissingResource = (err) => err?.httpStatus === 404 || err?.status === 404 || err?.code === 'object_not_found';
|
|
217
|
+
const READ_STATES = new Set(['read', 'clicked', 'dismissed']);
|
|
134
218
|
const fetchOnce = async () => {
|
|
219
|
+
if (notifInFlightRef.current)
|
|
220
|
+
return;
|
|
221
|
+
notifInFlightRef.current = true;
|
|
135
222
|
try {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
223
|
+
const [inboxRes, receiptRes] = await Promise.all([
|
|
224
|
+
dataSource.find('sys_inbox_message', {
|
|
225
|
+
$filter: { user_id: user.id },
|
|
226
|
+
$orderby: { created_at: 'desc' },
|
|
227
|
+
$top: 20,
|
|
228
|
+
}),
|
|
229
|
+
// Read-state spine. Best-effort: if receipts are unavailable the
|
|
230
|
+
// inbox still renders (everything shows unread) rather than erroring.
|
|
231
|
+
dataSource.find('sys_notification_receipt', {
|
|
232
|
+
$filter: { user_id: user.id, channel: 'inbox' },
|
|
233
|
+
$top: 200,
|
|
234
|
+
}).catch(() => ({ data: [] })),
|
|
235
|
+
]);
|
|
236
|
+
if (!mountedRef.current)
|
|
142
237
|
return;
|
|
143
|
-
|
|
144
|
-
|
|
238
|
+
const rows = Array.isArray(inboxRes?.data) ? inboxRes.data : [];
|
|
239
|
+
const receipts = Array.isArray(receiptRes?.data) ? receiptRes.data : [];
|
|
240
|
+
// notification_id → { id, state } (most-advanced receipt wins).
|
|
241
|
+
const receiptByNotif = new Map();
|
|
242
|
+
for (const r of receipts) {
|
|
243
|
+
const nid = r?.notification_id != null ? String(r.notification_id) : '';
|
|
244
|
+
if (!nid)
|
|
245
|
+
continue;
|
|
246
|
+
const prev = receiptByNotif.get(nid);
|
|
247
|
+
// Prefer a read/clicked/dismissed receipt over a plain delivered one.
|
|
248
|
+
if (!prev || (!READ_STATES.has(prev.state) && READ_STATES.has(r.state))) {
|
|
249
|
+
receiptByNotif.set(nid, { id: String(r.id), state: String(r.state) });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const merged = rows.map((m) => {
|
|
253
|
+
const nid = m?.notification_id != null ? String(m.notification_id) : null;
|
|
254
|
+
const rec = nid ? receiptByNotif.get(nid) : undefined;
|
|
255
|
+
return {
|
|
256
|
+
id: String(m.id),
|
|
257
|
+
notification_id: nid,
|
|
258
|
+
receipt_id: rec?.id ?? null,
|
|
259
|
+
type: m.topic ?? 'notification',
|
|
260
|
+
title: m.title ?? '',
|
|
261
|
+
body: m.body_md ?? null,
|
|
262
|
+
action_url: m.action_url ?? null,
|
|
263
|
+
is_read: rec ? READ_STATES.has(rec.state) : false,
|
|
264
|
+
created_at: m.created_at,
|
|
265
|
+
};
|
|
266
|
+
});
|
|
267
|
+
setNotifications(merged);
|
|
145
268
|
backoffMs = ACTIVE_INTERVAL_MS;
|
|
146
269
|
}
|
|
147
270
|
catch (err) {
|
|
@@ -151,6 +274,9 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
151
274
|
}
|
|
152
275
|
backoffMs = Math.min(backoffMs * 2, MAX_BACKOFF_MS);
|
|
153
276
|
}
|
|
277
|
+
finally {
|
|
278
|
+
notifInFlightRef.current = false;
|
|
279
|
+
}
|
|
154
280
|
};
|
|
155
281
|
const scheduleNext = () => {
|
|
156
282
|
if (cancelled || notificationsUnavailableRef.current)
|
|
@@ -192,6 +318,13 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
192
318
|
* Hits the framework's `/api/v1/approvals/requests?status=pending`
|
|
193
319
|
* endpoint with the user's identities (id, email, role:<r>). Degrades
|
|
194
320
|
* silently to zero on 404 (approvals plugin not installed).
|
|
321
|
+
*
|
|
322
|
+
* The endpoint accepts a comma-separated `approverId` and matches a
|
|
323
|
+
* request when ANY identity is a pending approver, so this issues ONE
|
|
324
|
+
* request per poll. (It previously looped one fetch per identity, firing
|
|
325
|
+
* N near-simultaneous calls every cycle — the dominant duplicate-request
|
|
326
|
+
* offender on the control plane. Requires framework with multi-approverId
|
|
327
|
+
* support; ship the framework + console SHA bumps together.)
|
|
195
328
|
*/
|
|
196
329
|
useEffect(() => {
|
|
197
330
|
if (!isApp || !user?.id)
|
|
@@ -213,27 +346,35 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
213
346
|
let timer = null;
|
|
214
347
|
const POLL_MS = 30000;
|
|
215
348
|
const fetchOnce = async () => {
|
|
349
|
+
if (identities.length === 0)
|
|
350
|
+
return;
|
|
351
|
+
// In-flight dedupe: bootstrap re-runs this effect a few times; coalesce
|
|
352
|
+
// the immediate fetches into one instead of firing them concurrently.
|
|
353
|
+
if (approvalsInFlightRef.current)
|
|
354
|
+
return;
|
|
355
|
+
approvalsInFlightRef.current = true;
|
|
216
356
|
try {
|
|
217
|
-
const
|
|
218
|
-
|
|
357
|
+
const qs = new URLSearchParams({ status: 'pending', approverId: identities.join(',') });
|
|
358
|
+
const res = await fetch(`${base}?${qs}`, { credentials: 'include' });
|
|
359
|
+
if (res.status === 404) {
|
|
360
|
+
approvalsUnavailableRef.current = true;
|
|
219
361
|
return;
|
|
220
|
-
for (const id of identities) {
|
|
221
|
-
const qs = new URLSearchParams({ status: 'pending', approverId: id });
|
|
222
|
-
const res = await fetch(`${base}?${qs}`, { credentials: 'include' });
|
|
223
|
-
if (res.status === 404) {
|
|
224
|
-
approvalsUnavailableRef.current = true;
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
if (!res.ok)
|
|
228
|
-
return;
|
|
229
|
-
const payload = await res.json().catch(() => null);
|
|
230
|
-
for (const row of (payload?.data || []))
|
|
231
|
-
seen.add(row.id);
|
|
232
362
|
}
|
|
233
|
-
if (!
|
|
363
|
+
if (!res.ok)
|
|
364
|
+
return;
|
|
365
|
+
const payload = await res.json().catch(() => null);
|
|
366
|
+
const seen = new Set();
|
|
367
|
+
for (const row of (payload?.data || []))
|
|
368
|
+
seen.add(row.id);
|
|
369
|
+
// Apply if still mounted (not gated on this run's `cancelled`, so the
|
|
370
|
+
// single in-flight fetch survives a bootstrap re-run mid-flight).
|
|
371
|
+
if (mountedRef.current)
|
|
234
372
|
setPendingApprovalsCount(seen.size);
|
|
235
373
|
}
|
|
236
374
|
catch { /* transient — keep last value */ }
|
|
375
|
+
finally {
|
|
376
|
+
approvalsInFlightRef.current = false;
|
|
377
|
+
}
|
|
237
378
|
};
|
|
238
379
|
const schedule = () => {
|
|
239
380
|
if (cancelled || approvalsUnavailableRef.current)
|
|
@@ -245,41 +386,47 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
245
386
|
clearTimeout(timer); };
|
|
246
387
|
}, [isApp, user?.id]);
|
|
247
388
|
const unreadCount = notifications.reduce((n, x) => n + (x.is_read ? 0 : 1), 0);
|
|
389
|
+
// Read-state lives in `sys_notification_receipt`, keyed
|
|
390
|
+
// (notification_id, user_id, channel) — ADR-0030. Marking read UPDATEs the
|
|
391
|
+
// existing `delivered` receipt to `read` (the inbox channel always writes one
|
|
392
|
+
// on materialization); we INSERT only as a fallback for the rare row whose
|
|
393
|
+
// receipt is missing. Rows without a `notification_id` (legacy/synthetic)
|
|
394
|
+
// can't be keyed, so they update optimistically but don't persist.
|
|
395
|
+
const writeReadReceipt = useCallback(async (n, now) => {
|
|
396
|
+
if (!dataSource || !n.notification_id)
|
|
397
|
+
return;
|
|
398
|
+
if (n.receipt_id) {
|
|
399
|
+
await dataSource.update('sys_notification_receipt', n.receipt_id, { state: 'read', at: now });
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
await dataSource.create('sys_notification_receipt', {
|
|
403
|
+
notification_id: n.notification_id,
|
|
404
|
+
user_id: user?.id,
|
|
405
|
+
channel: 'inbox',
|
|
406
|
+
state: 'read',
|
|
407
|
+
at: now,
|
|
408
|
+
created_at: now,
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}, [dataSource, user?.id]);
|
|
248
412
|
const markNotificationRead = useCallback(async (id) => {
|
|
413
|
+
const target = notifications.find(n => n.id === id);
|
|
249
414
|
setNotifications(prev => prev.map(n => n.id === id ? { ...n, is_read: true } : n));
|
|
250
|
-
if (!
|
|
415
|
+
if (!target)
|
|
251
416
|
return;
|
|
252
417
|
try {
|
|
253
|
-
await
|
|
254
|
-
is_read: true,
|
|
255
|
-
read_at: new Date().toISOString(),
|
|
256
|
-
});
|
|
418
|
+
await writeReadReceipt(target, new Date().toISOString());
|
|
257
419
|
}
|
|
258
420
|
catch { /* best-effort */ }
|
|
259
|
-
}, [
|
|
421
|
+
}, [notifications, writeReadReceipt]);
|
|
260
422
|
const markAllRead = useCallback(async () => {
|
|
261
423
|
const unread = notifications.filter(n => !n.is_read);
|
|
262
424
|
if (!unread.length)
|
|
263
425
|
return;
|
|
264
426
|
setNotifications(prev => prev.map(n => ({ ...n, is_read: true })));
|
|
265
|
-
if (!dataSource)
|
|
266
|
-
return;
|
|
267
427
|
const now = new Date().toISOString();
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// N parallel PATCHes, which previously caused noticeable hitching
|
|
271
|
-
// (Slack-style "mark all read" jank) on inboxes with 50+ unread.
|
|
272
|
-
// Fall back to the per-id loop on adapters that don't implement it.
|
|
273
|
-
const ds = dataSource;
|
|
274
|
-
if (typeof ds.bulkUpdate === 'function') {
|
|
275
|
-
try {
|
|
276
|
-
await ds.bulkUpdate('sys_notification', ids, { is_read: true, read_at: now });
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
catch { /* fall through to per-id loop */ }
|
|
280
|
-
}
|
|
281
|
-
await Promise.all(unread.map(n => dataSource.update('sys_notification', n.id, { is_read: true, read_at: now }).catch(() => { })));
|
|
282
|
-
}, [dataSource, notifications]);
|
|
428
|
+
await Promise.all(unread.map(n => writeReadReceipt(n, now).catch(() => { })));
|
|
429
|
+
}, [notifications, writeReadReceipt]);
|
|
283
430
|
const tenantPresence = useTenantPresence();
|
|
284
431
|
const activeUsers = presenceUsers ?? (tenantPresence.length > 0 ? tenantPresence : EMPTY_PRESENCE_USERS);
|
|
285
432
|
const activeActivities = activities ?? apiActivities ?? [];
|
|
@@ -293,7 +440,8 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
293
440
|
const safeObjects = objects ?? [];
|
|
294
441
|
// Filter objects to only those belonging to the current app via its navigation
|
|
295
442
|
const appNameKey = activeAppName || currentAppName || appNameFromRoute;
|
|
296
|
-
|
|
443
|
+
// ADR-0048 (A) — appNameKey may be a package id (route segment); match by it.
|
|
444
|
+
const currentApp = matchAppBySegment(metadataApps || [], appNameKey);
|
|
297
445
|
const appNavObjectNames = new Set();
|
|
298
446
|
const collectNavObjects = (items) => {
|
|
299
447
|
for (const item of items || []) {
|
|
@@ -309,6 +457,13 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
309
457
|
const appObjects = appNavObjectNames.size > 0
|
|
310
458
|
? safeObjects.filter((o) => appNavObjectNames.has(o.name))
|
|
311
459
|
: safeObjects.filter((o) => !o.name.startsWith('sys_') && !o.name.startsWith('auth_'));
|
|
460
|
+
// Help menu — docs owned by the current app (matched by package id, the
|
|
461
|
+
// precise owner link; ADR-0048). Empty when not inside an app, the app
|
|
462
|
+
// ships no docs, or the lazy fetch hasn't run yet.
|
|
463
|
+
const currentAppPackageId = currentApp?._packageId;
|
|
464
|
+
const currentAppDocs = currentAppPackageId
|
|
465
|
+
? (helpDocs ?? []).filter((d) => d._packageId === currentAppPackageId)
|
|
466
|
+
: [];
|
|
312
467
|
const objectSiblings = appObjects.map((o) => ({
|
|
313
468
|
label: objectLabel(o),
|
|
314
469
|
href: `${baseHref}/${o.name}`,
|
|
@@ -319,7 +474,8 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
319
474
|
extraSegments.push({ label: t('console.breadcrumb.dashboards'), href: baseHref });
|
|
320
475
|
if (pathParts[3]) {
|
|
321
476
|
const dashboardName = pathParts[3];
|
|
322
|
-
|
|
477
|
+
// ADR-0048 Phase 2 — prefer the current app's package (container-scoped).
|
|
478
|
+
const dashboardDef = preferLocal(metadataDashboards, dashboardName, currentApp?._packageId);
|
|
323
479
|
const fallback = dashboardDef?.label || humanizeSlug(dashboardName);
|
|
324
480
|
extraSegments.push({ label: dashboardLabel({ name: dashboardName, label: fallback }) });
|
|
325
481
|
}
|
|
@@ -328,7 +484,7 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
328
484
|
extraSegments.push({ label: t('console.breadcrumb.pages'), href: baseHref });
|
|
329
485
|
if (pathParts[3]) {
|
|
330
486
|
const pageName = pathParts[3];
|
|
331
|
-
const pageDef = (metadataPages
|
|
487
|
+
const pageDef = preferLocal(metadataPages, pageName, currentApp?._packageId);
|
|
332
488
|
const fallback = pageDef?.label || humanizeSlug(pageName);
|
|
333
489
|
extraSegments.push({ label: pageLabel({ name: pageName, label: fallback }) });
|
|
334
490
|
}
|
|
@@ -337,7 +493,7 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
337
493
|
extraSegments.push({ label: t('console.breadcrumb.reports'), href: baseHref });
|
|
338
494
|
if (pathParts[3]) {
|
|
339
495
|
const reportName = pathParts[3];
|
|
340
|
-
const reportDef = (metadataReports
|
|
496
|
+
const reportDef = preferLocal(metadataReports, reportName, currentApp?._packageId);
|
|
341
497
|
const fallback = reportDef?.label || humanizeSlug(reportName);
|
|
342
498
|
extraSegments.push({ label: reportLabel({ name: reportName, label: fallback }) });
|
|
343
499
|
}
|
|
@@ -378,10 +534,10 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
378
534
|
}
|
|
379
535
|
}
|
|
380
536
|
const lastSegmentLabel = extraSegments[extraSegments.length - 1]?.label || appName || '';
|
|
381
|
-
return (_jsxs("div", { className: "flex items-center justify-between w-full h-full", children: [_jsxs("div", { className: "flex items-center min-w-0 flex-1", children: [_jsx(Link, { to: "/home", className: cn("flex items-center justify-center h-7 w-7 shrink-0 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", isApp && "hidden sm:flex"), title:
|
|
537
|
+
return (_jsxs("div", { className: "flex items-center justify-between w-full h-full", children: [_jsxs("div", { className: "flex items-center min-w-0 flex-1", children: [_jsx(Link, { to: "/home", className: cn("flex items-center justify-center h-7 w-7 shrink-0 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", isApp && "hidden sm:flex"), title: getProductName(), children: _jsx(Layers, { className: "h-4 w-4" }) }), resolvedVariant === 'home' && (_jsx("span", { className: "hidden sm:inline ml-2 text-sm font-semibold tracking-tight", children: getProductName() })), resolvedVariant === 'orgs' && (_jsxs(_Fragment, { children: [_jsx(PathSep, {}), _jsx("span", { className: "text-sm font-medium text-foreground/80 px-1.5", children: t('organizations.title', { defaultValue: 'Organizations' }) })] })), isApp && (_jsxs(_Fragment, { children: [_jsx(LocalizedSidebarTrigger, { className: "lg:hidden shrink-0 ml-1", "aria-label": t('common.toggleSidebar', { defaultValue: 'Toggle sidebar' }) }), activeAppName && onAppChange ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "hidden sm:flex items-center", children: _jsx(PathSep, {}) }), _jsx("div", { className: "hidden sm:flex items-center", children: _jsx(AppSwitcher, { activeAppName: activeAppName, onAppChange: onAppChange }) })] })) : appName ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "hidden sm:flex items-center", children: _jsx(PathSep, {}) }), _jsx("span", { className: "hidden sm:inline text-sm font-medium text-foreground/80 px-1.5", children: appName })] })) : null, extraSegments.map((seg, i) => {
|
|
382
538
|
const isLast = i === extraSegments.length - 1;
|
|
383
539
|
return (_jsxs("span", { className: "hidden sm:flex items-center min-w-0", children: [_jsx(PathSep, {}), seg.siblings && seg.siblings.length > 1 ? (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { className: `flex items-center gap-1 rounded-md px-1.5 py-1 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring hover:bg-accent hover:text-foreground ${!isLast ? 'text-foreground/60' : 'text-foreground/80'}`, children: [seg.label, _jsx(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" })] }), _jsxs(DropdownMenuContent, { align: "start", sideOffset: 8, className: "w-56 max-h-72 overflow-y-auto", children: [_jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground font-normal", children: "Switch Object" }), _jsx(DropdownMenuSeparator, {}), seg.siblings.map((sibling) => (_jsx(DropdownMenuItem, { asChild: true, children: _jsx(Link, { to: sibling.href, className: "w-full", children: sibling.label }) }, sibling.href)))] })] })) : seg.href ? (_jsx(Link, { to: seg.href, className: `rounded-md px-1.5 py-1 text-sm font-medium transition-colors hover:bg-accent hover:text-foreground truncate max-w-[160px] ${isLast ? 'text-foreground/80' : 'text-foreground/60'}`, children: seg.label })) : (_jsx("span", { className: `px-1.5 py-1 text-sm font-medium truncate max-w-[160px] ${isLast ? 'text-foreground/80' : 'text-foreground/60'}`, children: seg.label }))] }, i));
|
|
384
|
-
}), mobileSwitcher && mobileSwitcher.views.length > 0 ? (mobileSwitcher.views.length > 1 ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "sm:hidden flex items-center gap-0.5 min-w-0 ml-1 rounded-md px-1.5 py-1 text-sm font-medium hover:bg-accent active:bg-accent/80 transition-colors", "aria-label":
|
|
540
|
+
}), mobileSwitcher && mobileSwitcher.views.length > 0 ? (mobileSwitcher.views.length > 1 ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "sm:hidden flex items-center gap-0.5 min-w-0 ml-1 rounded-md px-1.5 py-1 text-sm font-medium hover:bg-accent active:bg-accent/80 transition-colors", "aria-label": t('topbar.switchView', { defaultValue: 'Switch view' }), children: [_jsx("span", { className: "truncate max-w-[180px]", children: mobileSwitcher.triggerLabel ??
|
|
385
541
|
mobileSwitcher.views.find((v) => v.id === mobileSwitcher.activeViewId)?.label ??
|
|
386
542
|
lastSegmentLabel }), _jsx(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" })] }) }), _jsx(DropdownMenuContent, { align: "start", className: "min-w-[220px] max-w-[280px]", children: mobileSwitcher.views.map((v) => {
|
|
387
543
|
const isActive = v.id === mobileSwitcher.activeViewId;
|
|
@@ -389,5 +545,14 @@ export function AppHeader({ variant, appName, objects, connectionState, presence
|
|
|
389
545
|
if (!isActive)
|
|
390
546
|
mobileSwitcher.onChange(v.id);
|
|
391
547
|
}, className: "gap-2", children: [v.icon ? (_jsx("span", { className: "shrink-0 text-muted-foreground [&>svg]:h-4 [&>svg]:w-4", children: v.icon })) : null, _jsx("span", { className: "flex-1 truncate", children: v.label }), v.locked ? (_jsx(Lock, { className: "h-3 w-3 shrink-0 text-muted-foreground", "aria-hidden": true })) : null, isActive ? (_jsx(Check, { className: "h-4 w-4 shrink-0 text-foreground", "aria-hidden": true })) : null] }, v.id));
|
|
392
|
-
}) })] })) : (_jsx("span", { className: "text-sm font-medium sm:hidden truncate min-w-0 ml-1", children: mobileSwitcher.triggerLabel ?? mobileSwitcher.views[0].label }))) : (_jsx("span", { className: "text-sm font-medium sm:hidden truncate min-w-0 ml-1", children: lastSegmentLabel }))] }))] }), _jsxs("div", { className: "flex items-center gap-0.5 sm:gap-1 shrink-0 [&>*+*[data-topbar-group]]:ml-1 [&>[data-topbar-group]+[data-topbar-group]]:border-l [&>[data-topbar-group]+[data-topbar-group]]:border-border/60 [&>[data-topbar-group]+[data-topbar-group]]:pl-1 sm:[&>[data-topbar-group]+[data-topbar-group]]:pl-2 sm:[&>[data-topbar-group]+[data-topbar-group]]:ml-2", children: [!isOnline && (_jsxs("div", { className: "flex items-center gap-1 px-2 py-1 rounded-full bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-200 text-xs font-medium", children: [_jsx("span", { className: "h-2 w-2 rounded-full bg-yellow-500 animate-pulse" }),
|
|
548
|
+
}) })] })) : (_jsx("span", { className: "text-sm font-medium sm:hidden truncate min-w-0 ml-1", children: mobileSwitcher.triggerLabel ?? mobileSwitcher.views[0].label }))) : (_jsx("span", { className: "text-sm font-medium sm:hidden truncate min-w-0 ml-1", children: lastSegmentLabel }))] }))] }), _jsxs("div", { className: "flex items-center gap-0.5 sm:gap-1 shrink-0 [&>*+*[data-topbar-group]]:ml-1 [&>[data-topbar-group]+[data-topbar-group]]:border-l [&>[data-topbar-group]+[data-topbar-group]]:border-border/60 [&>[data-topbar-group]+[data-topbar-group]]:pl-1 sm:[&>[data-topbar-group]+[data-topbar-group]]:pl-2 sm:[&>[data-topbar-group]+[data-topbar-group]]:ml-2", children: [!isOnline && (_jsxs("div", { className: "flex items-center gap-1 px-2 py-1 rounded-full bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-200 text-xs font-medium", children: [_jsx("span", { className: "h-2 w-2 rounded-full bg-yellow-500 animate-pulse" }), t('topbar.offline', { defaultValue: 'Offline' })] })), isApp && connectionState && _jsx(ConnectionStatus, { state: connectionState }), isApp && activeUsers.length > 0 && (_jsx("div", { className: "hidden md:flex items-center shrink-0", title: t('topbar.usersOnline', { defaultValue: 'Users currently online' }), children: _jsx(PresenceAvatars, { users: activeUsers, size: "sm", maxVisible: 3, showStatus: true }) })), _jsxs("div", { "data-topbar-group": true, className: "flex items-center gap-0.5 sm:gap-1 shrink-0", children: [_jsxs("button", { type: "button", "data-testid": "action:command-palette:open", "aria-label": t('console.search', { defaultValue: 'Search…' }), "aria-keyshortcuts": "Meta+K Control+K", onClick: openCommandPalette, className: "hidden lg:flex relative items-center gap-2 w-48 xl:w-64 h-8 px-3 text-sm rounded-md border bg-muted/50 text-muted-foreground hover:bg-muted transition-colors", children: [_jsx(Search, { className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "flex-1 text-left text-xs", children: t('console.search', { defaultValue: 'Search…' }) }), _jsxs("kbd", { className: "pointer-events-none inline-flex h-5 items-center gap-0.5 rounded border bg-background px-1.5 text-[10px] font-medium text-muted-foreground", children: [_jsx("span", { className: "text-xs", children: "\u2318" }), "K"] })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "lg:hidden h-8 w-8 shrink-0", "data-testid": "action:command-palette:open-mobile", onClick: openCommandPalette, "aria-label": t('console.search', { defaultValue: 'Search…' }), children: _jsx(Search, { className: "h-4 w-4" }) })] }), _jsxs("div", { "data-topbar-group": true, className: "flex items-center gap-0.5 shrink-0", children: [_jsx(InboxPopover, { notifications: notifications, unreadCount: unreadCount, pendingApprovalsCount: pendingApprovalsCount, activities: activeActivities, onMarkAllRead: markAllRead, onMarkRead: markNotificationRead }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 shrink-0", asChild: true, "aria-label": t('topbar.aiAssistant', { defaultValue: 'AI Assistant' }), children: _jsx(Link, { to: "/ai", children: _jsx(Bot, { className: "h-4 w-4" }) }) }), _jsxs(DropdownMenu, { onOpenChange: (open) => { if (open)
|
|
549
|
+
void loadHelpDocs(); }, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 hidden md:flex shrink-0", "aria-label": t('sidebar.helpTooltip', { defaultValue: 'Help & Documentation' }), children: _jsx(HelpCircle, { className: "h-4 w-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: "min-w-56 rounded-lg", sideOffset: 4, children: [currentAppDocs.length > 0 && currentAppPackageId ? (_jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => navigate(currentAppDocs.length === 1
|
|
550
|
+
? `/apps/${currentAppPackageId}/docs/${currentAppDocs[0].name}`
|
|
551
|
+
: `/apps/${currentAppPackageId}/docs`), children: [_jsx(BookOpen, { className: "mr-2 h-4 w-4" }), t('help.appDocs', { defaultValue: "This app's docs" })] })) : null, _jsxs(DropdownMenuItem, { className: "cursor-pointer", onClick: () => navigate('/docs'), children: [_jsx(Layers, { className: "mr-2 h-4 w-4" }), t('help.allDocs', { defaultValue: 'All documentation' })] }), isApp ? (_jsxs(DropdownMenuItem, { className: "cursor-pointer", "data-testid": "action:keyboard-shortcuts:open", onClick: openShortcuts, children: [_jsx(Keyboard, { className: "mr-2 h-4 w-4" }), t('help.keyboardShortcuts', { defaultValue: 'Keyboard shortcuts' })] })) : null, _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { asChild: true, className: "cursor-pointer", children: _jsxs("a", { href: "https://docs.objectstack.ai", target: "_blank", rel: "noopener noreferrer", children: [_jsx(ExternalLink, { className: "mr-2 h-4 w-4" }), t('help.onlineDocs', { defaultValue: 'Online documentation' })] }) })] })] })] }), _jsxs("div", { "data-topbar-group": true, className: "flex items-center gap-0.5 shrink-0", children: [" ", _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "h-8 w-8 shrink-0 rounded-full", children: _jsxs(Avatar, { className: "h-7 w-7 rounded-full", children: [_jsx(AvatarImage, { src: user?.image, alt: user?.name ?? 'User' }), _jsx(AvatarFallback, { className: "rounded-full bg-primary text-primary-foreground text-xs", children: getUserInitials(user) })] }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: "min-w-64 rounded-lg", sideOffset: 4, children: [_jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: _jsxs("div", { className: "flex items-center gap-2 px-2 py-2", children: [_jsxs(Avatar, { className: "h-8 w-8 rounded-lg", children: [_jsx(AvatarImage, { src: user?.image, alt: user?.name ?? 'User' }), _jsx(AvatarFallback, { className: "rounded-lg bg-primary text-primary-foreground", children: getUserInitials(user) })] }), _jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [_jsx("span", { className: "truncate font-semibold", children: user?.name ?? 'User' }), _jsx("span", { className: "truncate text-xs text-muted-foreground", children: user?.email ?? '' })] })] }) }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuGroup, { children: [_jsxs(DropdownMenuItem, { onClick: () => navigate('/apps/account/component/account/profile_card'), className: "cursor-pointer", children: [_jsx(User, { className: "mr-2 h-4 w-4" }), t('user.profile', { defaultValue: 'Profile' })] }), hasOrgSection && (_jsxs(DropdownMenuItem, { onClick: () => navigate('/organizations'), className: "cursor-pointer", children: [_jsx(Boxes, { className: "mr-2 h-4 w-4" }), t('organizations.mine', { defaultValue: 'My Organizations' })] })), (metadataApps || [])
|
|
552
|
+
.filter((a) => a.active !== false && a.hidden === true && a.name !== 'account')
|
|
553
|
+
.map((app) => {
|
|
554
|
+
const AppIcon = getIcon(app.icon);
|
|
555
|
+
const label = appLabel({ name: app.name, label: resolveI18nLabel(app.label, t) });
|
|
556
|
+
return (_jsxs(DropdownMenuItem, { onClick: () => navigate(`/apps/${appRouteSegment(app) ?? app.name}`), className: "cursor-pointer", children: [_jsx(AppIcon, { className: "mr-2 h-4 w-4" }), label] }, `hidden_app_${app.name}`));
|
|
557
|
+
})] }), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuLabel, { className: "text-[11px] font-normal text-muted-foreground uppercase tracking-wide px-2", children: t('user.preferences', { defaultValue: 'Preferences' }) }), _jsxs("div", { className: "flex items-center justify-between px-2 py-1.5 text-sm", children: [_jsx("span", { className: "text-foreground/80", children: t('user.theme', { defaultValue: 'Theme' }) }), _jsx(ModeToggle, {})] }), _jsxs("div", { className: "flex items-center justify-between px-2 py-1.5 text-sm", children: [_jsx("span", { className: "text-foreground/80", children: t('user.language', { defaultValue: 'Language' }) }), _jsx(LocaleSwitcher, {})] }), isAuthEnabled && (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onClick: () => signOut(), children: [_jsx(LogOut, { className: "mr-2 h-4 w-4" }), t('user.logout', { defaultValue: 'Log out' })] })] }))] })] })] })] })] }));
|
|
393
558
|
}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* and mobile swipe gesture.
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
+
import * as React from 'react';
|
|
11
12
|
export declare function AppSidebar({ activeAppName, onAppChange }: {
|
|
12
13
|
activeAppName: string;
|
|
13
14
|
onAppChange: (name: string) => void;
|
|
14
|
-
}):
|
|
15
|
+
}): React.JSX.Element;
|