@burdenoff/microfe-workspaces 2026.510.50

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.
Files changed (260) hide show
  1. package/README.md +88 -0
  2. package/dist/WorkspacesRoot.d.ts +35 -0
  3. package/dist/WorkspacesRoot.d.ts.map +1 -0
  4. package/dist/WorkspacesRoot.js +71 -0
  5. package/dist/WorkspacesRoot.js.map +1 -0
  6. package/dist/WorkspacesRoutes.d.ts +10 -0
  7. package/dist/WorkspacesRoutes.d.ts.map +1 -0
  8. package/dist/WorkspacesRoutes.js +111 -0
  9. package/dist/WorkspacesRoutes.js.map +1 -0
  10. package/dist/components/CreateProjectDialog.d.ts +6 -0
  11. package/dist/components/CreateProjectDialog.d.ts.map +1 -0
  12. package/dist/components/CreateProjectDialog.js +115 -0
  13. package/dist/components/CreateProjectDialog.js.map +1 -0
  14. package/dist/components/CreateWorkspaceDialog.d.ts +2 -0
  15. package/dist/components/CreateWorkspaceDialog.d.ts.map +1 -0
  16. package/dist/components/CreateWorkspaceDialog.js +172 -0
  17. package/dist/components/CreateWorkspaceDialog.js.map +1 -0
  18. package/dist/components/InviteMemberDialog.d.ts +7 -0
  19. package/dist/components/InviteMemberDialog.d.ts.map +1 -0
  20. package/dist/components/InviteMemberDialog.js +148 -0
  21. package/dist/components/InviteMemberDialog.js.map +1 -0
  22. package/dist/components/MemberListItem.d.ts +11 -0
  23. package/dist/components/MemberListItem.d.ts.map +1 -0
  24. package/dist/components/MemberListItem.js +118 -0
  25. package/dist/components/MemberListItem.js.map +1 -0
  26. package/dist/components/ProjectCard.d.ts +13 -0
  27. package/dist/components/ProjectCard.d.ts.map +1 -0
  28. package/dist/components/ProjectCard.js +150 -0
  29. package/dist/components/ProjectCard.js.map +1 -0
  30. package/dist/components/WorkspaceCard.d.ts +8 -0
  31. package/dist/components/WorkspaceCard.d.ts.map +1 -0
  32. package/dist/components/WorkspaceCard.js +79 -0
  33. package/dist/components/WorkspaceCard.js.map +1 -0
  34. package/dist/components/WorkspacesErrorBoundary.d.ts +27 -0
  35. package/dist/components/WorkspacesErrorBoundary.d.ts.map +1 -0
  36. package/dist/components/WorkspacesErrorBoundary.js +136 -0
  37. package/dist/components/WorkspacesErrorBoundary.js.map +1 -0
  38. package/dist/components/index.d.ts +8 -0
  39. package/dist/components/index.d.ts.map +1 -0
  40. package/dist/components/index.js +7 -0
  41. package/dist/constants/permissions.d.ts +33 -0
  42. package/dist/constants/permissions.d.ts.map +1 -0
  43. package/dist/constants/permissions.js +31 -0
  44. package/dist/constants/permissions.js.map +1 -0
  45. package/dist/generated/global-operations.d.ts +279 -0
  46. package/dist/generated/global-operations.d.ts.map +1 -0
  47. package/dist/generated/global-operations.js +103 -0
  48. package/dist/generated/global-operations.js.map +1 -0
  49. package/dist/generated/global-types.d.ts +20714 -0
  50. package/dist/generated/global-types.d.ts.map +1 -0
  51. package/dist/generated/wspace-operations.d.ts +2209 -0
  52. package/dist/generated/wspace-operations.d.ts.map +1 -0
  53. package/dist/generated/wspace-operations.js +576 -0
  54. package/dist/generated/wspace-operations.js.map +1 -0
  55. package/dist/generated/wspace-types.d.ts +54990 -0
  56. package/dist/generated/wspace-types.d.ts.map +1 -0
  57. package/dist/hooks/index.d.ts +8 -0
  58. package/dist/hooks/index.d.ts.map +1 -0
  59. package/dist/hooks/index.js +7 -0
  60. package/dist/hooks/useMemberMutations.d.ts +61 -0
  61. package/dist/hooks/useMemberMutations.d.ts.map +1 -0
  62. package/dist/hooks/useMemberMutations.js +263 -0
  63. package/dist/hooks/useMemberMutations.js.map +1 -0
  64. package/dist/hooks/useProjectMutations.d.ts +26 -0
  65. package/dist/hooks/useProjectMutations.d.ts.map +1 -0
  66. package/dist/hooks/useProjectMutations.js +127 -0
  67. package/dist/hooks/useProjectMutations.js.map +1 -0
  68. package/dist/hooks/useProjects.d.ts +16 -0
  69. package/dist/hooks/useProjects.d.ts.map +1 -0
  70. package/dist/hooks/useProjects.js +103 -0
  71. package/dist/hooks/useProjects.js.map +1 -0
  72. package/dist/hooks/useScopedNavigation.d.ts +4 -0
  73. package/dist/hooks/useScopedNavigation.d.ts.map +1 -0
  74. package/dist/hooks/useScopedNavigation.js +11 -0
  75. package/dist/hooks/useScopedNavigation.js.map +1 -0
  76. package/dist/hooks/useTenants.d.ts +13 -0
  77. package/dist/hooks/useTenants.d.ts.map +1 -0
  78. package/dist/hooks/useTenants.js +47 -0
  79. package/dist/hooks/useTenants.js.map +1 -0
  80. package/dist/hooks/useWorkspaceActivity.d.ts +12 -0
  81. package/dist/hooks/useWorkspaceActivity.d.ts.map +1 -0
  82. package/dist/hooks/useWorkspaceActivity.js +31 -0
  83. package/dist/hooks/useWorkspaceActivity.js.map +1 -0
  84. package/dist/hooks/useWorkspaceMembers.d.ts +24 -0
  85. package/dist/hooks/useWorkspaceMembers.d.ts.map +1 -0
  86. package/dist/hooks/useWorkspaceMembers.js +130 -0
  87. package/dist/hooks/useWorkspaceMembers.js.map +1 -0
  88. package/dist/hooks/useWorkspaceMutations.d.ts +36 -0
  89. package/dist/hooks/useWorkspaceMutations.d.ts.map +1 -0
  90. package/dist/hooks/useWorkspaceMutations.js +119 -0
  91. package/dist/hooks/useWorkspaceMutations.js.map +1 -0
  92. package/dist/hooks/useWorkspacePermissions.d.ts +29 -0
  93. package/dist/hooks/useWorkspacePermissions.d.ts.map +1 -0
  94. package/dist/hooks/useWorkspacePermissions.js +33 -0
  95. package/dist/hooks/useWorkspacePermissions.js.map +1 -0
  96. package/dist/hooks/useWorkspaceRoles.d.ts +8 -0
  97. package/dist/hooks/useWorkspaceRoles.d.ts.map +1 -0
  98. package/dist/hooks/useWorkspaceRoles.js +31 -0
  99. package/dist/hooks/useWorkspaceRoles.js.map +1 -0
  100. package/dist/hooks/useWorkspaces.d.ts +21 -0
  101. package/dist/hooks/useWorkspaces.d.ts.map +1 -0
  102. package/dist/hooks/useWorkspaces.js +75 -0
  103. package/dist/hooks/useWorkspaces.js.map +1 -0
  104. package/dist/hooks/useWorkspacesEventEmitter.d.ts +14 -0
  105. package/dist/hooks/useWorkspacesEventEmitter.d.ts.map +1 -0
  106. package/dist/hooks/useWorkspacesEventEmitter.js +14 -0
  107. package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -0
  108. package/dist/index.d.ts +33 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +24 -0
  111. package/dist/pages/ActivityListPage.d.ts +2 -0
  112. package/dist/pages/ActivityListPage.d.ts.map +1 -0
  113. package/dist/pages/ActivityListPage.js +119 -0
  114. package/dist/pages/ActivityListPage.js.map +1 -0
  115. package/dist/pages/CreateWorkspacePage.d.ts +2 -0
  116. package/dist/pages/CreateWorkspacePage.d.ts.map +1 -0
  117. package/dist/pages/CreateWorkspacePage.js +264 -0
  118. package/dist/pages/CreateWorkspacePage.js.map +1 -0
  119. package/dist/pages/InviteAcceptancePage.d.ts +6 -0
  120. package/dist/pages/InviteAcceptancePage.d.ts.map +1 -0
  121. package/dist/pages/InviteAcceptancePage.js +495 -0
  122. package/dist/pages/InviteAcceptancePage.js.map +1 -0
  123. package/dist/pages/MembersListPage.d.ts +2 -0
  124. package/dist/pages/MembersListPage.d.ts.map +1 -0
  125. package/dist/pages/MembersListPage.js +420 -0
  126. package/dist/pages/MembersListPage.js.map +1 -0
  127. package/dist/pages/ProjectDetailPage.d.ts +2 -0
  128. package/dist/pages/ProjectDetailPage.d.ts.map +1 -0
  129. package/dist/pages/ProjectDetailPage.js +361 -0
  130. package/dist/pages/ProjectDetailPage.js.map +1 -0
  131. package/dist/pages/ProjectsListPage.d.ts +2 -0
  132. package/dist/pages/ProjectsListPage.d.ts.map +1 -0
  133. package/dist/pages/ProjectsListPage.js +398 -0
  134. package/dist/pages/ProjectsListPage.js.map +1 -0
  135. package/dist/pages/WorkspaceDetailPage.d.ts +2 -0
  136. package/dist/pages/WorkspaceDetailPage.d.ts.map +1 -0
  137. package/dist/pages/WorkspaceDetailPage.js +230 -0
  138. package/dist/pages/WorkspaceDetailPage.js.map +1 -0
  139. package/dist/pages/WorkspaceSettingsPage.d.ts +2 -0
  140. package/dist/pages/WorkspaceSettingsPage.d.ts.map +1 -0
  141. package/dist/pages/WorkspaceSettingsPage.js +157 -0
  142. package/dist/pages/WorkspaceSettingsPage.js.map +1 -0
  143. package/dist/pages/WorkspacesListPage.d.ts +2 -0
  144. package/dist/pages/WorkspacesListPage.d.ts.map +1 -0
  145. package/dist/pages/WorkspacesListPage.js +186 -0
  146. package/dist/pages/WorkspacesListPage.js.map +1 -0
  147. package/dist/pages/dashboard/DashboardCustomizer.d.ts +12 -0
  148. package/dist/pages/dashboard/DashboardCustomizer.d.ts.map +1 -0
  149. package/dist/pages/dashboard/DashboardCustomizer.js +136 -0
  150. package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -0
  151. package/dist/pages/dashboard/DashboardGrid.d.ts +8 -0
  152. package/dist/pages/dashboard/DashboardGrid.d.ts.map +1 -0
  153. package/dist/pages/dashboard/DashboardGrid.js +58 -0
  154. package/dist/pages/dashboard/DashboardGrid.js.map +1 -0
  155. package/dist/pages/dashboard/DashboardPage.d.ts +14 -0
  156. package/dist/pages/dashboard/DashboardPage.d.ts.map +1 -0
  157. package/dist/pages/dashboard/DashboardPage.js +136 -0
  158. package/dist/pages/dashboard/DashboardPage.js.map +1 -0
  159. package/dist/pages/dashboard/WidgetWrapper.d.ts +17 -0
  160. package/dist/pages/dashboard/WidgetWrapper.d.ts.map +1 -0
  161. package/dist/pages/dashboard/WidgetWrapper.js +72 -0
  162. package/dist/pages/dashboard/WidgetWrapper.js.map +1 -0
  163. package/dist/pages/dashboard/config.d.ts +9 -0
  164. package/dist/pages/dashboard/config.d.ts.map +1 -0
  165. package/dist/pages/dashboard/config.js +214 -0
  166. package/dist/pages/dashboard/config.js.map +1 -0
  167. package/dist/pages/dashboard/hooks/useDashboardData.d.ts +9 -0
  168. package/dist/pages/dashboard/hooks/useDashboardData.d.ts.map +1 -0
  169. package/dist/pages/dashboard/hooks/useDashboardData.js +118 -0
  170. package/dist/pages/dashboard/hooks/useDashboardData.js.map +1 -0
  171. package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts +4 -0
  172. package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts.map +1 -0
  173. package/dist/pages/dashboard/hooks/useDashboardPreferences.js +32 -0
  174. package/dist/pages/dashboard/hooks/useDashboardPreferences.js.map +1 -0
  175. package/dist/pages/dashboard/types.d.ts +145 -0
  176. package/dist/pages/dashboard/types.d.ts.map +1 -0
  177. package/dist/pages/dashboard/widgets/GroupsWidget.d.ts +4 -0
  178. package/dist/pages/dashboard/widgets/GroupsWidget.d.ts.map +1 -0
  179. package/dist/pages/dashboard/widgets/GroupsWidget.js +59 -0
  180. package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -0
  181. package/dist/pages/dashboard/widgets/MembersWidget.d.ts +4 -0
  182. package/dist/pages/dashboard/widgets/MembersWidget.d.ts.map +1 -0
  183. package/dist/pages/dashboard/widgets/MembersWidget.js +65 -0
  184. package/dist/pages/dashboard/widgets/MembersWidget.js.map +1 -0
  185. package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts +4 -0
  186. package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts.map +1 -0
  187. package/dist/pages/dashboard/widgets/ProjectsWidget.js +91 -0
  188. package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -0
  189. package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts +4 -0
  190. package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts.map +1 -0
  191. package/dist/pages/dashboard/widgets/QuickActionsWidget.js +80 -0
  192. package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -0
  193. package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts +4 -0
  194. package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts.map +1 -0
  195. package/dist/pages/dashboard/widgets/RecentActivityWidget.js +81 -0
  196. package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -0
  197. package/dist/pages/dashboard/widgets/StorageWidget.d.ts +4 -0
  198. package/dist/pages/dashboard/widgets/StorageWidget.d.ts.map +1 -0
  199. package/dist/pages/dashboard/widgets/StorageWidget.js +69 -0
  200. package/dist/pages/dashboard/widgets/StorageWidget.js.map +1 -0
  201. package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts +4 -0
  202. package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts.map +1 -0
  203. package/dist/pages/dashboard/widgets/SystemHealthWidget.js +59 -0
  204. package/dist/pages/dashboard/widgets/SystemHealthWidget.js.map +1 -0
  205. package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts +4 -0
  206. package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts.map +1 -0
  207. package/dist/pages/dashboard/widgets/TagCloudWidget.js +61 -0
  208. package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -0
  209. package/dist/pages/dashboard/widgets/TipsWidget.d.ts +4 -0
  210. package/dist/pages/dashboard/widgets/TipsWidget.d.ts.map +1 -0
  211. package/dist/pages/dashboard/widgets/TipsWidget.js +67 -0
  212. package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -0
  213. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts +4 -0
  214. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts.map +1 -0
  215. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +83 -0
  216. package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -0
  217. package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts +4 -0
  218. package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts.map +1 -0
  219. package/dist/pages/dashboard/widgets/WelcomeWidget.js +71 -0
  220. package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -0
  221. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts +4 -0
  222. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts.map +1 -0
  223. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +97 -0
  224. package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -0
  225. package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts +4 -0
  226. package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts.map +1 -0
  227. package/dist/pages/dashboard/widgets/WorkspacesWidget.js +67 -0
  228. package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -0
  229. package/dist/providers/WorkspacesProvider.d.ts +13 -0
  230. package/dist/providers/WorkspacesProvider.d.ts.map +1 -0
  231. package/dist/providers/WorkspacesProvider.js +24 -0
  232. package/dist/providers/WorkspacesProvider.js.map +1 -0
  233. package/dist/store/workspacesStore.d.ts +82 -0
  234. package/dist/store/workspacesStore.d.ts.map +1 -0
  235. package/dist/store/workspacesStore.js +92 -0
  236. package/dist/store/workspacesStore.js.map +1 -0
  237. package/dist/types/index.d.ts +280 -0
  238. package/dist/types/index.d.ts.map +1 -0
  239. package/dist/utils/formatters.d.ts +60 -0
  240. package/dist/utils/formatters.d.ts.map +1 -0
  241. package/dist/utils/formatters.js +61 -0
  242. package/dist/utils/formatters.js.map +1 -0
  243. package/dist/utils/index.d.ts +3 -0
  244. package/dist/utils/index.d.ts.map +1 -0
  245. package/dist/utils/nativeBridge.d.ts +3 -0
  246. package/dist/utils/nativeBridge.d.ts.map +1 -0
  247. package/dist/utils/nativeBridge.js +2 -0
  248. package/dist/utils/projectTags.d.ts +6 -0
  249. package/dist/utils/projectTags.d.ts.map +1 -0
  250. package/dist/utils/projectTags.js +49 -0
  251. package/dist/utils/projectTags.js.map +1 -0
  252. package/dist/utils/slug.d.ts +13 -0
  253. package/dist/utils/slug.d.ts.map +1 -0
  254. package/dist/utils/slug.js +8 -0
  255. package/dist/utils/slug.js.map +1 -0
  256. package/dist/utils/tokenHelpers.d.ts +114 -0
  257. package/dist/utils/tokenHelpers.d.ts.map +1 -0
  258. package/dist/utils/tokenHelpers.js +80 -0
  259. package/dist/utils/tokenHelpers.js.map +1 -0
  260. package/package.json +113 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/pages/dashboard/DashboardPage.tsx"],"sourcesContent":["/**\n * DashboardPage — Comprehensive workspace dashboard.\n *\n * This is the main dashboard component exported from microfe-workspaces.\n * It fetches data from both workspace and global gateways, manages widget\n * layout preferences, and renders a customizable grid of widgets.\n *\n * Props:\n * - navigate: Shell navigation function\n * - authToken: Current user's auth token\n * - currentUser: Basic user info from shell\n *\n * Data Flow:\n * 1. Two parallel queries: workspace gateway + global gateway\n * 2. Global query returns user preferences (dashboard layout)\n * 3. Widget layout falls back to defaults if no preferences saved\n * 4. Data is passed as props to individual widgets\n */\nimport { useState, useMemo, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Button, Skeleton } from '@burdenoff/fe-libs/ui';\nimport { Settings2, RefreshCw, Loader2, AlertCircle } from 'lucide-react';\nimport {\n useWorkspaceDashboardData,\n useGlobalDashboardData,\n useProjectsDashboardData,\n} from './hooks/useDashboardData';\nimport { useUpdateDashboardPreferences } from './hooks/useDashboardPreferences';\nimport { DashboardGrid } from './DashboardGrid';\nimport { DashboardCustomizer } from './DashboardCustomizer';\nimport { getEffectiveWidgets, DEFAULT_DASHBOARD_WIDGETS } from './config';\nimport type { WidgetConfig, DashboardPreferences } from './types';\n\ninterface DashboardPageProps {\n navigate: (path: string) => void;\n authToken?: string | null;\n currentUser?: {\n id: string;\n email: string;\n firstName?: string;\n lastName?: string;\n name?: string;\n } | null;\n}\n\nexport function DashboardPage({ navigate, authToken, currentUser }: DashboardPageProps) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const [customizerOpen, setCustomizerOpen] = useState(false);\n\n // ─── Data Fetching ────────────────────────────────────────────────────────\n const {\n data: workspaceData,\n isLoading: wsLoading,\n error: wsError,\n refetch: refetchWs,\n } = useWorkspaceDashboardData(authToken);\n\n const {\n data: globalData,\n isLoading: globalLoading,\n error: globalError,\n refetch: refetchGlobal,\n } = useGlobalDashboardData(authToken);\n\n const {\n data: projectsData,\n isLoading: projectsLoading,\n refetch: refetchProjects,\n } = useProjectsDashboardData(authToken);\n\n const updatePrefs = useUpdateDashboardPreferences(authToken);\n\n const isLoading = wsLoading || globalLoading || projectsLoading;\n\n // ─── Merge data ───────────────────────────────────────────────────────────\n // Workspace/org stats come from the global tenant service (globalData),\n // while workspace-scoped features (activity, calendar, tags, etc.) come\n // from the workspace gateway (workspaceData). Merge them so widgets\n // reading workspaceData.workspaces see the real tenant data.\n const mergedWorkspaceData = useMemo(() => {\n if (!workspaceData && !globalData && !projectsData) return null;\n return {\n ...(workspaceData ?? {\n workspaces: { items: [], total: 0 },\n projects: { items: [], total: 0 },\n recentActivities: [],\n upcomingEvents: [],\n tags: { items: [], total: 0 },\n groups: { items: [], totalCount: 0 },\n workflowStats: null,\n storageUsage: null,\n }),\n // Override with real workspace/org data from the global gateway\n workspaces: globalData?.workspaces ?? { items: [], total: 0 },\n // Override with real project data from the separate projects query\n // (fetched independently to avoid being poisoned by other subgraph errors)\n projects: projectsData ?? { items: [], total: 0 },\n };\n }, [workspaceData, globalData, projectsData]);\n\n // ─── Widget Configuration ─────────────────────────────────────────────────\n const savedPrefs = globalData?.dashboardPreferences;\n const widgets = useMemo(() => getEffectiveWidgets(savedPrefs?.widgets ?? null), [savedPrefs]);\n\n // ─── Handlers ─────────────────────────────────────────────────────────────\n const handleRefresh = useCallback(() => {\n refetchWs();\n refetchGlobal();\n refetchProjects();\n }, [refetchWs, refetchGlobal, refetchProjects]);\n\n const handleSaveWidgets = useCallback(\n async (newWidgets: WidgetConfig[]) => {\n await updatePrefs.mutateAsync(newWidgets);\n },\n [updatePrefs]\n );\n\n // ─── Error Banner ─────────────────────────────────────────────────────────\n const hasError = wsError || globalError;\n\n return (\n <div className=\"min-h-[calc(100vh-8rem)] p-4 md:p-6 bg-bg-canvas\" data-tour=\"main-content\">\n {/* Header */}\n <div className=\"flex flex-wrap items-center justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"text-xl font-bold text-text-primary\">\n {tr('dashboard.title', 'Dashboard')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-0.5\">\n {tr('dashboard.subtitle', 'Your workspace overview at a glance')}\n </p>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\" data-tour=\"quick-actions\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleRefresh}\n disabled={isLoading}\n className=\"text-xs\"\n >\n {isLoading ? (\n <Loader2 className=\"h-3.5 w-3.5 sm:mr-1.5 animate-spin\" />\n ) : (\n <RefreshCw className=\"h-3.5 w-3.5 sm:mr-1.5\" />\n )}\n <span className=\"hidden sm:inline\">{tr('dashboard.refresh', 'Refresh')}</span>\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setCustomizerOpen(true)}\n className=\"text-xs\"\n >\n <Settings2 className=\"h-3.5 w-3.5 sm:mr-1.5\" />\n <span className=\"hidden sm:inline\">{tr('dashboard.customize', 'Customize')}</span>\n </Button>\n </div>\n </div>\n\n {/* Error Banner */}\n {hasError && (\n <div className=\"mb-4 p-3 bg-destructive/10 border border-destructive/20 rounded-lg flex items-center gap-2\">\n <AlertCircle className=\"h-4 w-4 text-destructive shrink-0\" />\n <p className=\"text-sm text-destructive\">\n {tr('dashboard.error.partialData', 'Some data may be unavailable.')}{' '}\n {wsError ? tr('dashboard.error.workspaceDown', 'Workspace services may be down.') : ''}{' '}\n {globalError ? tr('dashboard.error.globalDown', 'Global services may be down.') : ''}{' '}\n <button\n className=\"underline font-medium hover:text-destructive/80\"\n onClick={handleRefresh}\n >\n {tr('dashboard.error.tryRefreshing', 'Try refreshing')}\n </button>\n </p>\n </div>\n )}\n\n {/* Widget Grid */}\n {/* Merge workspace/org data from the global query into workspaceData\n so widgets that read workspaceData.workspaces see the real data\n from the global tenant service. */}\n <DashboardGrid\n widgets={widgets}\n workspaceData={mergedWorkspaceData}\n globalData={globalData ?? null}\n isLoading={isLoading}\n navigate={navigate}\n />\n\n {/* Customizer */}\n <DashboardCustomizer\n open={customizerOpen}\n onOpenChange={setCustomizerOpen}\n widgets={widgets}\n onSave={handleSaveWidgets}\n isSaving={updatePrefs.isPending}\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from 'react';
