@multiplatform.one/backoffice 6.3.0 → 6.4.1
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/dist/cjs/chrome/CommandPalette.cjs +20 -9
- package/dist/cjs/chrome/CommandPalette.native.js +18 -10
- package/dist/cjs/chrome/CommandPalette.native.js.map +1 -1
- package/dist/cjs/i18n/en.cjs +21 -0
- package/dist/cjs/i18n/en.native.js +21 -0
- package/dist/cjs/i18n/en.native.js.map +1 -1
- package/dist/cjs/index.cjs +49 -1
- package/dist/cjs/index.native.js +48 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/shared/types.cjs +18 -0
- package/dist/cjs/shared/types.native.js +21 -0
- package/dist/cjs/shared/types.native.js.map +1 -0
- package/dist/cjs/shared/useDocinfo.cjs +116 -0
- package/dist/cjs/shared/useDocinfo.native.js +167 -0
- package/dist/cjs/shared/useDocinfo.native.js.map +1 -0
- package/dist/cjs/shared/useDoctypeMeta.cjs +124 -0
- package/dist/cjs/shared/useDoctypeMeta.native.js +158 -0
- package/dist/cjs/shared/useDoctypeMeta.native.js.map +1 -0
- package/dist/cjs/shared/useRecentVisit.cjs +40 -0
- package/dist/cjs/shared/useRecentVisit.native.js +43 -0
- package/dist/cjs/shared/useRecentVisit.native.js.map +1 -0
- package/dist/cjs/shared/useSessionUserId.cjs +54 -0
- package/dist/cjs/shared/useSessionUserId.native.js +59 -0
- package/dist/cjs/shared/useSessionUserId.native.js.map +1 -0
- package/dist/cjs/shared/useSlugTarget.cjs +138 -0
- package/dist/cjs/shared/useSlugTarget.native.js +166 -0
- package/dist/cjs/shared/useSlugTarget.native.js.map +1 -0
- package/dist/cjs/shared/useUserRoles.cjs +72 -0
- package/dist/cjs/shared/useUserRoles.native.js +79 -0
- package/dist/cjs/shared/useUserRoles.native.js.map +1 -0
- package/dist/cjs/shell/WorkspaceSidebar.cjs +4 -0
- package/dist/cjs/shell/WorkspaceSidebar.native.js +4 -0
- package/dist/cjs/shell/WorkspaceSidebar.native.js.map +1 -1
- package/dist/cjs/workspace/WorkspaceChartBlock.cjs +136 -0
- package/dist/cjs/workspace/WorkspaceChartBlock.native.js +144 -0
- package/dist/cjs/workspace/WorkspaceChartBlock.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceGrid.cjs +91 -0
- package/dist/cjs/workspace/WorkspaceGrid.native.js +126 -0
- package/dist/cjs/workspace/WorkspaceGrid.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceLinkCard.cjs +139 -0
- package/dist/cjs/workspace/WorkspaceLinkCard.native.js +155 -0
- package/dist/cjs/workspace/WorkspaceLinkCard.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceLinkDirectory.cjs +110 -0
- package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js +127 -0
- package/dist/cjs/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceNumberCard.cjs +133 -0
- package/dist/cjs/workspace/WorkspaceNumberCard.native.js +138 -0
- package/dist/cjs/workspace/WorkspaceNumberCard.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceQuickList.cjs +112 -0
- package/dist/cjs/workspace/WorkspaceQuickList.native.js +130 -0
- package/dist/cjs/workspace/WorkspaceQuickList.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceRecents.cjs +116 -0
- package/dist/cjs/workspace/WorkspaceRecents.native.js +132 -0
- package/dist/cjs/workspace/WorkspaceRecents.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceScreen.cjs +291 -0
- package/dist/cjs/workspace/WorkspaceScreen.native.js +323 -0
- package/dist/cjs/workspace/WorkspaceScreen.native.js.map +1 -0
- package/dist/cjs/workspace/WorkspaceShortcut.cjs +185 -0
- package/dist/cjs/workspace/WorkspaceShortcut.native.js +202 -0
- package/dist/cjs/workspace/WorkspaceShortcut.native.js.map +1 -0
- package/dist/cjs/workspace/parseContent.cjs +180 -0
- package/dist/cjs/workspace/parseContent.native.js +299 -0
- package/dist/cjs/workspace/parseContent.native.js.map +1 -0
- package/dist/cjs/workspace/types.cjs +18 -0
- package/dist/cjs/workspace/types.native.js +21 -0
- package/dist/cjs/workspace/types.native.js.map +1 -0
- package/dist/cjs/workspace/useDashboardChart.cjs +96 -0
- package/dist/cjs/workspace/useDashboardChart.native.js +110 -0
- package/dist/cjs/workspace/useDashboardChart.native.js.map +1 -0
- package/dist/cjs/workspace/useWorkspaceDoc.cjs +103 -0
- package/dist/cjs/workspace/useWorkspaceDoc.native.js +120 -0
- package/dist/cjs/workspace/useWorkspaceDoc.native.js.map +1 -0
- package/dist/esm/chrome/CommandPalette.mjs +20 -9
- package/dist/esm/chrome/CommandPalette.mjs.map +1 -1
- package/dist/esm/chrome/CommandPalette.native.js +18 -10
- package/dist/esm/chrome/CommandPalette.native.js.map +1 -1
- package/dist/esm/i18n/en.mjs +21 -0
- package/dist/esm/i18n/en.mjs.map +1 -1
- package/dist/esm/i18n/en.native.js +21 -0
- package/dist/esm/i18n/en.native.js.map +1 -1
- package/dist/esm/index.mjs +19 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +19 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/shared/types.mjs +2 -0
- package/dist/esm/shared/types.mjs.map +1 -0
- package/dist/esm/shared/types.native.js +2 -0
- package/dist/esm/shared/types.native.js.map +1 -0
- package/dist/esm/shared/useDocinfo.mjs +90 -0
- package/dist/esm/shared/useDocinfo.mjs.map +1 -0
- package/dist/esm/shared/useDocinfo.native.js +138 -0
- package/dist/esm/shared/useDocinfo.native.js.map +1 -0
- package/dist/esm/shared/useDoctypeMeta.mjs +99 -0
- package/dist/esm/shared/useDoctypeMeta.mjs.map +1 -0
- package/dist/esm/shared/useDoctypeMeta.native.js +130 -0
- package/dist/esm/shared/useDoctypeMeta.native.js.map +1 -0
- package/dist/esm/shared/useRecentVisit.mjs +15 -0
- package/dist/esm/shared/useRecentVisit.mjs.map +1 -0
- package/dist/esm/shared/useRecentVisit.native.js +15 -0
- package/dist/esm/shared/useRecentVisit.native.js.map +1 -0
- package/dist/esm/shared/useSessionUserId.mjs +29 -0
- package/dist/esm/shared/useSessionUserId.mjs.map +1 -0
- package/dist/esm/shared/useSessionUserId.native.js +31 -0
- package/dist/esm/shared/useSessionUserId.native.js.map +1 -0
- package/dist/esm/shared/useSlugTarget.mjs +113 -0
- package/dist/esm/shared/useSlugTarget.mjs.map +1 -0
- package/dist/esm/shared/useSlugTarget.native.js +138 -0
- package/dist/esm/shared/useSlugTarget.native.js.map +1 -0
- package/dist/esm/shared/useUserRoles.mjs +47 -0
- package/dist/esm/shared/useUserRoles.mjs.map +1 -0
- package/dist/esm/shared/useUserRoles.native.js +51 -0
- package/dist/esm/shared/useUserRoles.native.js.map +1 -0
- package/dist/esm/shell/WorkspaceSidebar.mjs +4 -0
- package/dist/esm/shell/WorkspaceSidebar.mjs.map +1 -1
- package/dist/esm/shell/WorkspaceSidebar.native.js +4 -0
- package/dist/esm/shell/WorkspaceSidebar.native.js.map +1 -1
- package/dist/esm/workspace/WorkspaceChartBlock.mjs +111 -0
- package/dist/esm/workspace/WorkspaceChartBlock.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceChartBlock.native.js +116 -0
- package/dist/esm/workspace/WorkspaceChartBlock.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceGrid.mjs +66 -0
- package/dist/esm/workspace/WorkspaceGrid.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceGrid.native.js +98 -0
- package/dist/esm/workspace/WorkspaceGrid.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceLinkCard.mjs +113 -0
- package/dist/esm/workspace/WorkspaceLinkCard.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceLinkCard.native.js +126 -0
- package/dist/esm/workspace/WorkspaceLinkCard.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceLinkDirectory.mjs +84 -0
- package/dist/esm/workspace/WorkspaceLinkDirectory.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceLinkDirectory.native.js +98 -0
- package/dist/esm/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceNumberCard.mjs +108 -0
- package/dist/esm/workspace/WorkspaceNumberCard.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceNumberCard.native.js +110 -0
- package/dist/esm/workspace/WorkspaceNumberCard.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceQuickList.mjs +87 -0
- package/dist/esm/workspace/WorkspaceQuickList.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceQuickList.native.js +102 -0
- package/dist/esm/workspace/WorkspaceQuickList.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceRecents.mjs +91 -0
- package/dist/esm/workspace/WorkspaceRecents.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceRecents.native.js +104 -0
- package/dist/esm/workspace/WorkspaceRecents.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceScreen.mjs +266 -0
- package/dist/esm/workspace/WorkspaceScreen.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceScreen.native.js +295 -0
- package/dist/esm/workspace/WorkspaceScreen.native.js.map +1 -0
- package/dist/esm/workspace/WorkspaceShortcut.mjs +159 -0
- package/dist/esm/workspace/WorkspaceShortcut.mjs.map +1 -0
- package/dist/esm/workspace/WorkspaceShortcut.native.js +173 -0
- package/dist/esm/workspace/WorkspaceShortcut.native.js.map +1 -0
- package/dist/esm/workspace/parseContent.mjs +148 -0
- package/dist/esm/workspace/parseContent.mjs.map +1 -0
- package/dist/esm/workspace/parseContent.native.js +264 -0
- package/dist/esm/workspace/parseContent.native.js.map +1 -0
- package/dist/esm/workspace/types.mjs +2 -0
- package/dist/esm/workspace/types.mjs.map +1 -0
- package/dist/esm/workspace/types.native.js +2 -0
- package/dist/esm/workspace/types.native.js.map +1 -0
- package/dist/esm/workspace/useDashboardChart.mjs +71 -0
- package/dist/esm/workspace/useDashboardChart.mjs.map +1 -0
- package/dist/esm/workspace/useDashboardChart.native.js +82 -0
- package/dist/esm/workspace/useDashboardChart.native.js.map +1 -0
- package/dist/esm/workspace/useWorkspaceDoc.mjs +77 -0
- package/dist/esm/workspace/useWorkspaceDoc.mjs.map +1 -0
- package/dist/esm/workspace/useWorkspaceDoc.native.js +91 -0
- package/dist/esm/workspace/useWorkspaceDoc.native.js.map +1 -0
- package/dist/jsx/chrome/CommandPalette.mjs +20 -9
- package/dist/jsx/chrome/CommandPalette.mjs.map +1 -1
- package/dist/jsx/chrome/CommandPalette.native.js +18 -10
- package/dist/jsx/chrome/CommandPalette.native.js.map +1 -1
- package/dist/jsx/i18n/en.mjs +21 -0
- package/dist/jsx/i18n/en.mjs.map +1 -1
- package/dist/jsx/i18n/en.native.js +21 -0
- package/dist/jsx/i18n/en.native.js.map +1 -1
- package/dist/jsx/index.js +19 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +19 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +48 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/types.mjs +2 -0
- package/dist/jsx/shared/types.mjs.map +1 -0
- package/dist/jsx/shared/types.native.js +21 -0
- package/dist/jsx/shared/types.native.js.map +1 -0
- package/dist/jsx/shared/useDocinfo.mjs +90 -0
- package/dist/jsx/shared/useDocinfo.mjs.map +1 -0
- package/dist/jsx/shared/useDocinfo.native.js +167 -0
- package/dist/jsx/shared/useDocinfo.native.js.map +1 -0
- package/dist/jsx/shared/useDoctypeMeta.mjs +99 -0
- package/dist/jsx/shared/useDoctypeMeta.mjs.map +1 -0
- package/dist/jsx/shared/useDoctypeMeta.native.js +158 -0
- package/dist/jsx/shared/useDoctypeMeta.native.js.map +1 -0
- package/dist/jsx/shared/useRecentVisit.mjs +15 -0
- package/dist/jsx/shared/useRecentVisit.mjs.map +1 -0
- package/dist/jsx/shared/useRecentVisit.native.js +43 -0
- package/dist/jsx/shared/useRecentVisit.native.js.map +1 -0
- package/dist/jsx/shared/useSessionUserId.mjs +29 -0
- package/dist/jsx/shared/useSessionUserId.mjs.map +1 -0
- package/dist/jsx/shared/useSessionUserId.native.js +59 -0
- package/dist/jsx/shared/useSessionUserId.native.js.map +1 -0
- package/dist/jsx/shared/useSlugTarget.mjs +113 -0
- package/dist/jsx/shared/useSlugTarget.mjs.map +1 -0
- package/dist/jsx/shared/useSlugTarget.native.js +166 -0
- package/dist/jsx/shared/useSlugTarget.native.js.map +1 -0
- package/dist/jsx/shared/useUserRoles.mjs +47 -0
- package/dist/jsx/shared/useUserRoles.mjs.map +1 -0
- package/dist/jsx/shared/useUserRoles.native.js +79 -0
- package/dist/jsx/shared/useUserRoles.native.js.map +1 -0
- package/dist/jsx/shell/WorkspaceSidebar.mjs +4 -0
- package/dist/jsx/shell/WorkspaceSidebar.mjs.map +1 -1
- package/dist/jsx/shell/WorkspaceSidebar.native.js +4 -0
- package/dist/jsx/shell/WorkspaceSidebar.native.js.map +1 -1
- package/dist/jsx/workspace/WorkspaceChartBlock.mjs +111 -0
- package/dist/jsx/workspace/WorkspaceChartBlock.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceChartBlock.native.js +144 -0
- package/dist/jsx/workspace/WorkspaceChartBlock.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceGrid.mjs +66 -0
- package/dist/jsx/workspace/WorkspaceGrid.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceGrid.native.js +126 -0
- package/dist/jsx/workspace/WorkspaceGrid.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceLinkCard.mjs +113 -0
- package/dist/jsx/workspace/WorkspaceLinkCard.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceLinkCard.native.js +155 -0
- package/dist/jsx/workspace/WorkspaceLinkCard.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceLinkDirectory.mjs +84 -0
- package/dist/jsx/workspace/WorkspaceLinkDirectory.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js +127 -0
- package/dist/jsx/workspace/WorkspaceLinkDirectory.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceNumberCard.mjs +108 -0
- package/dist/jsx/workspace/WorkspaceNumberCard.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceNumberCard.native.js +138 -0
- package/dist/jsx/workspace/WorkspaceNumberCard.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceQuickList.mjs +87 -0
- package/dist/jsx/workspace/WorkspaceQuickList.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceQuickList.native.js +130 -0
- package/dist/jsx/workspace/WorkspaceQuickList.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceRecents.mjs +91 -0
- package/dist/jsx/workspace/WorkspaceRecents.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceRecents.native.js +132 -0
- package/dist/jsx/workspace/WorkspaceRecents.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceScreen.mjs +266 -0
- package/dist/jsx/workspace/WorkspaceScreen.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceScreen.native.js +323 -0
- package/dist/jsx/workspace/WorkspaceScreen.native.js.map +1 -0
- package/dist/jsx/workspace/WorkspaceShortcut.mjs +159 -0
- package/dist/jsx/workspace/WorkspaceShortcut.mjs.map +1 -0
- package/dist/jsx/workspace/WorkspaceShortcut.native.js +202 -0
- package/dist/jsx/workspace/WorkspaceShortcut.native.js.map +1 -0
- package/dist/jsx/workspace/parseContent.mjs +148 -0
- package/dist/jsx/workspace/parseContent.mjs.map +1 -0
- package/dist/jsx/workspace/parseContent.native.js +299 -0
- package/dist/jsx/workspace/parseContent.native.js.map +1 -0
- package/dist/jsx/workspace/types.mjs +2 -0
- package/dist/jsx/workspace/types.mjs.map +1 -0
- package/dist/jsx/workspace/types.native.js +21 -0
- package/dist/jsx/workspace/types.native.js.map +1 -0
- package/dist/jsx/workspace/useDashboardChart.mjs +71 -0
- package/dist/jsx/workspace/useDashboardChart.mjs.map +1 -0
- package/dist/jsx/workspace/useDashboardChart.native.js +110 -0
- package/dist/jsx/workspace/useDashboardChart.native.js.map +1 -0
- package/dist/jsx/workspace/useWorkspaceDoc.mjs +77 -0
- package/dist/jsx/workspace/useWorkspaceDoc.mjs.map +1 -0
- package/dist/jsx/workspace/useWorkspaceDoc.native.js +120 -0
- package/dist/jsx/workspace/useWorkspaceDoc.native.js.map +1 -0
- package/package.json +12 -12
- package/src/chrome/CommandPalette.tsx +35 -15
- package/src/i18n/en.ts +21 -0
- package/src/index.ts +69 -0
- package/src/shared/types.ts +14 -0
- package/src/shared/useDocinfo.ts +163 -0
- package/src/shared/useDoctypeMeta.ts +243 -0
- package/src/shared/useRecentVisit.ts +33 -0
- package/src/shared/useSessionUserId.ts +42 -0
- package/src/shared/useSlugTarget.ts +143 -0
- package/src/shared/useUserRoles.ts +66 -0
- package/src/shell/WorkspaceSidebar.tsx +3 -0
- package/src/workspace/WorkspaceChartBlock.tsx +115 -0
- package/src/workspace/WorkspaceGrid.tsx +82 -0
- package/src/workspace/WorkspaceLinkCard.tsx +134 -0
- package/src/workspace/WorkspaceLinkDirectory.tsx +126 -0
- package/src/workspace/WorkspaceNumberCard.tsx +126 -0
- package/src/workspace/WorkspaceQuickList.tsx +100 -0
- package/src/workspace/WorkspaceRecents.tsx +100 -0
- package/src/workspace/WorkspaceScreen.tsx +322 -0
- package/src/workspace/WorkspaceShortcut.tsx +223 -0
- package/src/workspace/parseContent.spec.ts +327 -0
- package/src/workspace/parseContent.ts +240 -0
- package/src/workspace/types.ts +135 -0
- package/src/workspace/useDashboardChart.ts +115 -0
- package/src/workspace/useWorkspaceDoc.ts +111 -0
- package/types/chrome/CommandPalette.d.ts.map +1 -1
- package/types/i18n/en.d.ts +19 -0
- package/types/i18n/en.d.ts.map +1 -1
- package/types/index.d.ts +34 -0
- package/types/index.d.ts.map +1 -1
- package/types/shared/types.d.ts +21 -0
- package/types/shared/types.d.ts.map +1 -0
- package/types/shared/useDocinfo.d.ts +61 -0
- package/types/shared/useDocinfo.d.ts.map +1 -0
- package/types/shared/useDoctypeMeta.d.ts +118 -0
- package/types/shared/useDoctypeMeta.d.ts.map +1 -0
- package/types/shared/useRecentVisit.d.ts +10 -0
- package/types/shared/useRecentVisit.d.ts.map +1 -0
- package/types/shared/useSessionUserId.d.ts +6 -0
- package/types/shared/useSessionUserId.d.ts.map +1 -0
- package/types/shared/useSlugTarget.d.ts +18 -0
- package/types/shared/useSlugTarget.d.ts.map +1 -0
- package/types/shared/useUserRoles.d.ts +15 -0
- package/types/shared/useUserRoles.d.ts.map +1 -0
- package/types/shell/WorkspaceSidebar.d.ts.map +1 -1
- package/types/workspace/WorkspaceChartBlock.d.ts +6 -0
- package/types/workspace/WorkspaceChartBlock.d.ts.map +1 -0
- package/types/workspace/WorkspaceGrid.d.ts +23 -0
- package/types/workspace/WorkspaceGrid.d.ts.map +1 -0
- package/types/workspace/WorkspaceLinkCard.d.ts +20 -0
- package/types/workspace/WorkspaceLinkCard.d.ts.map +1 -0
- package/types/workspace/WorkspaceLinkDirectory.d.ts +19 -0
- package/types/workspace/WorkspaceLinkDirectory.d.ts.map +1 -0
- package/types/workspace/WorkspaceNumberCard.d.ts +19 -0
- package/types/workspace/WorkspaceNumberCard.d.ts.map +1 -0
- package/types/workspace/WorkspaceQuickList.d.ts +6 -0
- package/types/workspace/WorkspaceQuickList.d.ts.map +1 -0
- package/types/workspace/WorkspaceRecents.d.ts +2 -0
- package/types/workspace/WorkspaceRecents.d.ts.map +1 -0
- package/types/workspace/WorkspaceScreen.d.ts +24 -0
- package/types/workspace/WorkspaceScreen.d.ts.map +1 -0
- package/types/workspace/WorkspaceShortcut.d.ts +27 -0
- package/types/workspace/WorkspaceShortcut.d.ts.map +1 -0
- package/types/workspace/parseContent.d.ts +77 -0
- package/types/workspace/parseContent.d.ts.map +1 -0
- package/types/workspace/types.d.ts +112 -0
- package/types/workspace/types.d.ts.map +1 -0
- package/types/workspace/useDashboardChart.d.ts +29 -0
- package/types/workspace/useDashboardChart.d.ts.map +1 -0
- package/types/workspace/useWorkspaceDoc.d.ts +18 -0
- package/types/workspace/useWorkspaceDoc.d.ts.map +1 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace number card block — renders a Number Card doc by name.
|
|
3
|
+
*
|
|
4
|
+
* "Document Type" cards (the default) map cleanly onto the live aggregate
|
|
5
|
+
* widget: `function` (Count/Sum/Average/Minimum/Maximum) +
|
|
6
|
+
* `aggregate_function_based_on` + `filters_json` become a FrappeKPICard
|
|
7
|
+
* data source, so the value is realtime like desk. "Report" and "Custom"
|
|
8
|
+
* cards need server-side evaluation
|
|
9
|
+
* (`frappe.desk.doctype.number_card.number_card.get_result`) and are
|
|
10
|
+
* rendered as an informational card for now (documented gap).
|
|
11
|
+
*/
|
|
12
|
+
import { Card, SizableText, Skeleton, YStack } from "@multiplatform.one/components";
|
|
13
|
+
import {
|
|
14
|
+
FrappeKPICard,
|
|
15
|
+
type FrappeAggregateOperation,
|
|
16
|
+
type FrappeKPIDataSource,
|
|
17
|
+
} from "@multiplatform.one/frappe-ui";
|
|
18
|
+
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
19
|
+
import { useMemo } from "react";
|
|
20
|
+
import { useTranslation } from "react-i18next";
|
|
21
|
+
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
22
|
+
import { parseFrappeFilters } from "./parseContent";
|
|
23
|
+
import type { WorkspaceNumberCardRow } from "./types";
|
|
24
|
+
import { useFrappeDoc } from "./useWorkspaceDoc";
|
|
25
|
+
|
|
26
|
+
export interface NumberCardDoc {
|
|
27
|
+
name: string;
|
|
28
|
+
doctype: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
/** "Document Type" | "Report" | "Custom" */
|
|
31
|
+
type?: string;
|
|
32
|
+
document_type?: string;
|
|
33
|
+
/** "Count" | "Sum" | "Average" | "Minimum" | "Maximum" */
|
|
34
|
+
function?: string;
|
|
35
|
+
aggregate_function_based_on?: string;
|
|
36
|
+
filters_json?: string;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const FUNCTION_MAP: Record<string, FrappeAggregateOperation> = {
|
|
41
|
+
Count: "count",
|
|
42
|
+
Sum: "sum",
|
|
43
|
+
Average: "avg",
|
|
44
|
+
Minimum: "min",
|
|
45
|
+
Maximum: "max",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export interface WorkspaceNumberCardProps {
|
|
49
|
+
row: WorkspaceNumberCardRow;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function WorkspaceNumberCard({ row }: WorkspaceNumberCardProps) {
|
|
53
|
+
const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
|
|
54
|
+
const { knobProps } = useResolvedKnobs();
|
|
55
|
+
const { doc, isLoading, error } = useFrappeDoc<NumberCardDoc>(
|
|
56
|
+
"Number Card",
|
|
57
|
+
row.number_card_name,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const title = row.label || doc?.label || row.number_card_name;
|
|
61
|
+
|
|
62
|
+
const dataSource = useMemo<FrappeKPIDataSource | undefined>(() => {
|
|
63
|
+
if (!doc?.document_type) return undefined;
|
|
64
|
+
if (doc.type && doc.type !== "Document Type") return undefined;
|
|
65
|
+
const aggregate = FUNCTION_MAP[doc.function ?? "Count"] ?? "count";
|
|
66
|
+
return {
|
|
67
|
+
doctype: doc.document_type,
|
|
68
|
+
aggregate,
|
|
69
|
+
field: aggregate === "count" ? undefined : doc.aggregate_function_based_on,
|
|
70
|
+
filters: parseFrappeFilters(doc.filters_json),
|
|
71
|
+
};
|
|
72
|
+
}, [doc]);
|
|
73
|
+
|
|
74
|
+
if (isLoading) {
|
|
75
|
+
return (
|
|
76
|
+
<Card flexGrow={1} aria-busy aria-label={t("loading", "Loading")}>
|
|
77
|
+
<YStack {...knobProps.panelPadding} {...knobProps.gap}>
|
|
78
|
+
<Skeleton width="60%" height={12} />
|
|
79
|
+
<Skeleton width="40%" height={28} />
|
|
80
|
+
</YStack>
|
|
81
|
+
</Card>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (error || !doc) {
|
|
86
|
+
return (
|
|
87
|
+
<Card flexGrow={1}>
|
|
88
|
+
<YStack {...knobProps.panelPadding} {...knobProps.gap}>
|
|
89
|
+
<SizableText size="$3" fontWeight="600">
|
|
90
|
+
{title}
|
|
91
|
+
</SizableText>
|
|
92
|
+
<SizableText size="$2" color="$color10">
|
|
93
|
+
{t("workspaceNumberCardError", "Couldn't load number card")}
|
|
94
|
+
</SizableText>
|
|
95
|
+
</YStack>
|
|
96
|
+
</Card>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!dataSource) {
|
|
101
|
+
// Report / Custom cards need server-side evaluation — not wired yet.
|
|
102
|
+
return (
|
|
103
|
+
<Card flexGrow={1}>
|
|
104
|
+
<YStack {...knobProps.panelPadding} {...knobProps.gap}>
|
|
105
|
+
<SizableText size="$3" fontWeight="600">
|
|
106
|
+
{title}
|
|
107
|
+
</SizableText>
|
|
108
|
+
<SizableText size="$2" color="$color10">
|
|
109
|
+
{t(
|
|
110
|
+
"workspaceNumberCardUnsupported",
|
|
111
|
+
"This card type is only available in desk",
|
|
112
|
+
)}
|
|
113
|
+
</SizableText>
|
|
114
|
+
</YStack>
|
|
115
|
+
</Card>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<FrappeKPICard
|
|
121
|
+
config={{ id: `workspace-number-card-${row.name}`, title, value: "—" }}
|
|
122
|
+
dataSource={dataSource}
|
|
123
|
+
flexGrow={1}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace quick list block — a compact live list of a doctype with the
|
|
3
|
+
* row's `quick_list_filter` applied, plus a "View All" jump to the full
|
|
4
|
+
* list page. Rows navigate to the document form. Rows show the document
|
|
5
|
+
* name — desk shows the meta title field, which needs a DocType meta
|
|
6
|
+
* fetch (documented simplification).
|
|
7
|
+
*/
|
|
8
|
+
import { Card, Separator, SizableText, XStack, YStack } from "@multiplatform.one/components";
|
|
9
|
+
import { FrappeList } from "@multiplatform.one/frappe-ui";
|
|
10
|
+
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
11
|
+
import { useMemo } from "react";
|
|
12
|
+
import { useTranslation } from "react-i18next";
|
|
13
|
+
import { useBackofficeNavigator, useBackofficePaths } from "../config/BackofficeProvider";
|
|
14
|
+
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
15
|
+
import { parseFrappeFilters } from "./parseContent";
|
|
16
|
+
import type { WorkspaceQuickListRow } from "./types";
|
|
17
|
+
|
|
18
|
+
interface QuickListDoc {
|
|
19
|
+
name: string;
|
|
20
|
+
doctype: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Generic JSX (`<FrappeList<QuickListDoc> …/>`) breaks one-dev's source
|
|
24
|
+
// annotation transform; instantiate the type argument outside JSX instead.
|
|
25
|
+
const QuickList = FrappeList<QuickListDoc>;
|
|
26
|
+
|
|
27
|
+
/** Fixed viewport for the compact list (~4 rows + load-more headroom). */
|
|
28
|
+
const QUICK_LIST_HEIGHT = 220;
|
|
29
|
+
|
|
30
|
+
export interface WorkspaceQuickListProps {
|
|
31
|
+
row: WorkspaceQuickListRow;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function WorkspaceQuickList({ row }: WorkspaceQuickListProps) {
|
|
35
|
+
const navigator = useBackofficeNavigator();
|
|
36
|
+
const paths = useBackofficePaths();
|
|
37
|
+
const { knobProps } = useResolvedKnobs();
|
|
38
|
+
const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
|
|
39
|
+
|
|
40
|
+
const filters = useMemo(() => parseFrappeFilters(row.quick_list_filter), [row.quick_list_filter]);
|
|
41
|
+
|
|
42
|
+
const title = row.label || row.document_type;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Card flexGrow={1}>
|
|
46
|
+
<YStack {...knobProps.panelPadding} {...knobProps.gap}>
|
|
47
|
+
<XStack justifyContent="space-between" alignItems="center" {...knobProps.gap}>
|
|
48
|
+
<SizableText size="$4" fontWeight="700" numberOfLines={1} flexShrink={1}>
|
|
49
|
+
{title}
|
|
50
|
+
</SizableText>
|
|
51
|
+
<SizableText
|
|
52
|
+
size="$2"
|
|
53
|
+
color="$color11"
|
|
54
|
+
cursor="pointer"
|
|
55
|
+
role="link"
|
|
56
|
+
hoverStyle={{ color: "$color12" }}
|
|
57
|
+
onPress={() => navigator.navigate(paths.list(row.document_type))}
|
|
58
|
+
>
|
|
59
|
+
{t("workspaceQuickListViewAll", "View All")}
|
|
60
|
+
</SizableText>
|
|
61
|
+
</XStack>
|
|
62
|
+
<Separator />
|
|
63
|
+
{/* Fixed-height box: FrappeList's internal flex-basis:0 stack
|
|
64
|
+
contributes no intrinsic height, so an unclamped Card collapses
|
|
65
|
+
and the rows paint past the frame (LC-10). The box gives the
|
|
66
|
+
flex chain a definite height to fill. */}
|
|
67
|
+
<YStack height={QUICK_LIST_HEIGHT} overflow="hidden">
|
|
68
|
+
<QuickList
|
|
69
|
+
doctype={row.document_type}
|
|
70
|
+
fields={["name"]}
|
|
71
|
+
filters={filters as Array<["name", string, unknown]> | undefined}
|
|
72
|
+
pageSize={4}
|
|
73
|
+
height={QUICK_LIST_HEIGHT}
|
|
74
|
+
estimateSize={44}
|
|
75
|
+
aria-label={title}
|
|
76
|
+
renderItem={(item) => (
|
|
77
|
+
<XStack
|
|
78
|
+
paddingVertical="$2"
|
|
79
|
+
paddingHorizontal="$2"
|
|
80
|
+
alignItems="center"
|
|
81
|
+
cursor="pointer"
|
|
82
|
+
borderRadius="$2"
|
|
83
|
+
hoverStyle={{ backgroundColor: "$color3" }}
|
|
84
|
+
onPress={() =>
|
|
85
|
+
item.name && navigator.navigate(paths.form(row.document_type, item.name))
|
|
86
|
+
}
|
|
87
|
+
role="link"
|
|
88
|
+
aria-label={item.name}
|
|
89
|
+
>
|
|
90
|
+
<SizableText size="$3" numberOfLines={1} flexShrink={1}>
|
|
91
|
+
{item.name}
|
|
92
|
+
</SizableText>
|
|
93
|
+
</XStack>
|
|
94
|
+
)}
|
|
95
|
+
/>
|
|
96
|
+
</YStack>
|
|
97
|
+
</YStack>
|
|
98
|
+
</Card>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Continue where you left off" strip (MOD-11) — a wrapping band of chips
|
|
3
|
+
* for the most recent backoffice visits, read from the shared desk recents
|
|
4
|
+
* store (chrome/awesomebar-data's readRecentItems over the same
|
|
5
|
+
* "frappe-desk-recent" key frappe-ui's addToRecent writes — one list across
|
|
6
|
+
* navbar recents, sidebar recents, and this strip; no new store).
|
|
7
|
+
*
|
|
8
|
+
* Renders nothing while the store is unread or empty — the strip is
|
|
9
|
+
* discovery chrome, not data the page promised (no skeleton, D-10).
|
|
10
|
+
* Refreshes on mount and on window focus (web); paths outside the
|
|
11
|
+
* provider's basePath (e.g. the frappe-ui `/desk` demo shell writes there
|
|
12
|
+
* too) are filtered out so every chip stays navigable in this app.
|
|
13
|
+
*/
|
|
14
|
+
import { ClockCounterClockwiseIcon } from "@phosphor-icons/react";
|
|
15
|
+
import { Card, PageSection, SizableText, XStack, useTheme } from "@multiplatform.one/components";
|
|
16
|
+
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
17
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
18
|
+
import { useTranslation } from "react-i18next";
|
|
19
|
+
import { readRecentItems, type RecentItem } from "../chrome/awesomebar-data";
|
|
20
|
+
import { useBackofficeNavigator, useBackofficePaths } from "../config/BackofficeProvider";
|
|
21
|
+
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
22
|
+
|
|
23
|
+
/** Last N visits shown (MOD-11: "last 5 items from the shared recents store"). */
|
|
24
|
+
const MAX_RECENTS = 5;
|
|
25
|
+
|
|
26
|
+
export function WorkspaceRecents() {
|
|
27
|
+
const navigator = useBackofficeNavigator();
|
|
28
|
+
const paths = useBackofficePaths();
|
|
29
|
+
const { knobProps } = useResolvedKnobs();
|
|
30
|
+
const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
|
|
31
|
+
const theme = useTheme();
|
|
32
|
+
// Phosphor icons take a resolved color string, not a tamagui token —
|
|
33
|
+
// read the theme value so native/GTK get a real color (not a CSS var).
|
|
34
|
+
const iconColor = typeof theme.color11?.val === "string" ? theme.color11.val : undefined;
|
|
35
|
+
const [recents, setRecents] = useState<RecentItem[]>([]);
|
|
36
|
+
|
|
37
|
+
const mountedRef = useRef(true);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
mountedRef.current = true;
|
|
40
|
+
return () => {
|
|
41
|
+
mountedRef.current = false;
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
const base = paths.base;
|
|
46
|
+
const refresh = useCallback(() => {
|
|
47
|
+
void readRecentItems().then((stored) => {
|
|
48
|
+
if (!mountedRef.current) return;
|
|
49
|
+
setRecents(stored.filter((item) => item.path.startsWith(base)).slice(0, MAX_RECENTS));
|
|
50
|
+
});
|
|
51
|
+
}, [base]);
|
|
52
|
+
|
|
53
|
+
// Fresh on mount and whenever the window regains focus (another surface
|
|
54
|
+
// may have pushed a visit since) — same staleness contract as the
|
|
55
|
+
// awesomebar's refresh-on-open.
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
refresh();
|
|
58
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const onFocus = () => refresh();
|
|
62
|
+
window.addEventListener("focus", onFocus);
|
|
63
|
+
return () => window.removeEventListener("focus", onFocus);
|
|
64
|
+
}, [refresh]);
|
|
65
|
+
|
|
66
|
+
if (recents.length === 0) return null;
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
// Section heading on the shared sectionHeading scale (LC-17); no
|
|
70
|
+
// divider rule over a chip band (Axiom 16 chrome-earns-role).
|
|
71
|
+
<PageSection
|
|
72
|
+
title={t("workspaceRecents", "Continue where you left off")}
|
|
73
|
+
divider={false}
|
|
74
|
+
>
|
|
75
|
+
<XStack flexWrap="wrap" {...knobProps.gap}>
|
|
76
|
+
{recents.map((item) => (
|
|
77
|
+
<Card
|
|
78
|
+
key={item.path}
|
|
79
|
+
// Chip-scale surface: eject the Card's default panelPadding —
|
|
80
|
+
// the inner row owns the compact inset (LC-18 eject-last).
|
|
81
|
+
padding={0}
|
|
82
|
+
onPress={() => navigator.navigate(item.path)}
|
|
83
|
+
cursor="pointer"
|
|
84
|
+
hoverStyle={{ borderColor: "$accentBackground" }}
|
|
85
|
+
pressStyle={{ scale: 0.98 }}
|
|
86
|
+
role="link"
|
|
87
|
+
aria-label={item.label}
|
|
88
|
+
>
|
|
89
|
+
<XStack paddingHorizontal="$3" minHeight={44} alignItems="center" {...knobProps.gap}>
|
|
90
|
+
<ClockCounterClockwiseIcon size={14} color={iconColor} aria-hidden />
|
|
91
|
+
<SizableText size="$3" numberOfLines={1} flexShrink={1}>
|
|
92
|
+
{item.label}
|
|
93
|
+
</SizableText>
|
|
94
|
+
</XStack>
|
|
95
|
+
</Card>
|
|
96
|
+
))}
|
|
97
|
+
</XStack>
|
|
98
|
+
</PageSection>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
// Contract: renders a frappe Workspace document (shortcuts, link cards,
|
|
2
|
+
// charts, number cards, quick lists) by workspace name.
|
|
3
|
+
/**
|
|
4
|
+
* Dashboard-first workspace page (MOD-11). The Workspace doc's `content`
|
|
5
|
+
* JSON declares the blocks; the composition is ours, not desk's authoring
|
|
6
|
+
* order (owner mandate: desk is a capability reference, not a design
|
|
7
|
+
* constraint): recents strip, then live data widgets (number cards →
|
|
8
|
+
* charts → quick lists), then narrative text, then a compact shortcut chip
|
|
9
|
+
* band, then the grouped link cards behind a searchable "Browse all"
|
|
10
|
+
* disclosure. Each widget resolves its definition from the doc's child
|
|
11
|
+
* tables (`shortcuts`, `links`, `charts`, `number_cards`, `quick_lists`)
|
|
12
|
+
* — shapes verified against a real bench (see types.ts).
|
|
13
|
+
*
|
|
14
|
+
* Skipped block types (rendered as nothing, by design): `onboarding`
|
|
15
|
+
* (module onboarding widget needs its own RPC surface), `custom_block`
|
|
16
|
+
* (arbitrary HTML — unsafe cross-platform), and `spacer` (the section
|
|
17
|
+
* composition owns vertical rhythm now).
|
|
18
|
+
*/
|
|
19
|
+
import {
|
|
20
|
+
AsyncBoundary,
|
|
21
|
+
H2,
|
|
22
|
+
H3,
|
|
23
|
+
H4,
|
|
24
|
+
H5,
|
|
25
|
+
H6,
|
|
26
|
+
PageHeader,
|
|
27
|
+
PageSection,
|
|
28
|
+
Paragraph,
|
|
29
|
+
Screen,
|
|
30
|
+
Skeleton,
|
|
31
|
+
XStack,
|
|
32
|
+
YStack,
|
|
33
|
+
} from "@multiplatform.one/components";
|
|
34
|
+
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
35
|
+
import { useMemo, type ReactNode } from "react";
|
|
36
|
+
import { useTranslation } from "react-i18next";
|
|
37
|
+
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
38
|
+
import {
|
|
39
|
+
composeWorkspaceBlocks,
|
|
40
|
+
findLinkGroup,
|
|
41
|
+
findShortcut,
|
|
42
|
+
groupLinks,
|
|
43
|
+
headerLevel,
|
|
44
|
+
parseWorkspaceContent,
|
|
45
|
+
stripHtml,
|
|
46
|
+
} from "./parseContent";
|
|
47
|
+
import type { WorkspaceBlock, WorkspaceDoc, WorkspaceShortcutRow } from "./types";
|
|
48
|
+
import { useWorkspaceDoc } from "./useWorkspaceDoc";
|
|
49
|
+
import { WorkspaceChartBlock } from "./WorkspaceChartBlock";
|
|
50
|
+
import { WorkspaceGrid, type WorkspaceGridItem } from "./WorkspaceGrid";
|
|
51
|
+
import { WorkspaceLinkDirectory, type WorkspaceLinkDirectoryItem } from "./WorkspaceLinkDirectory";
|
|
52
|
+
import { WorkspaceNumberCard } from "./WorkspaceNumberCard";
|
|
53
|
+
import { WorkspaceQuickList } from "./WorkspaceQuickList";
|
|
54
|
+
import { WorkspaceRecents } from "./WorkspaceRecents";
|
|
55
|
+
import { WorkspaceShortcut } from "./WorkspaceShortcut";
|
|
56
|
+
|
|
57
|
+
/** Block classes a host can hide from the workspace composition. */
|
|
58
|
+
export type WorkspaceBlockKind =
|
|
59
|
+
| "shortcuts"
|
|
60
|
+
| "links"
|
|
61
|
+
| "charts"
|
|
62
|
+
| "numbers"
|
|
63
|
+
| "quickLists"
|
|
64
|
+
| "recents";
|
|
65
|
+
|
|
66
|
+
export interface WorkspaceScreenProps {
|
|
67
|
+
/** Workspace document name (proper case, e.g. "Home", "Users") */
|
|
68
|
+
workspace: string;
|
|
69
|
+
/** Hide whole block classes from the composition. */
|
|
70
|
+
hiddenBlocks?: readonly WorkspaceBlockKind[];
|
|
71
|
+
/** Override the default shortcut-chip navigation. */
|
|
72
|
+
onShortcutPress?: (row: WorkspaceShortcutRow) => void;
|
|
73
|
+
/**
|
|
74
|
+
* Replace the rendering of individual grid blocks (data widgets and
|
|
75
|
+
* narrative text). Shortcut chips and link cards have their own
|
|
76
|
+
* composition and are controlled via `hiddenBlocks`/`onShortcutPress`.
|
|
77
|
+
*/
|
|
78
|
+
renderBlock?: (context: {
|
|
79
|
+
block: WorkspaceBlock;
|
|
80
|
+
doc: WorkspaceDoc;
|
|
81
|
+
defaultContent: ReactNode;
|
|
82
|
+
}) => ReactNode;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Section headers step under the page H1; visual scale follows desk's
|
|
86
|
+
// small workspace section headings.
|
|
87
|
+
const HEADER_TAGS = { 1: H2, 2: H2, 3: H3, 4: H4, 5: H5, 6: H6 } as const;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Map a text or data block to a grid item. Shortcut and card blocks never
|
|
91
|
+
* reach this — the composition renders them as the chip band and the
|
|
92
|
+
* "Browse all" directory instead.
|
|
93
|
+
*/
|
|
94
|
+
function blockToGridItem(block: WorkspaceBlock, doc: WorkspaceDoc): WorkspaceGridItem | undefined {
|
|
95
|
+
const key = block.id || JSON.stringify(block.data);
|
|
96
|
+
switch (block.type) {
|
|
97
|
+
case "header": {
|
|
98
|
+
const text = stripHtml(block.data.text);
|
|
99
|
+
if (!text) return undefined;
|
|
100
|
+
const Tag = HEADER_TAGS[headerLevel(block.data.text)];
|
|
101
|
+
return {
|
|
102
|
+
key,
|
|
103
|
+
col: 12,
|
|
104
|
+
node: (
|
|
105
|
+
<Tag margin={0} marginTop="$3">
|
|
106
|
+
{text}
|
|
107
|
+
</Tag>
|
|
108
|
+
),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
case "paragraph": {
|
|
112
|
+
const text = stripHtml(block.data.text);
|
|
113
|
+
if (!text) return undefined;
|
|
114
|
+
return {
|
|
115
|
+
key,
|
|
116
|
+
col: 12,
|
|
117
|
+
node: <Paragraph margin={0}>{text}</Paragraph>,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
case "chart": {
|
|
121
|
+
const row = doc.charts?.find(
|
|
122
|
+
(chart) =>
|
|
123
|
+
chart.chart_name === block.data.chart_name || chart.label === block.data.chart_name,
|
|
124
|
+
);
|
|
125
|
+
if (!row) return undefined;
|
|
126
|
+
return { key, col: block.data.col ?? 12, node: <WorkspaceChartBlock row={row} /> };
|
|
127
|
+
}
|
|
128
|
+
case "number_card": {
|
|
129
|
+
const row = doc.number_cards?.find(
|
|
130
|
+
(card) =>
|
|
131
|
+
card.number_card_name === block.data.number_card_name ||
|
|
132
|
+
card.label === block.data.number_card_name,
|
|
133
|
+
);
|
|
134
|
+
if (!row) return undefined;
|
|
135
|
+
return { key, col: block.data.col ?? 3, node: <WorkspaceNumberCard row={row} /> };
|
|
136
|
+
}
|
|
137
|
+
case "quick_list": {
|
|
138
|
+
const row = doc.quick_lists?.find(
|
|
139
|
+
(list) =>
|
|
140
|
+
list.document_type === block.data.quick_list_name ||
|
|
141
|
+
list.label === block.data.quick_list_name,
|
|
142
|
+
);
|
|
143
|
+
if (!row) return undefined;
|
|
144
|
+
return { key, col: block.data.col ?? 4, node: <WorkspaceQuickList row={row} /> };
|
|
145
|
+
}
|
|
146
|
+
default:
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function WorkspaceSkeleton() {
|
|
152
|
+
const { knobProps } = useResolvedKnobs();
|
|
153
|
+
const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
|
|
154
|
+
// Mirrors the dashboard-first anatomy (LC-20): title line, shortcut chip
|
|
155
|
+
// band (44px chips, deterministic widths), then the content card region.
|
|
156
|
+
return (
|
|
157
|
+
<YStack {...knobProps.gapLg} aria-busy aria-label={t("loading", "Loading")}>
|
|
158
|
+
<Skeleton width="30%" height={32} />
|
|
159
|
+
<XStack {...knobProps.gap}>
|
|
160
|
+
<Skeleton variant="rounded" width={128} height={44} />
|
|
161
|
+
<Skeleton variant="rounded" width={104} height={44} />
|
|
162
|
+
<Skeleton variant="rounded" width={144} height={44} />
|
|
163
|
+
<Skeleton variant="rounded" width={112} height={44} />
|
|
164
|
+
</XStack>
|
|
165
|
+
<XStack {...knobProps.gap}>
|
|
166
|
+
<Skeleton variant="rounded" width="32%" height={200} />
|
|
167
|
+
<Skeleton variant="rounded" width="32%" height={200} />
|
|
168
|
+
<Skeleton variant="rounded" width="32%" height={200} />
|
|
169
|
+
</XStack>
|
|
170
|
+
</YStack>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
interface WorkspaceSections {
|
|
175
|
+
/** Data widgets first: number cards → charts → quick lists. */
|
|
176
|
+
data: WorkspaceGridItem[];
|
|
177
|
+
/** Narrative headers/paragraphs (e.g. the text-only Welcome Workspace). */
|
|
178
|
+
text: WorkspaceGridItem[];
|
|
179
|
+
/** Resolved shortcut rows for the chip band. */
|
|
180
|
+
shortcuts: WorkspaceShortcutRow[];
|
|
181
|
+
/** Resolved link groups (with authored spans) for the directory. */
|
|
182
|
+
links: WorkspaceLinkDirectoryItem[];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const DATA_KIND_BY_TYPE: Record<string, WorkspaceBlockKind> = {
|
|
186
|
+
chart: "charts",
|
|
187
|
+
number_card: "numbers",
|
|
188
|
+
quick_list: "quickLists",
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
function buildSections(
|
|
192
|
+
doc: WorkspaceDoc,
|
|
193
|
+
hidden: ReadonlySet<WorkspaceBlockKind>,
|
|
194
|
+
renderBlock?: WorkspaceScreenProps["renderBlock"],
|
|
195
|
+
): WorkspaceSections {
|
|
196
|
+
const composition = composeWorkspaceBlocks(parseWorkspaceContent(doc.content));
|
|
197
|
+
const toGridItems = (blocks: WorkspaceBlock[]) =>
|
|
198
|
+
blocks
|
|
199
|
+
.map((block) => {
|
|
200
|
+
const item = blockToGridItem(block, doc);
|
|
201
|
+
if (!item || !renderBlock) return item;
|
|
202
|
+
return { ...item, node: renderBlock({ block, doc, defaultContent: item.node }) };
|
|
203
|
+
})
|
|
204
|
+
.filter((item): item is WorkspaceGridItem => item !== undefined);
|
|
205
|
+
const groups = groupLinks(doc.links);
|
|
206
|
+
const dataBlocks = composition.data.filter((block) => {
|
|
207
|
+
const kind = DATA_KIND_BY_TYPE[block.type];
|
|
208
|
+
return !kind || !hidden.has(kind);
|
|
209
|
+
});
|
|
210
|
+
return {
|
|
211
|
+
data: toGridItems(dataBlocks),
|
|
212
|
+
text: toGridItems(composition.text),
|
|
213
|
+
shortcuts: hidden.has("shortcuts")
|
|
214
|
+
? []
|
|
215
|
+
: composition.shortcuts.flatMap((block) => {
|
|
216
|
+
const row = findShortcut(doc, block.data.shortcut_name);
|
|
217
|
+
return row ? [row] : [];
|
|
218
|
+
}),
|
|
219
|
+
links: hidden.has("links")
|
|
220
|
+
? []
|
|
221
|
+
: composition.cards.flatMap((block) => {
|
|
222
|
+
const group = findLinkGroup(groups, block.data.card_name);
|
|
223
|
+
if (!group) return [];
|
|
224
|
+
return [{ key: block.id || group.label, col: block.data.col ?? 4, group }];
|
|
225
|
+
}),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function WorkspaceScreen({
|
|
230
|
+
workspace,
|
|
231
|
+
hiddenBlocks,
|
|
232
|
+
onShortcutPress,
|
|
233
|
+
renderBlock,
|
|
234
|
+
}: WorkspaceScreenProps) {
|
|
235
|
+
const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
|
|
236
|
+
const { knobProps } = useResolvedKnobs();
|
|
237
|
+
const { doc, isLoading, error, isPermissionError, refresh } = useWorkspaceDoc(workspace);
|
|
238
|
+
|
|
239
|
+
const hidden = useMemo(() => new Set(hiddenBlocks ?? []), [hiddenBlocks]);
|
|
240
|
+
const sections = useMemo(
|
|
241
|
+
() => (doc ? buildSections(doc, hidden, renderBlock) : undefined),
|
|
242
|
+
[doc, hidden, renderBlock],
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
if (isLoading) {
|
|
246
|
+
return (
|
|
247
|
+
<Screen>
|
|
248
|
+
<WorkspaceSkeleton />
|
|
249
|
+
</Screen>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (error || !doc || !sections) {
|
|
254
|
+
return (
|
|
255
|
+
<Screen>
|
|
256
|
+
<AsyncBoundary
|
|
257
|
+
error={error ?? true}
|
|
258
|
+
onRetry={refresh}
|
|
259
|
+
errorTitle={
|
|
260
|
+
isPermissionError
|
|
261
|
+
? t(
|
|
262
|
+
"workspacePermissionError",
|
|
263
|
+
"You do not have permission to view {{workspace}}",
|
|
264
|
+
{ workspace },
|
|
265
|
+
)
|
|
266
|
+
: t("workspaceError", "Couldn't load workspace {{workspace}}", {
|
|
267
|
+
workspace,
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
/>
|
|
271
|
+
</Screen>
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const isEmpty =
|
|
276
|
+
sections.data.length === 0 &&
|
|
277
|
+
sections.text.length === 0 &&
|
|
278
|
+
sections.shortcuts.length === 0 &&
|
|
279
|
+
sections.links.length === 0;
|
|
280
|
+
|
|
281
|
+
return (
|
|
282
|
+
<Screen>
|
|
283
|
+
{/* D-11 page-title dial: moderate (32px) — a workspace title is
|
|
284
|
+
wayfinding, not display copy. No divider: the rule under the title
|
|
285
|
+
earned no role (Axiom 16 chrome-earns-role). */}
|
|
286
|
+
<PageHeader
|
|
287
|
+
title={doc.title || doc.label || workspace}
|
|
288
|
+
titleScale="moderate"
|
|
289
|
+
divider={false}
|
|
290
|
+
/>
|
|
291
|
+
{hidden.has("recents") ? null : <WorkspaceRecents />}
|
|
292
|
+
{isEmpty ? (
|
|
293
|
+
<AsyncBoundary
|
|
294
|
+
empty
|
|
295
|
+
emptyTitle={t("workspaceEmpty", "This workspace is empty")}
|
|
296
|
+
emptyDescription={t(
|
|
297
|
+
"workspaceEmptyDescription",
|
|
298
|
+
"No blocks have been added to {{workspace}} yet",
|
|
299
|
+
{ workspace },
|
|
300
|
+
)}
|
|
301
|
+
/>
|
|
302
|
+
) : (
|
|
303
|
+
<>
|
|
304
|
+
{sections.data.length > 0 ? <WorkspaceGrid items={sections.data} /> : null}
|
|
305
|
+
{sections.text.length > 0 ? <WorkspaceGrid items={sections.text} /> : null}
|
|
306
|
+
{sections.shortcuts.length > 0 ? (
|
|
307
|
+
// Section heading on the shared sectionHeading scale (LC-17) —
|
|
308
|
+
// PageSection owns it; no divider rule over a chip band.
|
|
309
|
+
<PageSection title={t("workspaceShortcuts", "Shortcuts")} divider={false}>
|
|
310
|
+
<XStack flexWrap="wrap" {...knobProps.gap}>
|
|
311
|
+
{sections.shortcuts.map((row) => (
|
|
312
|
+
<WorkspaceShortcut key={row.name} row={row} onPress={onShortcutPress} />
|
|
313
|
+
))}
|
|
314
|
+
</XStack>
|
|
315
|
+
</PageSection>
|
|
316
|
+
) : null}
|
|
317
|
+
{sections.links.length > 0 ? <WorkspaceLinkDirectory items={sections.links} /> : null}
|
|
318
|
+
</>
|
|
319
|
+
)}
|
|
320
|
+
</Screen>
|
|
321
|
+
);
|
|
322
|
+
}
|