@multiplatform.one/backoffice 6.4.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/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/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/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/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/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,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
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace shortcut chip — compact chip rendering for the `shortcut`
|
|
3
|
+
* content block (MOD-11): type icon + label + live count pill in a ~44px
|
|
4
|
+
* self-sized chip, laid out as a wrapping band by WorkspaceScreen (not
|
|
5
|
+
* grid-stretched cards).
|
|
6
|
+
*
|
|
7
|
+
* DocType shortcuts show a live count (respecting `stats_filter`) via the
|
|
8
|
+
* shared realtime aggregate and navigate to the doctype list. Report and
|
|
9
|
+
* Page shortcuts navigate into the backoffice slug router (best-effort —
|
|
10
|
+
* see the navigation notes on `resolveShortcutTarget`). URL shortcuts open
|
|
11
|
+
* via the platform-split openUrl (web new tab / native Linking / GNOME Gio).
|
|
12
|
+
*
|
|
13
|
+
* Rendering gates: chips targeting doctypes outside the provider's
|
|
14
|
+
* `doctypes` scope render nothing, and DocType/Report chips (list-surface
|
|
15
|
+
* navigations) render nothing when the `views` capability is off.
|
|
16
|
+
*/
|
|
17
|
+
import {
|
|
18
|
+
ArrowSquareOutIcon,
|
|
19
|
+
BrowserIcon,
|
|
20
|
+
ChartBarIcon,
|
|
21
|
+
GaugeIcon,
|
|
22
|
+
ListBulletsIcon,
|
|
23
|
+
SquaresFourIcon,
|
|
24
|
+
type Icon,
|
|
25
|
+
} from "@phosphor-icons/react";
|
|
26
|
+
import {
|
|
27
|
+
Card,
|
|
28
|
+
SizableText,
|
|
29
|
+
Skeleton,
|
|
30
|
+
XStack,
|
|
31
|
+
YStack,
|
|
32
|
+
useTheme,
|
|
33
|
+
} from "@multiplatform.one/components";
|
|
34
|
+
import { useFrappeAggregate, useFrappeConfig } from "@multiplatform.one/frappe-ui";
|
|
35
|
+
import { openUrl } from "@multiplatform.one/platform";
|
|
36
|
+
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
37
|
+
import { useMemo } from "react";
|
|
38
|
+
import { useTranslation } from "react-i18next";
|
|
39
|
+
import {
|
|
40
|
+
useBackofficeCapabilities,
|
|
41
|
+
useBackofficeNavigator,
|
|
42
|
+
useBackofficePaths,
|
|
43
|
+
useIsDoctypeAllowed,
|
|
44
|
+
} from "../config/BackofficeProvider";
|
|
45
|
+
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
46
|
+
import { createBackofficePaths, type BackofficePaths } from "../navigation/paths";
|
|
47
|
+
import { parseFrappeFilters } from "./parseContent";
|
|
48
|
+
import type { WorkspaceShortcutRow } from "./types";
|
|
49
|
+
|
|
50
|
+
const defaultPaths = createBackofficePaths();
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Resolve a shortcut press to a router path (or an external URL) —
|
|
54
|
+
* basePath-aware when the provider's `paths` are passed; defaults to the
|
|
55
|
+
* canonical "/backoffice".
|
|
56
|
+
*
|
|
57
|
+
* - DocType → paths.list(link_to)
|
|
58
|
+
* - Report → paths.list(link_to): there is no query-report route yet, so the
|
|
59
|
+
* report slug goes through the runtime slug resolver (documented gap).
|
|
60
|
+
* - Page → `{base}/<link_to>` (frappe page names are already slugs,
|
|
61
|
+
* e.g. "permission-manager"); resolution is up to the slug router.
|
|
62
|
+
* - Dashboard → no dashboard-view route yet → disabled (documented gap).
|
|
63
|
+
* - URL → external, opened through the platform openUrl.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveShortcutTarget(
|
|
66
|
+
row: WorkspaceShortcutRow,
|
|
67
|
+
paths: BackofficePaths = defaultPaths,
|
|
68
|
+
): {
|
|
69
|
+
path?: string;
|
|
70
|
+
externalUrl?: string;
|
|
71
|
+
disabled?: boolean;
|
|
72
|
+
} {
|
|
73
|
+
const target = row.link_to || row.url || "";
|
|
74
|
+
const prefix = paths.base === "/" ? "" : paths.base;
|
|
75
|
+
switch (row.type) {
|
|
76
|
+
case "DocType":
|
|
77
|
+
return { path: paths.list(target) };
|
|
78
|
+
case "Report":
|
|
79
|
+
return { path: paths.list(target) };
|
|
80
|
+
case "Page":
|
|
81
|
+
return { path: `${prefix}/${target}` };
|
|
82
|
+
case "URL":
|
|
83
|
+
return { externalUrl: row.url || row.link_to };
|
|
84
|
+
default:
|
|
85
|
+
// "Dashboard" and unknown types have no backoffice route yet.
|
|
86
|
+
return { disabled: true };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface WorkspaceShortcutProps {
|
|
91
|
+
row: WorkspaceShortcutRow;
|
|
92
|
+
/** Override the default navigation/open behavior for this chip. */
|
|
93
|
+
onPress?: (row: WorkspaceShortcutRow) => void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Leading chip glyph per shortcut target type. */
|
|
97
|
+
const TYPE_ICONS: Record<string, Icon> = {
|
|
98
|
+
DocType: ListBulletsIcon,
|
|
99
|
+
Report: ChartBarIcon,
|
|
100
|
+
Page: BrowserIcon,
|
|
101
|
+
Dashboard: GaugeIcon,
|
|
102
|
+
URL: ArrowSquareOutIcon,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export function WorkspaceShortcut({ row, onPress }: WorkspaceShortcutProps) {
|
|
106
|
+
const navigator = useBackofficeNavigator();
|
|
107
|
+
const paths = useBackofficePaths();
|
|
108
|
+
const config = useFrappeConfig();
|
|
109
|
+
const { knobProps } = useResolvedKnobs();
|
|
110
|
+
const { t } = useTranslation(BACKOFFICE_I18N_NAMESPACE);
|
|
111
|
+
const theme = useTheme();
|
|
112
|
+
const { views } = useBackofficeCapabilities();
|
|
113
|
+
const isDoctypeAllowed = useIsDoctypeAllowed();
|
|
114
|
+
// Phosphor icons take a resolved color string, not a tamagui token —
|
|
115
|
+
// read the theme value so native/GTK get a real color (not a CSS var).
|
|
116
|
+
const iconColor = typeof theme.color11?.val === "string" ? theme.color11.val : undefined;
|
|
117
|
+
|
|
118
|
+
const isDoctype = row.type === "DocType" && !!row.link_to;
|
|
119
|
+
const filters = useMemo(() => parseFrappeFilters(row.stats_filter), [row.stats_filter]);
|
|
120
|
+
|
|
121
|
+
const connection = useMemo(
|
|
122
|
+
() =>
|
|
123
|
+
config?.baseURL || config?.fixtures
|
|
124
|
+
? {
|
|
125
|
+
baseURL: config.baseURL,
|
|
126
|
+
socketPort: config.socketPort,
|
|
127
|
+
auth: config.auth,
|
|
128
|
+
syncOptions: config.syncOptions,
|
|
129
|
+
fixtures: config.fixtures,
|
|
130
|
+
}
|
|
131
|
+
: undefined,
|
|
132
|
+
[config],
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Visibility gates (before any early return — hooks above stay stable).
|
|
136
|
+
const hiddenByScope = isDoctype && row.link_to ? !isDoctypeAllowed(row.link_to) : false;
|
|
137
|
+
const hiddenByViews = (row.type === "DocType" || row.type === "Report") && !views.enabled;
|
|
138
|
+
|
|
139
|
+
const {
|
|
140
|
+
value: count,
|
|
141
|
+
isLoading: countLoading,
|
|
142
|
+
error: countError,
|
|
143
|
+
} = useFrappeAggregate(connection, {
|
|
144
|
+
doctype: row.link_to ?? "",
|
|
145
|
+
filters,
|
|
146
|
+
enabled: isDoctype && !!connection && !hiddenByScope && !hiddenByViews,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (hiddenByScope || hiddenByViews) return null;
|
|
150
|
+
|
|
151
|
+
const target = resolveShortcutTarget(row, paths);
|
|
152
|
+
|
|
153
|
+
const handlePress = () => {
|
|
154
|
+
if (onPress) {
|
|
155
|
+
onPress(row);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (target.path) {
|
|
159
|
+
navigator.navigate(target.path);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (target.externalUrl) {
|
|
163
|
+
// Platform-split: new tab on web, Linking on native, Gio on GNOME.
|
|
164
|
+
openUrl(target.externalUrl);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Desk shows "{} Open"-style templates when `format` is set.
|
|
169
|
+
const countLabel =
|
|
170
|
+
count === undefined
|
|
171
|
+
? undefined
|
|
172
|
+
: row.format
|
|
173
|
+
? row.format.replace("{}", String(count))
|
|
174
|
+
: String(count);
|
|
175
|
+
|
|
176
|
+
const TypeIcon = TYPE_ICONS[row.type] ?? SquaresFourIcon;
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<Card
|
|
180
|
+
// Chip-scale surface: eject the Card's default panelPadding — the
|
|
181
|
+
// inner row owns the compact inset (LC-18 eject-last contract).
|
|
182
|
+
padding={0}
|
|
183
|
+
onPress={target.disabled && !onPress ? undefined : handlePress}
|
|
184
|
+
disabled={target.disabled && !onPress}
|
|
185
|
+
opacity={target.disabled && !onPress ? 0.5 : 1}
|
|
186
|
+
cursor={target.disabled && !onPress ? "default" : "pointer"}
|
|
187
|
+
hoverStyle={target.disabled && !onPress ? undefined : { borderColor: "$accentBackground" }}
|
|
188
|
+
pressStyle={target.disabled && !onPress ? undefined : { scale: 0.98 }}
|
|
189
|
+
role="button"
|
|
190
|
+
aria-label={row.label}
|
|
191
|
+
>
|
|
192
|
+
{/* Compact chip anatomy: icon + label + count, ≥44px press target
|
|
193
|
+
(DG-LAY-04), self-sized so the band wraps instead of stretching. */}
|
|
194
|
+
<XStack paddingHorizontal="$3" minHeight={44} alignItems="center" {...knobProps.gap}>
|
|
195
|
+
<TypeIcon size={16} color={iconColor} aria-hidden />
|
|
196
|
+
<SizableText size="$3" fontWeight="600" numberOfLines={1} flexShrink={1}>
|
|
197
|
+
{row.label}
|
|
198
|
+
</SizableText>
|
|
199
|
+
{isDoctype ? (
|
|
200
|
+
countLoading ? (
|
|
201
|
+
// Pill-shaped like the real count pill (LC-20 radius class).
|
|
202
|
+
<Skeleton width={28} height={16} borderRadius={1000} />
|
|
203
|
+
) : countError ? null : countLabel !== undefined ? (
|
|
204
|
+
<YStack
|
|
205
|
+
backgroundColor="$color4"
|
|
206
|
+
borderRadius={1000}
|
|
207
|
+
paddingHorizontal="$2.5"
|
|
208
|
+
paddingVertical="$1"
|
|
209
|
+
>
|
|
210
|
+
<SizableText size="$1" color="$color11" fontWeight="600">
|
|
211
|
+
{countLabel}
|
|
212
|
+
</SizableText>
|
|
213
|
+
</YStack>
|
|
214
|
+
) : null
|
|
215
|
+
) : target.disabled && !onPress ? (
|
|
216
|
+
<SizableText size="$1" color="$color10">
|
|
217
|
+
{t("workspaceShortcutUnavailable", "Not available")}
|
|
218
|
+
</SizableText>
|
|
219
|
+
) : null}
|
|
220
|
+
</XStack>
|
|
221
|
+
</Card>
|
|
222
|
+
);
|
|
223
|
+
}
|