2
+ import { WidgetSize } from './types';
3
+
4
+ interface WidgetWrapperProps {
5
+ title: string;
6
+ icon?: ReactNode;
7
+ size: WidgetSize;
8
+ isLoading?: boolean;
9
+ error?: string | null;
10
+ unavailable?: boolean;
11
+ headerAction?: ReactNode;
12
+ children: ReactNode;
13
+ className?: string;
14
+ }
15
+ export declare function WidgetWrapper({ title, icon, size, isLoading, error, unavailable, headerAction, children, className, }: WidgetWrapperProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=WidgetWrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetWrapper.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/WidgetWrapper.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,OAAO,CAAC;AAKpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,UAAU,kBAAkB;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2DD,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,KAAK,EACL,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,SAAc,GACf,EAAE,kBAAkB,2CA2BpB"}
@@ -0,0 +1,72 @@
1
+ import { useCallback as e } from "react";
2
+ import { AlertCircle as t, WifiOff as n } from "lucide-react";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ import { Card as a, CardContent as o, CardHeader as s, CardTitle as c, Skeleton as l } from "@burdenoff/fe-libs/ui";
5
+ import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
+ //#region src/pages/dashboard/WidgetWrapper.tsx
7
+ function d(e) {
8
+ switch (e) {
9
+ case "large": return "col-span-1 sm:col-span-2 lg:col-span-3";
10
+ case "medium": return "col-span-1 sm:col-span-2 lg:col-span-2 xl:col-span-2 2xl:col-span-1";
11
+ case "small": return "col-span-1";
12
+ default: return "col-span-1";
13
+ }
14
+ }
15
+ function f() {
16
+ return /* @__PURE__ */ i("div", {
17
+ className: "space-y-3 p-1",
18
+ children: [
19
+ /* @__PURE__ */ r(l, { className: "h-4 w-3/4" }),
20
+ /* @__PURE__ */ r(l, { className: "h-4 w-1/2" }),
21
+ /* @__PURE__ */ r(l, { className: "h-20 w-full" }),
22
+ /* @__PURE__ */ r(l, { className: "h-4 w-2/3" })
23
+ ]
24
+ });
25
+ }
26
+ function p({ message: e }) {
27
+ return /* @__PURE__ */ i("div", {
28
+ className: "flex flex-col items-center justify-center py-6 text-center",
29
+ children: [/* @__PURE__ */ r("div", {
30
+ className: "rounded-full bg-destructive/10 p-2 mb-2",
31
+ children: /* @__PURE__ */ r(t, { className: "h-5 w-5 text-destructive" })
32
+ }), /* @__PURE__ */ r("p", {
33
+ className: "text-sm text-muted-foreground",
34
+ children: e
35
+ })]
36
+ });
37
+ }
38
+ function m() {
39
+ let { t } = u(), a = e((e, n) => {
40
+ let r = t(e);
41
+ return r === e ? n : r;
42
+ }, [t]);
43
+ return /* @__PURE__ */ i("div", {
44
+ className: "flex flex-col items-center justify-center py-6 text-center",
45
+ children: [/* @__PURE__ */ r("div", {
46
+ className: "rounded-full bg-muted p-2 mb-2",
47
+ children: /* @__PURE__ */ r(n, { className: "h-5 w-5 text-muted-foreground" })
48
+ }), /* @__PURE__ */ r("p", {
49
+ className: "text-sm text-muted-foreground",
50
+ children: a("widgetWrapper.serviceUnavailable", "Service unavailable")
51
+ })]
52
+ });
53
+ }
54
+ function h({ title: e, icon: t, size: n, isLoading: l, error: u, unavailable: h, headerAction: g, children: _, className: v = "" }) {
55
+ return /* @__PURE__ */ i(a, {
56
+ className: `${d(n)} transition-all duration-200 hover:shadow-md border border-border-default bg-bg-surface ${v}`,
57
+ children: [/* @__PURE__ */ i(s, {
58
+ className: "flex flex-row items-center justify-between pb-2 space-y-0",
59
+ children: [/* @__PURE__ */ i(c, {
60
+ className: "text-sm font-semibold text-text-primary flex items-center gap-2",
61
+ children: [t, e]
62
+ }), g]
63
+ }), /* @__PURE__ */ r(o, {
64
+ className: "pt-0",
65
+ children: l ? /* @__PURE__ */ r(f, {}) : u ? /* @__PURE__ */ r(p, { message: u }) : h ? /* @__PURE__ */ r(m, {}) : _
66
+ })]
67
+ });
68
+ }
69
+ //#endregion
70
+ export { h as WidgetWrapper };
71
+
72
+ //# sourceMappingURL=WidgetWrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetWrapper.js","names":[],"sources":["../../../src/pages/dashboard/WidgetWrapper.tsx"],"sourcesContent":["/**\n * WidgetWrapper — Common wrapper for all dashboard widgets.\n *\n * Provides consistent card styling, loading skeleton, error state,\n * and unavailable state.\n */\nimport { type ReactNode, useCallback } from 'react';\nimport { Card, CardContent, CardHeader, CardTitle } from '@burdenoff/fe-libs/ui';\nimport { Skeleton } from '@burdenoff/fe-libs/ui';\nimport { AlertCircle, WifiOff } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { WidgetSize } from './types';\n\ninterface WidgetWrapperProps {\n title: string;\n icon?: ReactNode;\n size: WidgetSize;\n isLoading?: boolean;\n error?: string | null;\n unavailable?: boolean;\n headerAction?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nfunction getColSpan(size: WidgetSize): string {\n switch (size) {\n case 'large':\n return 'col-span-1 sm:col-span-2 lg:col-span-3';\n case 'medium':\n return 'col-span-1 sm:col-span-2 lg:col-span-2 xl:col-span-2 2xl:col-span-1';\n case 'small':\n return 'col-span-1';\n default:\n return 'col-span-1';\n }\n}\n\nfunction LoadingSkeleton() {\n return (\n <div className=\"space-y-3 p-1\">\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-4 w-1/2\" />\n <Skeleton className=\"h-20 w-full\" />\n <Skeleton className=\"h-4 w-2/3\" />\n </div>\n );\n}\n\nfunction ErrorState({ message }: { message: string }) {\n return (\n <div className=\"flex flex-col items-center justify-center py-6 text-center\">\n <div className=\"rounded-full bg-destructive/10 p-2 mb-2\">\n <AlertCircle className=\"h-5 w-5 text-destructive\" />\n </div>\n <p className=\"text-sm text-muted-foreground\">{message}</p>\n </div>\n );\n}\n\nfunction UnavailableState() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n\n return (\n <div className=\"flex flex-col items-center justify-center py-6 text-center\">\n <div className=\"rounded-full bg-muted p-2 mb-2\">\n <WifiOff className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"text-sm text-muted-foreground\">\n {tr('widgetWrapper.serviceUnavailable', 'Service unavailable')}\n </p>\n </div>\n );\n}\n\nexport function WidgetWrapper({\n title,\n icon,\n size,\n isLoading,\n error,\n unavailable,\n headerAction,\n children,\n className = '',\n}: WidgetWrapperProps) {\n const colSpan = getColSpan(size);\n\n return (\n <Card\n className={`${colSpan} transition-all duration-200 hover:shadow-md border border-border-default bg-bg-surface ${className}`}\n >\n <CardHeader className=\"flex flex-row items-center justify-between pb-2 space-y-0\">\n <CardTitle className=\"text-sm font-semibold text-text-primary flex items-center gap-2\">\n {icon}\n {title}\n </CardTitle>\n {headerAction}\n </CardHeader>\n <CardContent className=\"pt-0\">\n {isLoading ? (\n <LoadingSkeleton />\n ) : error ? (\n <ErrorState message={error} />\n ) : unavailable ? (\n <UnavailableState />\n ) : (\n children\n )}\n </CardContent>\n </Card>\n );\n}\n"],"mappings":";;;;;;AAyBA,SAAS,EAAW,GAA0B;AAC5C,SAAQ,GAAR;EACE,KAAK,QACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAS,IAAkB;AACzB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;GAClC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;GAClC,kBAAC,GAAD,EAAU,WAAU,eAAgB,CAAA;GACpC,kBAAC,GAAD,EAAU,WAAU,aAAc,CAAA;GAC9B;;;AAIV,SAAS,EAAW,EAAE,cAAgC;AACpD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAa,WAAU,4BAA6B,CAAA;GAChD,CAAA,EACN,kBAAC,KAAD;GAAG,WAAU;aAAiC;GAAY,CAAA,CACtD;;;AAIV,SAAS,IAAmB;CAC1B,IAAM,EAAE,MAAM,GAAS,EACjB,IAAK,GACR,GAAa,MAA6B;EACzC,IAAM,IAAQ,EAAE,EAAI;AACpB,SAAO,MAAU,IAAM,IAAW;IAEpC,CAAC,EAAE,CACJ;AAED,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAS,WAAU,iCAAkC,CAAA;GACjD,CAAA,EACN,kBAAC,KAAD;GAAG,WAAU;aACV,EAAG,oCAAoC,sBAAsB;GAC5D,CAAA,CACA;;;AAIV,SAAgB,EAAc,EAC5B,UACA,SACA,SACA,cACA,UACA,gBACA,iBACA,aACA,eAAY,MACS;AAGrB,QACE,kBAAC,GAAD;EACE,WAAW,GAJC,EAAW,EAAK,CAIN,0FAA0F;YADlH,CAGE,kBAAC,GAAD;GAAY,WAAU;aAAtB,CACE,kBAAC,GAAD;IAAW,WAAU;cAArB,CACG,GACA,EACS;OACX,EACU;MACb,kBAAC,GAAD;GAAa,WAAU;aACpB,IACC,kBAAC,GAAD,EAAmB,CAAA,GACjB,IACF,kBAAC,GAAD,EAAY,SAAS,GAAS,CAAA,GAC5B,IACF,kBAAC,GAAD,EAAoB,CAAA,GAEpB;GAEU,CAAA,CACT"}
@@ -0,0 +1,9 @@
1
+ import { WidgetConfig, WidgetDefinition } from './types';
2
+
3
+ export declare const WIDGET_DEFINITIONS: Record<string, WidgetDefinition>;
4
+ export declare const DEFAULT_DASHBOARD_WIDGETS: WidgetConfig[];
5
+ /**
6
+ * Get the effective widget configuration, merging user prefs with defaults.
7
+ */
8
+ export declare function getEffectiveWidgets(userPrefs: WidgetConfig[] | null | undefined): WidgetConfig[];
9
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAI9D,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAsH/D,CAAC;AAIF,eAAO,MAAM,yBAAyB,EAAE,YAAY,EAcnD,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,EAAE,CAqBhG"}
@@ -0,0 +1,214 @@
1
+ //#region src/pages/dashboard/config.ts
2
+ var e = {
3
+ welcome: {
4
+ id: "welcome",
5
+ title: "Welcome",
6
+ description: "Greeting and overview statistics",
7
+ icon: "LayoutDashboard",
8
+ defaultSize: "large",
9
+ removable: !1,
10
+ dataSource: "global"
11
+ },
12
+ quickActions: {
13
+ id: "quickActions",
14
+ title: "Quick Actions",
15
+ description: "Frequently used actions and shortcuts",
16
+ icon: "Zap",
17
+ defaultSize: "medium",
18
+ removable: !0,
19
+ dataSource: "static"
20
+ },
21
+ workspaces: {
22
+ id: "workspaces",
23
+ title: "Workspaces",
24
+ description: "Your workspaces overview and quick access",
25
+ icon: "Building2",
26
+ defaultSize: "medium",
27
+ removable: !0,
28
+ dataSource: "workspace"
29
+ },
30
+ projects: {
31
+ id: "projects",
32
+ title: "Projects",
33
+ description: "Recent projects and status breakdown",
34
+ icon: "FolderKanban",
35
+ defaultSize: "medium",
36
+ removable: !0,
37
+ dataSource: "workspace"
38
+ },
39
+ activity: {
40
+ id: "activity",
41
+ title: "Recent Activity",
42
+ description: "Timeline of recent activity across modules",
43
+ icon: "Activity",
44
+ defaultSize: "large",
45
+ removable: !0,
46
+ dataSource: "workspace"
47
+ },
48
+ calendar: {
49
+ id: "calendar",
50
+ title: "Upcoming Events",
51
+ description: "Next upcoming calendar events",
52
+ icon: "Calendar",
53
+ defaultSize: "medium",
54
+ removable: !0,
55
+ dataSource: "workspace"
56
+ },
57
+ workflows: {
58
+ id: "workflows",
59
+ title: "Workflows",
60
+ description: "Active workflow stats and recent runs",
61
+ icon: "GitBranch",
62
+ defaultSize: "medium",
63
+ removable: !0,
64
+ dataSource: "workspace"
65
+ },
66
+ tags: {
67
+ id: "tags",
68
+ title: "Tags",
69
+ description: "Popular tags across your workspace",
70
+ icon: "Tags",
71
+ defaultSize: "small",
72
+ removable: !0,
73
+ dataSource: "workspace"
74
+ },
75
+ storage: {
76
+ id: "storage",
77
+ title: "Storage",
78
+ description: "Storage usage and file statistics",
79
+ icon: "HardDrive",
80
+ defaultSize: "small",
81
+ removable: !0,
82
+ dataSource: "workspace"
83
+ },
84
+ groups: {
85
+ id: "groups",
86
+ title: "Groups",
87
+ description: "Your groups and teams",
88
+ icon: "Users",
89
+ defaultSize: "small",
90
+ removable: !0,
91
+ dataSource: "workspace"
92
+ },
93
+ members: {
94
+ id: "members",
95
+ title: "Members",
96
+ description: "Workspace member overview",
97
+ icon: "UserPlus",
98
+ defaultSize: "small",
99
+ removable: !0,
100
+ dataSource: "workspace"
101
+ },
102
+ systemHealth: {
103
+ id: "systemHealth",
104
+ title: "System Status",
105
+ description: "Service health and availability",
106
+ icon: "HeartPulse",
107
+ defaultSize: "small",
108
+ removable: !0,
109
+ dataSource: "global"
110
+ },
111
+ tips: {
112
+ id: "tips",
113
+ title: "Tips & Resources",
114
+ description: "Getting started tips and documentation links",
115
+ icon: "Lightbulb",
116
+ defaultSize: "small",
117
+ removable: !0,
118
+ dataSource: "static"
119
+ }
120
+ }, t = [
121
+ {
122
+ widgetId: "welcome",
123
+ enabled: !0,
124
+ order: 0,
125
+ size: "large"
126
+ },
127
+ {
128
+ widgetId: "quickActions",
129
+ enabled: !0,
130
+ order: 1,
131
+ size: "medium"
132
+ },
133
+ {
134
+ widgetId: "workspaces",
135
+ enabled: !0,
136
+ order: 2,
137
+ size: "medium"
138
+ },
139
+ {
140
+ widgetId: "projects",
141
+ enabled: !0,
142
+ order: 3,
143
+ size: "medium"
144
+ },
145
+ {
146
+ widgetId: "activity",
147
+ enabled: !0,
148
+ order: 4,
149
+ size: "large"
150
+ },
151
+ {
152
+ widgetId: "calendar",
153
+ enabled: !0,
154
+ order: 5,
155
+ size: "medium"
156
+ },
157
+ {
158
+ widgetId: "workflows",
159
+ enabled: !0,
160
+ order: 6,
161
+ size: "medium"
162
+ },
163
+ {
164
+ widgetId: "tags",
165
+ enabled: !0,
166
+ order: 7,
167
+ size: "small"
168
+ },
169
+ {
170
+ widgetId: "storage",
171
+ enabled: !0,
172
+ order: 8,
173
+ size: "small"
174
+ },
175
+ {
176
+ widgetId: "groups",
177
+ enabled: !0,
178
+ order: 9,
179
+ size: "small"
180
+ },
181
+ {
182
+ widgetId: "members",
183
+ enabled: !0,
184
+ order: 10,
185
+ size: "small"
186
+ },
187
+ {
188
+ widgetId: "systemHealth",
189
+ enabled: !0,
190
+ order: 11,
191
+ size: "small"
192
+ },
193
+ {
194
+ widgetId: "tips",
195
+ enabled: !0,
196
+ order: 12,
197
+ size: "small"
198
+ }
199
+ ];
200
+ function n(n) {
201
+ if (!n || n.length === 0) return t;
202
+ let r = new Set(n.map((e) => e.widgetId)), i = [...n];
203
+ for (let t of Object.values(e)) r.has(t.id) || i.push({
204
+ widgetId: t.id,
205
+ enabled: !1,
206
+ order: i.length,
207
+ size: t.defaultSize
208
+ });
209
+ return i.sort((e, t) => e.order - t.order);
210
+ }
211
+ //#endregion
212
+ export { t as DEFAULT_DASHBOARD_WIDGETS, e as WIDGET_DEFINITIONS, n as getEffectiveWidgets };
213
+
214
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../src/pages/dashboard/config.ts"],"sourcesContent":["/**\n * Dashboard Widget Registry & Default Configuration\n */\nimport type { WidgetConfig, WidgetDefinition } from './types';\n\n// ─── Widget Definitions ───────────────────────────────────────────────────────\n\nexport const WIDGET_DEFINITIONS: Record<string, WidgetDefinition> = {\n welcome: {\n id: 'welcome',\n title: 'Welcome',\n description: 'Greeting and overview statistics',\n icon: 'LayoutDashboard',\n defaultSize: 'large',\n removable: false,\n dataSource: 'global',\n },\n quickActions: {\n id: 'quickActions',\n title: 'Quick Actions',\n description: 'Frequently used actions and shortcuts',\n icon: 'Zap',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'static',\n },\n workspaces: {\n id: 'workspaces',\n title: 'Workspaces',\n description: 'Your workspaces overview and quick access',\n icon: 'Building2',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n },\n projects: {\n id: 'projects',\n title: 'Projects',\n description: 'Recent projects and status breakdown',\n icon: 'FolderKanban',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n },\n activity: {\n id: 'activity',\n title: 'Recent Activity',\n description: 'Timeline of recent activity across modules',\n icon: 'Activity',\n defaultSize: 'large',\n removable: true,\n dataSource: 'workspace',\n },\n calendar: {\n id: 'calendar',\n title: 'Upcoming Events',\n description: 'Next upcoming calendar events',\n icon: 'Calendar',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n },\n workflows: {\n id: 'workflows',\n title: 'Workflows',\n description: 'Active workflow stats and recent runs',\n icon: 'GitBranch',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n },\n tags: {\n id: 'tags',\n title: 'Tags',\n description: 'Popular tags across your workspace',\n icon: 'Tags',\n defaultSize: 'small',\n removable: true,\n dataSource: 'workspace',\n },\n storage: {\n id: 'storage',\n title: 'Storage',\n description: 'Storage usage and file statistics',\n icon: 'HardDrive',\n defaultSize: 'small',\n removable: true,\n dataSource: 'workspace',\n },\n groups: {\n id: 'groups',\n title: 'Groups',\n description: 'Your groups and teams',\n icon: 'Users',\n defaultSize: 'small',\n removable: true,\n dataSource: 'workspace',\n },\n members: {\n id: 'members',\n title: 'Members',\n description: 'Workspace member overview',\n icon: 'UserPlus',\n defaultSize: 'small',\n removable: true,\n dataSource: 'workspace',\n },\n systemHealth: {\n id: 'systemHealth',\n title: 'System Status',\n description: 'Service health and availability',\n icon: 'HeartPulse',\n defaultSize: 'small',\n removable: true,\n dataSource: 'global',\n },\n tips: {\n id: 'tips',\n title: 'Tips & Resources',\n description: 'Getting started tips and documentation links',\n icon: 'Lightbulb',\n defaultSize: 'small',\n removable: true,\n dataSource: 'static',\n },\n};\n\n// ─── Default Widget Layout ────────────────────────────────────────────────────\n\nexport const DEFAULT_DASHBOARD_WIDGETS: WidgetConfig[] = [\n { widgetId: 'welcome', enabled: true, order: 0, size: 'large' },\n { widgetId: 'quickActions', enabled: true, order: 1, size: 'medium' },\n { widgetId: 'workspaces', enabled: true, order: 2, size: 'medium' },\n { widgetId: 'projects', enabled: true, order: 3, size: 'medium' },\n { widgetId: 'activity', enabled: true, order: 4, size: 'large' },\n { widgetId: 'calendar', enabled: true, order: 5, size: 'medium' },\n { widgetId: 'workflows', enabled: true, order: 6, size: 'medium' },\n { widgetId: 'tags', enabled: true, order: 7, size: 'small' },\n { widgetId: 'storage', enabled: true, order: 8, size: 'small' },\n { widgetId: 'groups', enabled: true, order: 9, size: 'small' },\n { widgetId: 'members', enabled: true, order: 10, size: 'small' },\n { widgetId: 'systemHealth', enabled: true, order: 11, size: 'small' },\n { widgetId: 'tips', enabled: true, order: 12, size: 'small' },\n];\n\n/**\n * Get the effective widget configuration, merging user prefs with defaults.\n */\nexport function getEffectiveWidgets(userPrefs: WidgetConfig[] | null | undefined): WidgetConfig[] {\n if (!userPrefs || userPrefs.length === 0) {\n return DEFAULT_DASHBOARD_WIDGETS;\n }\n\n // Ensure all defined widgets exist in user prefs (add any new ones as disabled)\n const userWidgetIds = new Set(userPrefs.map((w) => w.widgetId));\n const merged = [...userPrefs];\n\n for (const def of Object.values(WIDGET_DEFINITIONS)) {\n if (!userWidgetIds.has(def.id)) {\n merged.push({\n widgetId: def.id,\n enabled: false,\n order: merged.length,\n size: def.defaultSize,\n });\n }\n }\n\n return merged.sort((a, b) => a.order - b.order);\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { WorkspaceDashboardData, GlobalDashboardData } from '../types';
2
+
3
+ export declare function useProjectsDashboardData(authToken?: string | null): import('@tanstack/react-query').UseQueryResult<{
4
+ items: import('../types').ProjectSummary[];
5
+ total: number;
6
+ }, Error>;
7
+ export declare function useWorkspaceDashboardData(authToken?: string | null): import('@tanstack/react-query').UseQueryResult<WorkspaceDashboardData, Error>;
8
+ export declare function useGlobalDashboardData(authToken?: string | null): import('@tanstack/react-query').UseQueryResult<GlobalDashboardData, Error>;
9
+ //# sourceMappingURL=useDashboardData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDashboardData.d.ts","sourceRoot":"","sources":["../../../../src/pages/dashboard/hooks/useDashboardData.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAM5E,wBAAgB,wBAAwB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;;;UAwBjE;AAED,wBAAgB,yBAAyB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,iFAiElE;AAED,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,8EAkD/D"}
@@ -0,0 +1,118 @@
1
+ import { DashboardProjectsDocument as e, DashboardWorkspaceDataDocument as t } from "../../../generated/wspace-operations.js";
2
+ import { DashboardGlobalDataDocument as n } from "../../../generated/global-operations.js";
3
+ import { useActiveContext as r } from "@burdenoff/fe-libs/shared/providers/shell";
4
+ import { useQuery as i } from "@tanstack/react-query";
5
+ import { print as a } from "graphql";
6
+ import { graphqlFetch as o } from "@burdenoff/fe-libs/shared/graphql";
7
+ //#region src/pages/dashboard/hooks/useDashboardData.ts
8
+ var s = 1024 ** 3;
9
+ function c(t) {
10
+ let { workspaceId: n } = r();
11
+ return i({
12
+ queryKey: [
13
+ "dashboard",
14
+ "projects",
15
+ n
16
+ ],
17
+ enabled: !!t && !!n,
18
+ queryFn: async () => (await o({
19
+ gateway: "workspace",
20
+ authToken: t || void 0,
21
+ workspaceToken: !0,
22
+ query: a(e),
23
+ variables: { filter: { workspaceId: n } }
24
+ })).data?.projects ?? {
25
+ items: [],
26
+ total: 0
27
+ },
28
+ staleTime: 120 * 1e3,
29
+ gcTime: 300 * 1e3,
30
+ retry: 1,
31
+ refetchOnWindowFocus: !0
32
+ });
33
+ }
34
+ function l(e) {
35
+ let { workspaceId: n } = r();
36
+ return i({
37
+ queryKey: [
38
+ "dashboard",
39
+ "workspace",
40
+ n
41
+ ],
42
+ enabled: !!e && !!n,
43
+ queryFn: async () => {
44
+ let n = (await o({
45
+ gateway: "workspace",
46
+ authToken: e || void 0,
47
+ workspaceToken: !0,
48
+ query: a(t)
49
+ })).data, r = n?.workspaceResourceUsage ? {
50
+ usedBytes: Math.round(n.workspaceResourceUsage.currentStorageGb * s),
51
+ totalBytes: Math.round((n.workspaceResourceLimits?.maxStorageGb ?? 0) * s),
52
+ fileCount: null
53
+ } : null;
54
+ return {
55
+ workspaces: {
56
+ items: [],
57
+ total: 0
58
+ },
59
+ projects: {
60
+ items: [],
61
+ total: 0
62
+ },
63
+ recentActivities: n?.getRecentActivities ?? [],
64
+ upcomingEvents: n?.upcomingEvents ?? [],
65
+ tags: n?.getTags ?? {
66
+ items: [],
67
+ total: 0
68
+ },
69
+ groups: {
70
+ items: (n?.myGroups?.edges ?? []).map((e) => ({
71
+ id: e.node.id,
72
+ name: e.node.name,
73
+ description: e.node.description
74
+ })),
75
+ totalCount: n?.myGroups?.totalCount ?? 0
76
+ },
77
+ workflowStats: n?.dashboardSummary ?? null,
78
+ storageUsage: r
79
+ };
80
+ },
81
+ staleTime: 120 * 1e3,
82
+ gcTime: 300 * 1e3,
83
+ retry: 1,
84
+ refetchOnWindowFocus: !0
85
+ });
86
+ }
87
+ function u(e) {
88
+ return i({
89
+ queryKey: ["dashboard", "global"],
90
+ enabled: !!e,
91
+ queryFn: async () => {
92
+ let t = (await o({
93
+ gateway: "global",
94
+ authToken: e || void 0,
95
+ query: a(n)
96
+ })).data;
97
+ return {
98
+ currentUser: t?.currentUser ?? null,
99
+ dashboardPreferences: t?.myDashboardPreferences ? t.myDashboardPreferences : null,
100
+ workspaces: t?.myWorkspaces ?? {
101
+ items: [],
102
+ total: 0
103
+ },
104
+ organizations: t?.myOrganizations ?? {
105
+ items: [],
106
+ total: 0
107
+ }
108
+ };
109
+ },
110
+ staleTime: 300 * 1e3,
111
+ gcTime: 600 * 1e3,
112
+ retry: 1
113
+ });
114
+ }
115
+ //#endregion
116
+ export { u as useGlobalDashboardData, c as useProjectsDashboardData, l as useWorkspaceDashboardData };
117
+
118
+ //# sourceMappingURL=useDashboardData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDashboardData.js","names":[],"sources":["../../../../src/pages/dashboard/hooks/useDashboardData.ts"],"sourcesContent":["/**\n * Dashboard Data Hooks\n *\n * Three parallel queries: workspace gateway (features + projects), global gateway.\n * Uses graphqlFetch from fe-libs with React Query for caching.\n *\n * IMPORTANT: Workspace/org/member data lives in the global tenant service\n * (global gateway), NOT in the workspace service (workspace gateway).\n * The workspace gateway is used for workspace-scoped features like\n * activity, calendar, tags, groups, projects, and workflows.\n *\n * All GraphQL operations are defined in src/operations/ and generated via codegen.\n * Document nodes are imported and converted to strings via print() for graphqlFetch.\n */\nimport { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useActiveContext } from '@burdenoff/fe-libs/shared/providers/shell';\nimport {\n DashboardProjectsDocument,\n DashboardWorkspaceDataDocument,\n} from '../../../generated/wspace-operations';\nimport { DashboardGlobalDataDocument } from '../../../generated/global-operations';\nimport type { WorkspaceDashboardData, GlobalDashboardData } from '../types';\n\nconst BYTES_PER_GB = 1024 ** 3;\n\n// ─── Hooks ────────────────────────────────────────────────────────────────────\n\nexport function useProjectsDashboardData(authToken?: string | null) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'projects', workspaceId],\n enabled: !!authToken && !!workspaceId,\n queryFn: async (): Promise<WorkspaceDashboardData['projects']> => {\n const result = await graphqlFetch<{\n projects: WorkspaceDashboardData['projects'];\n }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: print(DashboardProjectsDocument),\n variables: { filter: { workspaceId } },\n });\n\n return result.data?.projects ?? { items: [], total: 0 };\n },\n staleTime: 2 * 60 * 1000,\n gcTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: true,\n });\n}\n\nexport function useWorkspaceDashboardData(authToken?: string | null) {\n const { workspaceId } = useActiveContext();\n\n return useQuery({\n queryKey: ['dashboard', 'workspace', workspaceId],\n enabled: !!authToken && !!workspaceId,\n queryFn: async (): Promise<WorkspaceDashboardData> => {\n const result = await graphqlFetch<{\n getRecentActivities: WorkspaceDashboardData['recentActivities'];\n upcomingEvents: WorkspaceDashboardData['upcomingEvents'];\n getTags: WorkspaceDashboardData['tags'];\n myGroups: {\n edges: Array<{ node: { id: string; name: string; description?: string } }>;\n totalCount: number;\n };\n dashboardSummary: WorkspaceDashboardData['workflowStats'];\n workspaceResourceUsage: { currentStorageGb: number } | null;\n workspaceResourceLimits: { maxStorageGb?: number | null } | null;\n }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n workspaceToken: true,\n query: print(DashboardWorkspaceDataDocument),\n });\n\n // Gracefully handle partial failures — the gateway may return data for some\n // subgraphs and errors for others due to individual services being down.\n const data = result.data;\n const storageUsage = data?.workspaceResourceUsage\n ? {\n usedBytes: Math.round(data.workspaceResourceUsage.currentStorageGb * BYTES_PER_GB),\n totalBytes: Math.round(\n (data.workspaceResourceLimits?.maxStorageGb ?? 0) * BYTES_PER_GB\n ),\n fileCount: null,\n }\n : null;\n\n return {\n // Workspace data comes from the global gateway (see useGlobalDashboardData)\n // and is merged in at the DashboardPage level.\n workspaces: { items: [], total: 0 },\n // Projects fetched separately via useProjectsDashboardData to avoid\n // being poisoned by other subgraph errors in the combined query.\n projects: { items: [], total: 0 },\n recentActivities: data?.getRecentActivities ?? [],\n upcomingEvents: data?.upcomingEvents ?? [],\n tags: data?.getTags ?? { items: [], total: 0 },\n groups: {\n items: (data?.myGroups?.edges ?? []).map((e) => ({\n id: e.node.id,\n name: e.node.name,\n description: e.node.description,\n })),\n totalCount: data?.myGroups?.totalCount ?? 0,\n },\n workflowStats: data?.dashboardSummary ?? null,\n storageUsage,\n };\n },\n staleTime: 2 * 60 * 1000, // 2 minutes — dashboard data changes moderately\n gcTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: true,\n });\n}\n\nexport function useGlobalDashboardData(authToken?: string | null) {\n return useQuery({\n queryKey: ['dashboard', 'global'],\n enabled: !!authToken,\n queryFn: async (): Promise<GlobalDashboardData> => {\n const result = await graphqlFetch<{\n currentUser: GlobalDashboardData['currentUser'];\n myDashboardPreferences: Record<string, unknown> | null;\n myWorkspaces: {\n items: Array<{\n id: string;\n name: string;\n status: string;\n type: string;\n createdAt: string;\n memberCount: number;\n }>;\n total: number;\n };\n myOrganizations: {\n items: Array<{\n id: string;\n name: string;\n status: string;\n type: string;\n createdAt: string;\n }>;\n total: number;\n };\n }>({\n gateway: 'global',\n authToken: authToken || undefined,\n query: print(DashboardGlobalDataDocument),\n });\n\n const data = result.data;\n\n return {\n currentUser: data?.currentUser ?? null,\n dashboardPreferences: data?.myDashboardPreferences\n ? (data.myDashboardPreferences as unknown as GlobalDashboardData['dashboardPreferences'])\n : null,\n workspaces: data?.myWorkspaces ?? { items: [], total: 0 },\n organizations: data?.myOrganizations ?? { items: [], total: 0 },\n };\n },\n staleTime: 5 * 60 * 1000, // 5 minutes — user info and prefs change rarely\n gcTime: 10 * 60 * 1000,\n retry: 1,\n });\n}\n"],"mappings":";;;;;;;AAyBA,IAAM,IAAe,QAAQ;AAI7B,SAAgB,EAAyB,GAA2B;CAClE,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAY;GAAY;EAChD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC;EAC1B,SAAS,aACQ,MAAM,EAElB;GACD,SAAS;GACT,WAAW,KAAa,KAAA;GACxB,gBAAgB;GAChB,OAAO,EAAM,EAA0B;GACvC,WAAW,EAAE,QAAQ,EAAE,gBAAa,EAAE;GACvC,CAAC,EAEY,MAAM,YAAY;GAAE,OAAO,EAAE;GAAE,OAAO;GAAG;EAEzD,WAAW,MAAS;EACpB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AAGJ,SAAgB,EAA0B,GAA2B;CACnE,IAAM,EAAE,mBAAgB,GAAkB;AAE1C,QAAO,EAAS;EACd,UAAU;GAAC;GAAa;GAAa;GAAY;EACjD,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC;EAC1B,SAAS,YAA6C;GAqBpD,IAAM,KApBS,MAAM,EAWlB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,gBAAgB;IAChB,OAAO,EAAM,EAA+B;IAC7C,CAAC,EAIkB,MACd,IAAe,GAAM,yBACvB;IACE,WAAW,KAAK,MAAM,EAAK,uBAAuB,mBAAmB,EAAa;IAClF,YAAY,KAAK,OACd,EAAK,yBAAyB,gBAAgB,KAAK,EACrD;IACD,WAAW;IACZ,GACD;AAEJ,UAAO;IAGL,YAAY;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAGnC,UAAU;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IACjC,kBAAkB,GAAM,uBAAuB,EAAE;IACjD,gBAAgB,GAAM,kBAAkB,EAAE;IAC1C,MAAM,GAAM,WAAW;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAC9C,QAAQ;KACN,QAAQ,GAAM,UAAU,SAAS,EAAE,EAAE,KAAK,OAAO;MAC/C,IAAI,EAAE,KAAK;MACX,MAAM,EAAE,KAAK;MACb,aAAa,EAAE,KAAK;MACrB,EAAE;KACH,YAAY,GAAM,UAAU,cAAc;KAC3C;IACD,eAAe,GAAM,oBAAoB;IACzC;IACD;;EAEH,WAAW,MAAS;EACpB,QAAQ,MAAS;EACjB,OAAO;EACP,sBAAsB;EACvB,CAAC;;AAGJ,SAAgB,EAAuB,GAA2B;AAChE,QAAO,EAAS;EACd,UAAU,CAAC,aAAa,SAAS;EACjC,SAAS,CAAC,CAAC;EACX,SAAS,YAA0C;GA+BjD,IAAM,KA9BS,MAAM,EAwBlB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA4B;IAC1C,CAAC,EAEkB;AAEpB,UAAO;IACL,aAAa,GAAM,eAAe;IAClC,sBAAsB,GAAM,yBACvB,EAAK,yBACN;IACJ,YAAY,GAAM,gBAAgB;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IACzD,eAAe,GAAM,mBAAmB;KAAE,OAAO,EAAE;KAAE,OAAO;KAAG;IAChE;;EAEH,WAAW,MAAS;EACpB,QAAQ,MAAU;EAClB,OAAO;EACR,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { WidgetConfig, DashboardPreferences } from '../types';
2
+
3
+ export declare function useUpdateDashboardPreferences(authToken?: string | null): import('@tanstack/react-query').UseMutationResult<DashboardPreferences, Error, WidgetConfig[], unknown>;
4
+ //# sourceMappingURL=useDashboardPreferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDashboardPreferences.d.ts","sourceRoot":"","sources":["../../../../src/pages/dashboard/hooks/useDashboardPreferences.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAEnE,wBAAgB,6BAA6B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,2GAkCtE"}
@@ -0,0 +1,32 @@
1
+ import { UpdateDashboardPreferencesDocument as e } from "../../../generated/global-operations.js";
2
+ import { useMutation as t, useQueryClient as n } from "@tanstack/react-query";
3
+ import { print as r } from "graphql";
4
+ import { graphqlFetch as i } from "@burdenoff/fe-libs/shared/graphql";
5
+ //#region src/pages/dashboard/hooks/useDashboardPreferences.ts
6
+ function a(a) {
7
+ let o = n();
8
+ return t({
9
+ mutationFn: async (t) => {
10
+ let n = await i({
11
+ gateway: "global",
12
+ authToken: a || void 0,
13
+ query: r(e),
14
+ variables: { input: { widgets: t.map((e) => ({
15
+ widgetId: e.widgetId,
16
+ enabled: e.enabled,
17
+ order: e.order,
18
+ size: e.size
19
+ })) } }
20
+ });
21
+ if (n.errors?.length) throw Error(n.errors[0]?.message || "Failed to save preferences");
22
+ return n.data.updateMyDashboardPreferences;
23
+ },
24
+ onSuccess: () => {
25
+ o.invalidateQueries({ queryKey: ["dashboard", "global"] });
26
+ }
27
+ });
28
+ }
29
+ //#endregion
30
+ export { a as useUpdateDashboardPreferences };
31
+
32
+ //# sourceMappingURL=useDashboardPreferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDashboardPreferences.js","names":[],"sources":["../../../../src/pages/dashboard/hooks/useDashboardPreferences.ts"],"sourcesContent":["/**\n * Dashboard Preferences Hook\n *\n * Manages dashboard widget layout preferences via the global gateway.\n * GraphQL operation defined in src/operations/dashboard/mutations/dashboard.graphql\n */\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { UpdateDashboardPreferencesDocument } from '../../../generated/global-operations';\nimport type { WidgetConfig, DashboardPreferences } from '../types';\n\nexport function useUpdateDashboardPreferences(authToken?: string | null) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async (widgets: WidgetConfig[]): Promise<DashboardPreferences> => {\n const result = await graphqlFetch<{\n updateMyDashboardPreferences: DashboardPreferences;\n }>({\n gateway: 'global',\n authToken: authToken || undefined,\n query: print(UpdateDashboardPreferencesDocument),\n variables: {\n input: {\n widgets: widgets.map((w) => ({\n widgetId: w.widgetId,\n enabled: w.enabled,\n order: w.order,\n size: w.size,\n })),\n },\n },\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'Failed to save preferences');\n }\n\n return result.data!.updateMyDashboardPreferences;\n },\n onSuccess: () => {\n // Invalidate global dashboard data so the preferences are refreshed\n queryClient.invalidateQueries({ queryKey: ['dashboard', 'global'] });\n },\n });\n}\n"],"mappings":";;;;;AAYA,SAAgB,EAA8B,GAA2B;CACvE,IAAM,IAAc,GAAgB;AAEpC,QAAO,EAAY;EACjB,YAAY,OAAO,MAA2D;GAC5E,IAAM,IAAS,MAAM,EAElB;IACD,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAAmC;IAChD,WAAW,EACT,OAAO,EACL,SAAS,EAAQ,KAAK,OAAO;KAC3B,UAAU,EAAE;KACZ,SAAS,EAAE;KACX,OAAO,EAAE;KACT,MAAM,EAAE;KACT,EAAE,EACJ,EACF;IACF,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,6BAA6B;AAG5E,UAAO,EAAO,KAAM;;EAEtB,iBAAiB;AAEf,KAAY,kBAAkB,EAAE,UAAU,CAAC,aAAa,SAAS,EAAE,CAAC;;EAEvE,CAAC"}