@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,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
|
+
}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parseContent — workspace content-block JSON parsing, HTML stripping,
|
|
3
|
+
* link grouping, and frappe filter-string normalization. Filter fixtures
|
|
4
|
+
* are the bench-verified shapes documented in the module header and
|
|
5
|
+
* p-results/backoffice/integration-notes.md (dicts for stats_filter /
|
|
6
|
+
* quick_list_filter, doctype-prefixed quads for Number Card filters_json).
|
|
7
|
+
*/
|
|
8
|
+
import { describe, expect, it } from "vitest";
|
|
9
|
+
import {
|
|
10
|
+
composeWorkspaceBlocks,
|
|
11
|
+
findLinkGroup,
|
|
12
|
+
findShortcut,
|
|
13
|
+
groupLinks,
|
|
14
|
+
headerLevel,
|
|
15
|
+
parseFrappeFilters,
|
|
16
|
+
parseWorkspaceContent,
|
|
17
|
+
stripHtml,
|
|
18
|
+
} from "./parseContent";
|
|
19
|
+
import type { WorkspaceBlock, WorkspaceDoc, WorkspaceLinkRow } from "./types";
|
|
20
|
+
|
|
21
|
+
describe("parseWorkspaceContent", () => {
|
|
22
|
+
it("parses a desk-shaped block array", () => {
|
|
23
|
+
const content = JSON.stringify([
|
|
24
|
+
{
|
|
25
|
+
id: "abc123",
|
|
26
|
+
type: "header",
|
|
27
|
+
data: { text: '<span class="h4"><b>Your Shortcuts</b></span>', col: 12 },
|
|
28
|
+
},
|
|
29
|
+
{ id: "def456", type: "shortcut", data: { shortcut_name: "User", col: 3 } },
|
|
30
|
+
{ id: "ghi789", type: "card", data: { card_name: "Masters", col: 4 } },
|
|
31
|
+
]);
|
|
32
|
+
const blocks = parseWorkspaceContent(content);
|
|
33
|
+
expect(blocks).toHaveLength(3);
|
|
34
|
+
expect(blocks[0].type).toBe("header");
|
|
35
|
+
expect(blocks[1].data.shortcut_name).toBe("User");
|
|
36
|
+
expect(blocks[2].data.card_name).toBe("Masters");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("drops entries that are not blocks (null, scalars, missing type)", () => {
|
|
40
|
+
const content = JSON.stringify([
|
|
41
|
+
null,
|
|
42
|
+
"string",
|
|
43
|
+
42,
|
|
44
|
+
{ id: "x", data: {} },
|
|
45
|
+
{ id: "y", type: 5, data: {} },
|
|
46
|
+
{ id: "z", type: "spacer", data: {} },
|
|
47
|
+
]);
|
|
48
|
+
const blocks = parseWorkspaceContent(content);
|
|
49
|
+
expect(blocks).toHaveLength(1);
|
|
50
|
+
expect(blocks[0].id).toBe("z");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("returns [] for empty, malformed, or non-array content", () => {
|
|
54
|
+
expect(parseWorkspaceContent(undefined)).toEqual([]);
|
|
55
|
+
expect(parseWorkspaceContent(null)).toEqual([]);
|
|
56
|
+
expect(parseWorkspaceContent("")).toEqual([]);
|
|
57
|
+
expect(parseWorkspaceContent("{not json")).toEqual([]);
|
|
58
|
+
expect(parseWorkspaceContent('{"type":"header"}')).toEqual([]);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("stripHtml", () => {
|
|
63
|
+
it("strips desk rich-text wrappers (documented example)", () => {
|
|
64
|
+
expect(stripHtml('<span class="h4"><b>Reports & Masters</b></span>')).toBe(
|
|
65
|
+
"Reports & Masters",
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("decodes named entities", () => {
|
|
70
|
+
expect(stripHtml("<tag>")).toBe("<tag>");
|
|
71
|
+
expect(stripHtml(""quoted" 's'")).toBe("\"quoted\" 's'");
|
|
72
|
+
expect(stripHtml("a b")).toBe("a b");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("decodes decimal and hex numeric entities", () => {
|
|
76
|
+
expect(stripHtml("AB")).toBe("AB");
|
|
77
|
+
expect(stripHtml("AB")).toBe("AB");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("leaves unknown entities untouched", () => {
|
|
81
|
+
expect(stripHtml("&unknown;")).toBe("&unknown;");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("converts <br> variants to newlines", () => {
|
|
85
|
+
expect(stripHtml("a<br>b")).toBe("a\nb");
|
|
86
|
+
expect(stripHtml("a<br/>b")).toBe("a\nb");
|
|
87
|
+
expect(stripHtml("a<br />b")).toBe("a\nb");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("trims and handles empty input", () => {
|
|
91
|
+
expect(stripHtml(" <b> x </b> ")).toBe("x");
|
|
92
|
+
expect(stripHtml("")).toBe("");
|
|
93
|
+
expect(stripHtml(null)).toBe("");
|
|
94
|
+
expect(stripHtml(undefined)).toBe("");
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("headerLevel", () => {
|
|
99
|
+
it("reads the hN class from the wrapper", () => {
|
|
100
|
+
expect(headerLevel('<span class="h1">t</span>')).toBe(1);
|
|
101
|
+
expect(headerLevel('<span class="h2">t</span>')).toBe(2);
|
|
102
|
+
expect(headerLevel('<span class="h6">t</span>')).toBe(6);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("finds hN among multiple classes (word boundary)", () => {
|
|
106
|
+
expect(headerLevel('<span class="ce-header h3 muted">t</span>')).toBe(3);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("falls back to 4 for unclassed, styled, or missing input", () => {
|
|
110
|
+
expect(headerLevel("<b>plain</b>")).toBe(4);
|
|
111
|
+
expect(headerLevel('<span style="font-size: 18px">t</span>')).toBe(4);
|
|
112
|
+
expect(headerLevel('<span class="h7">t</span>')).toBe(4);
|
|
113
|
+
expect(headerLevel(null)).toBe(4);
|
|
114
|
+
expect(headerLevel(undefined)).toBe(4);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe("groupLinks", () => {
|
|
119
|
+
const row = (partial: Partial<WorkspaceLinkRow> & { type: string; label: string }) =>
|
|
120
|
+
({ name: partial.label, ...partial }) as WorkspaceLinkRow;
|
|
121
|
+
|
|
122
|
+
it("groups Link rows under the preceding Card Break", () => {
|
|
123
|
+
const groups = groupLinks([
|
|
124
|
+
row({ type: "Card Break", label: "Masters", link_count: 2 }),
|
|
125
|
+
row({ type: "Link", label: "User", link_type: "DocType", link_to: "User" }),
|
|
126
|
+
row({ type: "Link", label: "Role", link_type: "DocType", link_to: "Role" }),
|
|
127
|
+
row({ type: "Card Break", label: "Settings" }),
|
|
128
|
+
row({ type: "Link", label: "System Settings", link_to: "System Settings" }),
|
|
129
|
+
]);
|
|
130
|
+
expect(groups).toHaveLength(2);
|
|
131
|
+
expect(groups[0].label).toBe("Masters");
|
|
132
|
+
expect(groups[0].breakRow.link_count).toBe(2);
|
|
133
|
+
expect(groups[0].links.map((l) => l.label)).toEqual(["User", "Role"]);
|
|
134
|
+
expect(groups[1].label).toBe("Settings");
|
|
135
|
+
expect(groups[1].links.map((l) => l.label)).toEqual(["System Settings"]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("drops hidden rows", () => {
|
|
139
|
+
const groups = groupLinks([
|
|
140
|
+
row({ type: "Card Break", label: "Masters" }),
|
|
141
|
+
row({ type: "Link", label: "Visible" }),
|
|
142
|
+
row({ type: "Link", label: "Hidden", hidden: 1 }),
|
|
143
|
+
]);
|
|
144
|
+
expect(groups[0].links.map((l) => l.label)).toEqual(["Visible"]);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("ignores Link rows before any Card Break (desk parity)", () => {
|
|
148
|
+
const groups = groupLinks([
|
|
149
|
+
row({ type: "Link", label: "Orphan" }),
|
|
150
|
+
row({ type: "Card Break", label: "Masters" }),
|
|
151
|
+
row({ type: "Link", label: "User" }),
|
|
152
|
+
]);
|
|
153
|
+
expect(groups).toHaveLength(1);
|
|
154
|
+
expect(groups[0].links.map((l) => l.label)).toEqual(["User"]);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("returns [] for undefined or empty links", () => {
|
|
158
|
+
expect(groupLinks(undefined)).toEqual([]);
|
|
159
|
+
expect(groupLinks([])).toEqual([]);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe("parseFrappeFilters (bench-verified shapes)", () => {
|
|
164
|
+
it("normalizes a plain dict to = triples", () => {
|
|
165
|
+
expect(parseFrappeFilters('{"status":"Open"}')).toEqual([["status", "=", "Open"]]);
|
|
166
|
+
expect(parseFrappeFilters('{"enabled":1}')).toEqual([["enabled", "=", 1]]);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("normalizes a dict of [op, value] tuples", () => {
|
|
170
|
+
expect(parseFrappeFilters('{"status":["=","Open"]}')).toEqual([["status", "=", "Open"]]);
|
|
171
|
+
expect(parseFrappeFilters('{"status":["in",["Open","Overdue"]]}')).toEqual([
|
|
172
|
+
["status", "in", ["Open", "Overdue"]],
|
|
173
|
+
]);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("treats non-operator array values as = values", () => {
|
|
177
|
+
// 3-element array value is not an [op, value] tuple.
|
|
178
|
+
expect(parseFrappeFilters('{"role":["a","b","c"]}')).toEqual([["role", "=", ["a", "b", "c"]]]);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("passes triples through as-is", () => {
|
|
182
|
+
expect(parseFrappeFilters('[["enabled","=",1]]')).toEqual([["enabled", "=", 1]]);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("strips the doctype element from quads (Number Card filters_json)", () => {
|
|
186
|
+
expect(parseFrappeFilters('[["User","enabled","=",1]]')).toEqual([["enabled", "=", 1]]);
|
|
187
|
+
expect(
|
|
188
|
+
parseFrappeFilters('[["ToDo","status","=","Open"],["ToDo","priority","!=","Low"]]'),
|
|
189
|
+
).toEqual([
|
|
190
|
+
["status", "=", "Open"],
|
|
191
|
+
["priority", "!=", "Low"],
|
|
192
|
+
]);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it("handles mixed triples and quads, skipping malformed entries", () => {
|
|
196
|
+
expect(
|
|
197
|
+
parseFrappeFilters('[["status","=","Open"],["User","enabled","=",1],"junk",["short","="]]'),
|
|
198
|
+
).toEqual([
|
|
199
|
+
["status", "=", "Open"],
|
|
200
|
+
["enabled", "=", 1],
|
|
201
|
+
]);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("returns undefined for empty, malformed, or valueless input", () => {
|
|
205
|
+
expect(parseFrappeFilters(undefined)).toBeUndefined();
|
|
206
|
+
expect(parseFrappeFilters(null)).toBeUndefined();
|
|
207
|
+
expect(parseFrappeFilters("")).toBeUndefined();
|
|
208
|
+
expect(parseFrappeFilters("{not json")).toBeUndefined();
|
|
209
|
+
expect(parseFrappeFilters("[]")).toBeUndefined();
|
|
210
|
+
expect(parseFrappeFilters("{}")).toBeUndefined();
|
|
211
|
+
expect(parseFrappeFilters('"scalar"')).toBeUndefined();
|
|
212
|
+
expect(parseFrappeFilters("[1,2]")).toBeUndefined();
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("composeWorkspaceBlocks (dashboard-first, MOD-11)", () => {
|
|
217
|
+
const block = (type: string, data: Record<string, unknown>, id: string) =>
|
|
218
|
+
({ id, type, data }) as WorkspaceBlock;
|
|
219
|
+
|
|
220
|
+
it("reorders by class: data (cards → charts → quick lists), shortcuts, cards", () => {
|
|
221
|
+
const composed = composeWorkspaceBlocks([
|
|
222
|
+
block("header", { text: '<span class="h4"><b>Your Shortcuts</b></span>' }, "h1"),
|
|
223
|
+
block("shortcut", { shortcut_name: "User" }, "s1"),
|
|
224
|
+
block("spacer", {}, "sp1"),
|
|
225
|
+
block("header", { text: '<span class="h4"><b>Reports & Masters</b></span>' }, "h2"),
|
|
226
|
+
block("card", { card_name: "Users" }, "c1"),
|
|
227
|
+
block("quick_list", { quick_list_name: "ToDo" }, "q1"),
|
|
228
|
+
block("chart", { chart_name: "Signups" }, "ch1"),
|
|
229
|
+
block("number_card", { number_card_name: "Enabled Users" }, "n1"),
|
|
230
|
+
]);
|
|
231
|
+
expect(composed.data.map((b) => b.id)).toEqual(["n1", "ch1", "q1"]);
|
|
232
|
+
expect(composed.shortcuts.map((b) => b.id)).toEqual(["s1"]);
|
|
233
|
+
expect(composed.cards.map((b) => b.id)).toEqual(["c1"]);
|
|
234
|
+
expect(composed.text).toEqual([]);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("keeps authored order within each data class", () => {
|
|
238
|
+
const composed = composeWorkspaceBlocks([
|
|
239
|
+
block("chart", { chart_name: "B" }, "ch2"),
|
|
240
|
+
block("number_card", { number_card_name: "N1" }, "n1"),
|
|
241
|
+
block("chart", { chart_name: "A" }, "ch1"),
|
|
242
|
+
block("number_card", { number_card_name: "N2" }, "n2"),
|
|
243
|
+
]);
|
|
244
|
+
expect(composed.data.map((b) => b.id)).toEqual(["n1", "n2", "ch2", "ch1"]);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it("drops headers that label widget runs, keeps text-only headers", () => {
|
|
248
|
+
const composed = composeWorkspaceBlocks([
|
|
249
|
+
// Welcome-Workspace shape: header + paragraph only → both kept.
|
|
250
|
+
block("header", { text: '<span class="h2">Hi,</span>' }, "keep"),
|
|
251
|
+
block("paragraph", { text: "You can create a workspace." }, "p1"),
|
|
252
|
+
// Section label directly over shortcuts → dropped.
|
|
253
|
+
block("header", { text: "<b>Your Shortcuts</b>" }, "drop1"),
|
|
254
|
+
block("shortcut", { shortcut_name: "User" }, "s1"),
|
|
255
|
+
// Label separated from its cards by a spacer → still dropped.
|
|
256
|
+
block("header", { text: "<b>Masters</b>" }, "drop2"),
|
|
257
|
+
block("spacer", {}, "sp"),
|
|
258
|
+
block("card", { card_name: "Users" }, "c1"),
|
|
259
|
+
]);
|
|
260
|
+
expect(composed.text.map((b) => b.id)).toEqual(["keep", "p1"]);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("keeps a trailing header with no following blocks", () => {
|
|
264
|
+
const composed = composeWorkspaceBlocks([
|
|
265
|
+
block("shortcut", { shortcut_name: "User" }, "s1"),
|
|
266
|
+
block("header", { text: "<b>Notes</b>" }, "h1"),
|
|
267
|
+
]);
|
|
268
|
+
expect(composed.text.map((b) => b.id)).toEqual(["h1"]);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
it("drops headers labeling onboarding/custom blocks (which never render)", () => {
|
|
272
|
+
const composed = composeWorkspaceBlocks([
|
|
273
|
+
block("header", { text: "<b>Getting Started</b>" }, "h1"),
|
|
274
|
+
block("onboarding", { onboarding_name: "Setup" }, "o1"),
|
|
275
|
+
]);
|
|
276
|
+
expect(composed.text).toEqual([]);
|
|
277
|
+
expect(composed.data).toEqual([]);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("drops spacers and unknown block types", () => {
|
|
281
|
+
const composed = composeWorkspaceBlocks([
|
|
282
|
+
block("spacer", {}, "sp1"),
|
|
283
|
+
block("custom_block", {}, "cb1"),
|
|
284
|
+
block("paragraph", { text: "kept" }, "p1"),
|
|
285
|
+
]);
|
|
286
|
+
expect(composed.text.map((b) => b.id)).toEqual(["p1"]);
|
|
287
|
+
expect(composed.data).toEqual([]);
|
|
288
|
+
expect(composed.shortcuts).toEqual([]);
|
|
289
|
+
expect(composed.cards).toEqual([]);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it("returns all-empty sections for empty input", () => {
|
|
293
|
+
expect(composeWorkspaceBlocks([])).toEqual({
|
|
294
|
+
data: [],
|
|
295
|
+
shortcuts: [],
|
|
296
|
+
cards: [],
|
|
297
|
+
text: [],
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
describe("findShortcut / findLinkGroup", () => {
|
|
303
|
+
const doc: WorkspaceDoc = {
|
|
304
|
+
name: "Users",
|
|
305
|
+
doctype: "Workspace",
|
|
306
|
+
shortcuts: [
|
|
307
|
+
{ name: "s1", type: "DocType", label: "User", link_to: "User" },
|
|
308
|
+
{ name: "s2", type: "DocType", label: "Role", link_to: "Role" },
|
|
309
|
+
],
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
it("finds shortcut rows by the block's shortcut_name (label match)", () => {
|
|
313
|
+
expect(findShortcut(doc, "Role")?.link_to).toBe("Role");
|
|
314
|
+
expect(findShortcut(doc, "Missing")).toBeUndefined();
|
|
315
|
+
expect(findShortcut(doc, undefined)).toBeUndefined();
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it("finds link groups by the card block's card_name", () => {
|
|
319
|
+
const groups = groupLinks([
|
|
320
|
+
{ name: "b1", type: "Card Break", label: "Masters" },
|
|
321
|
+
{ name: "l1", type: "Link", label: "User" },
|
|
322
|
+
]);
|
|
323
|
+
expect(findLinkGroup(groups, "Masters")?.links).toHaveLength(1);
|
|
324
|
+
expect(findLinkGroup(groups, "Nope")).toBeUndefined();
|
|
325
|
+
expect(findLinkGroup(groups, undefined)).toBeUndefined();
|
|
326
|
+
});
|
|
327
|
+
});
|