@burdenoff/microfe-workspaces 2026.802.1 → 2026.829.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/generated/global-operations.js +44 -1
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/wspace-operations.js +18 -18
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/hooks/useWorkspaceMutations.js +84 -61
- package/dist/hooks/useWorkspaceMutations.js.map +1 -1
- package/dist/pages/MembersListPage.js +3 -3
- package/dist/pages/MembersListPage.js.map +1 -1
- package/dist/pages/ProjectsListPage.js +3 -3
- package/dist/pages/ProjectsListPage.js.map +1 -1
- package/dist/pages/WorkspaceDetailPage.js +152 -114
- package/dist/pages/WorkspaceDetailPage.js.map +1 -1
- package/dist/pages/WorkspaceInvitePage.js +2 -2
- package/dist/pages/WorkspaceInvitePage.js.map +1 -1
- package/dist/pages/dashboard/DashboardCustomizer.js +62 -62
- package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -1
- package/dist/pages/dashboard/DashboardPage.js +88 -69
- package/dist/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/pages/dashboard/config.js +77 -1
- package/dist/pages/dashboard/config.js.map +1 -1
- package/dist/pages/dashboard/widgets/AgentsWidget.js +56 -54
- package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/GroupsWidget.js +29 -31
- package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/MembersWidget.js +33 -33
- package/dist/pages/dashboard/widgets/MembersWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/ProjectsWidget.js +42 -44
- package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js +171 -161
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js +54 -44
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/SessionsWidget.js +57 -41
- package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/StorageWidget.js +52 -54
- package/dist/pages/dashboard/widgets/StorageWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TagCloudWidget.js +28 -30
- package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TipsWidget.js +141 -131
- package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +46 -40
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/VibesWidget.js +44 -34
- package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WelcomeWidget.js +43 -41
- package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowRunsWidget.js +68 -62
- package/dist/pages/dashboard/widgets/WorkflowRunsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +50 -44
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowsOverviewWidget.js +59 -49
- package/dist/pages/dashboard/widgets/WorkflowsOverviewWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js +35 -33
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardCustomizer.js","names":[],"sources":["../../../src/pages/dashboard/DashboardCustomizer.tsx"],"sourcesContent":["/**\n * DashboardCustomizer — Sheet overlay for customizing dashboard widgets.\n *\n * Allows users to toggle widgets on/off, reorder them, and save their layout.\n */\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetFooter,\n Button,\n Switch,\n Badge,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowUp, ArrowDown, RotateCcw, Save, Loader2, GripVertical } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig } from './types';\nimport {\n WIDGET_DEFINITIONS,\n DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT,\n DEFAULT_DASHBOARD_WIDGETS,\n isWidgetAvailable,\n} from './config';\nimport { nativeImpact } from '../../utils/nativeBridge';\n\ninterface DashboardCustomizerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n widgets: WidgetConfig[];\n onSave: (widgets: WidgetConfig[]) => Promise<void>;\n isSaving: boolean;\n productId?: string;\n}\n\nexport function DashboardCustomizer({\n open,\n onOpenChange,\n widgets,\n onSave,\n isSaving,\n productId = 'workspaces',\n}: DashboardCustomizerProps) {\n const { t } = useI18n();\n\n const [localWidgets, setLocalWidgets] = useState<WidgetConfig[]>(widgets);\n const [hasChanges, setHasChanges] = useState(false);\n\n // Sync local state when sheet opens or widgets prop changes while open\n useEffect(() => {\n if (open) {\n setLocalWidgets([...widgets]);\n setHasChanges(false);\n }\n }, [open, widgets]);\n\n const toggleWidget = useCallback((widgetId: string) => {\n setLocalWidgets((prev) =>\n prev.map((w) => (w.widgetId === widgetId ? { ...w, enabled: !w.enabled } : w))\n );\n setHasChanges(true);\n }, []);\n\n const moveWidget = useCallback((widgetId: string, direction: 'up' | 'down') => {\n setLocalWidgets((prev) => {\n const sorted = [...prev].sort((a, b) => a.order - b.order);\n const idx = sorted.findIndex((w) => w.widgetId === widgetId);\n if (idx < 0) return prev;\n\n const swapIdx = direction === 'up' ? idx - 1 : idx + 1;\n if (swapIdx < 0 || swapIdx >= sorted.length) return prev;\n\n // Swap orders\n const tempOrder = sorted[idx].order;\n sorted[idx] = { ...sorted[idx], order: sorted[swapIdx].order };\n sorted[swapIdx] = { ...sorted[swapIdx], order: tempOrder };\n\n return sorted;\n });\n setHasChanges(true);\n }, []);\n\n const resetToDefaults = useCallback(() => {\n const defaults = DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT[productId] ?? DEFAULT_DASHBOARD_WIDGETS;\n setLocalWidgets([...defaults]);\n setHasChanges(true);\n }, [productId]);\n\n const handleSave = useCallback(async () => {\n await onSave(localWidgets);\n setHasChanges(false);\n onOpenChange(false);\n }, [localWidgets, onSave, onOpenChange]);\n\n const sorted = [...localWidgets].sort((a, b) => a.order - b.order);\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent className=\"w-full sm:max-w-md overflow-y-auto\" side=\"right\">\n <SheetHeader>\n <SheetTitle>\n {tWithFallback(t, 'dashboardCustomizer.title', 'Customize Dashboard')}\n </SheetTitle>\n <SheetDescription>\n {tWithFallback(\n t,\n 'dashboardCustomizer.description',\n 'Toggle widgets on or off and reorder them to personalize your dashboard.'\n )}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"py-4 space-y-1\">\n {sorted.map((widget, idx) => {\n const definition = WIDGET_DEFINITIONS[widget.widgetId];\n if (!definition) return null;\n if (!isWidgetAvailable(definition, productId)) return null;\n\n return (\n <div\n key={widget.widgetId}\n className={`flex items-center gap-3 p-3 rounded-lg border transition-colors ${\n widget.enabled\n ? 'border-border-default bg-bg-surface'\n : 'border-transparent bg-bg-sunken/30 opacity-60'\n }`}\n >\n <GripVertical className=\"size-4 text-text-secondary shrink-0\" />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {definition.title}\n </span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {definition.defaultSize}\n </Badge>\n </div>\n <p className=\"text-xs text-text-secondary truncate\">{definition.description}</p>\n </div>\n\n <div className=\"flex items-center gap-1 shrink-0\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 p-0\"\n disabled={idx === 0}\n onClick={() => moveWidget(widget.widgetId, 'up')}\n >\n <ArrowUp className=\"size-3\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 p-0\"\n disabled={idx === sorted.length - 1}\n onClick={() => moveWidget(widget.widgetId, 'down')}\n >\n <ArrowDown className=\"size-3\" />\n </Button>\n <Switch\n checked={widget.enabled}\n onCheckedChange={() => {\n void nativeImpact('medium');\n toggleWidget(widget.widgetId);\n }}\n disabled={!definition.removable}\n className=\"ml-1\"\n />\n </div>\n </div>\n );\n })}\n </div>\n\n <Separator />\n\n <SheetFooter className=\"flex-row gap-2 pt-4\">\n <Button variant=\"outline\" size=\"sm\" onClick={resetToDefaults} className=\"flex-1\">\n <RotateCcw className=\"size-3 mr-1.5\" />\n {tWithFallback(t, 'dashboardCustomizer.resetToDefaults', 'Reset to defaults')}\n </Button>\n <Button\n size=\"sm\"\n onClick={handleSave}\n disabled={!hasChanges || isSaving}\n className=\"flex-1\"\n >\n {isSaving ? (\n <Loader2 className=\"size-3 mr-1.5 animate-spin\" />\n ) : (\n <Save className=\"size-3 mr-1.5\" />\n )}\n {tWithFallback(t, 'dashboardCustomizer.saveLayout', 'Save layout')}\n </Button>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardCustomizer.js","names":[],"sources":["../../../src/pages/dashboard/DashboardCustomizer.tsx"],"sourcesContent":["/**\n * DashboardCustomizer — Sheet overlay for customizing dashboard widgets.\n *\n * Allows users to toggle widgets on/off, reorder them, and save their layout.\n */\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n Sheet,\n SheetContent,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n SheetFooter,\n Button,\n Switch,\n Badge,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowUp, ArrowDown, RotateCcw, Save, Loader2, GripVertical } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig } from './types';\nimport {\n WIDGET_DEFINITIONS,\n DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT,\n DEFAULT_DASHBOARD_WIDGETS,\n isWidgetAvailable,\n resolveWidgetCopy,\n} from './config';\nimport { nativeImpact } from '../../utils/nativeBridge';\n\ninterface DashboardCustomizerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n widgets: WidgetConfig[];\n onSave: (widgets: WidgetConfig[]) => Promise<void>;\n isSaving: boolean;\n productId?: string;\n}\n\nexport function DashboardCustomizer({\n open,\n onOpenChange,\n widgets,\n onSave,\n isSaving,\n productId = 'workspaces',\n}: DashboardCustomizerProps) {\n const { t } = useI18n();\n // Widget titles/descriptions live in module-scope WIDGET_DEFINITIONS, so they\n // are translated here at render time with literal keys. [BOFF-5997]\n const trLiteral = (key: string, fallback: string): string => tWithFallback(t, key, fallback);\n\n const [localWidgets, setLocalWidgets] = useState<WidgetConfig[]>(widgets);\n const [hasChanges, setHasChanges] = useState(false);\n\n // Sync local state when sheet opens or widgets prop changes while open\n useEffect(() => {\n if (open) {\n setLocalWidgets([...widgets]);\n setHasChanges(false);\n }\n }, [open, widgets]);\n\n const toggleWidget = useCallback((widgetId: string) => {\n setLocalWidgets((prev) =>\n prev.map((w) => (w.widgetId === widgetId ? { ...w, enabled: !w.enabled } : w))\n );\n setHasChanges(true);\n }, []);\n\n const moveWidget = useCallback((widgetId: string, direction: 'up' | 'down') => {\n setLocalWidgets((prev) => {\n const sorted = [...prev].sort((a, b) => a.order - b.order);\n const idx = sorted.findIndex((w) => w.widgetId === widgetId);\n if (idx < 0) return prev;\n\n const swapIdx = direction === 'up' ? idx - 1 : idx + 1;\n if (swapIdx < 0 || swapIdx >= sorted.length) return prev;\n\n // Swap orders\n const tempOrder = sorted[idx].order;\n sorted[idx] = { ...sorted[idx], order: sorted[swapIdx].order };\n sorted[swapIdx] = { ...sorted[swapIdx], order: tempOrder };\n\n return sorted;\n });\n setHasChanges(true);\n }, []);\n\n const resetToDefaults = useCallback(() => {\n const defaults = DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT[productId] ?? DEFAULT_DASHBOARD_WIDGETS;\n setLocalWidgets([...defaults]);\n setHasChanges(true);\n }, [productId]);\n\n const handleSave = useCallback(async () => {\n await onSave(localWidgets);\n setHasChanges(false);\n onOpenChange(false);\n }, [localWidgets, onSave, onOpenChange]);\n\n const sorted = [...localWidgets].sort((a, b) => a.order - b.order);\n\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent className=\"w-full sm:max-w-md overflow-y-auto\" side=\"right\">\n <SheetHeader>\n <SheetTitle>\n {tWithFallback(t, 'dashboardCustomizer.title', 'Customize Dashboard')}\n </SheetTitle>\n <SheetDescription>\n {tWithFallback(\n t,\n 'dashboardCustomizer.description',\n 'Toggle widgets on or off and reorder them to personalize your dashboard.'\n )}\n </SheetDescription>\n </SheetHeader>\n\n <div className=\"py-4 space-y-1\">\n {sorted.map((widget, idx) => {\n const definition = WIDGET_DEFINITIONS[widget.widgetId];\n if (!definition) return null;\n if (!isWidgetAvailable(definition, productId)) return null;\n\n return (\n <div\n key={widget.widgetId}\n className={`flex items-center gap-3 p-3 rounded-lg border transition-colors ${\n widget.enabled\n ? 'border-border-default bg-bg-surface'\n : 'border-transparent bg-bg-sunken/30 opacity-60'\n }`}\n >\n <GripVertical className=\"size-4 text-text-secondary shrink-0\" />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">\n {resolveWidgetCopy(trLiteral, definition).title}\n </span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {definition.defaultSize}\n </Badge>\n </div>\n <p className=\"text-xs text-text-secondary truncate\">\n {resolveWidgetCopy(trLiteral, definition).description}\n </p>\n </div>\n\n <div className=\"flex items-center gap-1 shrink-0\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 p-0\"\n disabled={idx === 0}\n onClick={() => moveWidget(widget.widgetId, 'up')}\n >\n <ArrowUp className=\"size-3\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"size-7 p-0\"\n disabled={idx === sorted.length - 1}\n onClick={() => moveWidget(widget.widgetId, 'down')}\n >\n <ArrowDown className=\"size-3\" />\n </Button>\n <Switch\n checked={widget.enabled}\n onCheckedChange={() => {\n void nativeImpact('medium');\n toggleWidget(widget.widgetId);\n }}\n disabled={!definition.removable}\n className=\"ml-1\"\n />\n </div>\n </div>\n );\n })}\n </div>\n\n <Separator />\n\n <SheetFooter className=\"flex-row gap-2 pt-4\">\n <Button variant=\"outline\" size=\"sm\" onClick={resetToDefaults} className=\"flex-1\">\n <RotateCcw className=\"size-3 mr-1.5\" />\n {tWithFallback(t, 'dashboardCustomizer.resetToDefaults', 'Reset to defaults')}\n </Button>\n <Button\n size=\"sm\"\n onClick={handleSave}\n disabled={!hasChanges || isSaving}\n className=\"flex-1\"\n >\n {isSaving ? (\n <Loader2 className=\"size-3 mr-1.5 animate-spin\" />\n ) : (\n <Save className=\"size-3 mr-1.5\" />\n )}\n {tWithFallback(t, 'dashboardCustomizer.saveLayout', 'Save layout')}\n </Button>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,43 +1,62 @@
|
|
|
1
1
|
import { useWorkspacesPageView as e } from "../../hooks/useWorkspacesPageView.js";
|
|
2
2
|
import { useGlobalDashboardData as t, useProjectsDashboardData as n, useVibecontrolsDashboardData as r, useWorkspaceDashboardData as i } from "./hooks/useDashboardData.js";
|
|
3
|
-
import { useUpdateDashboardPreferences as
|
|
4
|
-
import { getEffectiveWidgets as
|
|
5
|
-
import { DashboardGrid as
|
|
6
|
-
import { DashboardCustomizer as
|
|
7
|
-
import { useCallback as
|
|
8
|
-
import { AlertCircle as
|
|
9
|
-
import { Fragment as
|
|
10
|
-
import { AuroraBackground as
|
|
11
|
-
import { useI18n as
|
|
12
|
-
import { PageHeader as
|
|
3
|
+
import { useUpdateDashboardPreferences as ee } from "./hooks/useDashboardPreferences.js";
|
|
4
|
+
import { getEffectiveWidgets as a } from "./config.js";
|
|
5
|
+
import { DashboardGrid as te } from "./DashboardGrid.js";
|
|
6
|
+
import { DashboardCustomizer as o } from "./DashboardCustomizer.js";
|
|
7
|
+
import { useCallback as s, useMemo as c, useState as l } from "react";
|
|
8
|
+
import { AlertCircle as u, Building2 as d, GitBranch as f, Loader2 as p, RefreshCw as m, Settings2 as ne, Sparkles as h } from "lucide-react";
|
|
9
|
+
import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
10
|
+
import { AuroraBackground as y, Button as b, GradientText as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
|
|
11
|
+
import { useI18n as C } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
12
|
+
import { PageHeader as w } from "@burdenoff/fe-libs/chrome";
|
|
13
13
|
//#region src/pages/dashboard/DashboardPage.tsx
|
|
14
|
-
var
|
|
14
|
+
var T = {
|
|
15
15
|
workspaces: {
|
|
16
16
|
noun: "Workspaces",
|
|
17
17
|
subtitle: "Your workspace overview at a glance",
|
|
18
18
|
purpose: "This is your home base — a single glance across everything that matters: your workspaces and projects, recent activity, upcoming events and live status. Use Customize to choose which cards appear and how they are arranged, and click any card to dive into the full view.",
|
|
19
|
-
Icon:
|
|
19
|
+
Icon: d
|
|
20
20
|
},
|
|
21
21
|
vibecontrols: {
|
|
22
22
|
noun: "VibeControls",
|
|
23
23
|
subtitle: "Your workspace at a glance",
|
|
24
24
|
purpose: "This is your home base for this workspace — check on recent vibes, active sessions, and your agent fleet, then jump straight into whatever needs you. Use Customize to choose which cards appear and how they are arranged.",
|
|
25
|
-
Icon:
|
|
25
|
+
Icon: h
|
|
26
26
|
},
|
|
27
27
|
fluidgrids: {
|
|
28
28
|
noun: "FluidGrids",
|
|
29
29
|
subtitle: "Your workflow automation at a glance",
|
|
30
30
|
purpose: "This is your home base — track workflow health, recent runs, and team activity, then jump straight into building or debugging. Use Customize to choose which cards appear and how they are arranged.",
|
|
31
|
-
Icon:
|
|
31
|
+
Icon: f
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
|
-
function
|
|
34
|
+
function E(e, t, n) {
|
|
35
|
+
switch (t) {
|
|
36
|
+
case "vibecontrols": return {
|
|
37
|
+
noun: e("dashboard.titleNoun.vibecontrols", n.noun),
|
|
38
|
+
subtitle: e("dashboard.subtitle.vibecontrols", n.subtitle),
|
|
39
|
+
purpose: e("dashboard.purpose.vibecontrols", n.purpose)
|
|
40
|
+
};
|
|
41
|
+
case "fluidgrids": return {
|
|
42
|
+
noun: e("dashboard.titleNoun.fluidgrids", n.noun),
|
|
43
|
+
subtitle: e("dashboard.subtitle.fluidgrids", n.subtitle),
|
|
44
|
+
purpose: e("dashboard.purpose.fluidgrids", n.purpose)
|
|
45
|
+
};
|
|
46
|
+
default: return {
|
|
47
|
+
noun: e("dashboard.titleNoun.workspaces", n.noun),
|
|
48
|
+
subtitle: e("dashboard.subtitle.workspaces", n.subtitle),
|
|
49
|
+
purpose: e("dashboard.purpose.workspaces", n.purpose)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function D({ navigate: d, authToken: f, currentUser: h, productId: D = "workspaces" }) {
|
|
35
54
|
e("workspaces.dashboard");
|
|
36
|
-
let { t:
|
|
37
|
-
let n =
|
|
55
|
+
let { t: O } = C(), k = (e, t) => {
|
|
56
|
+
let n = O(e);
|
|
38
57
|
return n === e ? t : n;
|
|
39
|
-
}, [
|
|
40
|
-
...
|
|
58
|
+
}, [re, A] = l(!1), j = T[D] ?? T.workspaces, M = E(k, D, j), N = j.Icon, { data: P, isLoading: F, error: I, refetch: L } = i(f), { data: R, isLoading: z, error: B, refetch: V } = t(f), { data: H, isLoading: U, refetch: W } = n(f), G = D === "vibecontrols", { data: K, isLoading: q, refetch: J } = r(f, G), Y = ee(f), X = F || z || U || q, ie = c(() => !P && !R && !H && !K ? null : {
|
|
59
|
+
...P ?? {
|
|
41
60
|
workspaces: {
|
|
42
61
|
items: [],
|
|
43
62
|
total: 0
|
|
@@ -59,66 +78,66 @@ function O({ navigate: f, authToken: p, currentUser: _, productId: O = "workspac
|
|
|
59
78
|
workflowStats: null,
|
|
60
79
|
storageUsage: null
|
|
61
80
|
},
|
|
62
|
-
workspaces:
|
|
81
|
+
workspaces: R?.workspaces ?? {
|
|
63
82
|
items: [],
|
|
64
83
|
total: 0
|
|
65
84
|
},
|
|
66
|
-
projects:
|
|
85
|
+
projects: H ?? {
|
|
67
86
|
items: [],
|
|
68
87
|
total: 0
|
|
69
88
|
},
|
|
70
|
-
recentVibes:
|
|
71
|
-
activeSessions:
|
|
72
|
-
agentFleet:
|
|
89
|
+
recentVibes: K?.recentVibes,
|
|
90
|
+
activeSessions: K?.activeSessions,
|
|
91
|
+
agentFleet: K?.agentFleet ?? null
|
|
92
|
+
}, [
|
|
93
|
+
P,
|
|
94
|
+
R,
|
|
95
|
+
H,
|
|
96
|
+
K
|
|
97
|
+
]), Z = R?.dashboardPreferences, Q = c(() => a(Z?.widgets ?? null, D), [Z, D]), $ = s(() => {
|
|
98
|
+
L(), V(), W(), G && J();
|
|
73
99
|
}, [
|
|
74
|
-
N,
|
|
75
100
|
L,
|
|
76
101
|
V,
|
|
102
|
+
W,
|
|
103
|
+
J,
|
|
77
104
|
G
|
|
78
|
-
]),
|
|
79
|
-
|
|
80
|
-
}, [
|
|
81
|
-
|
|
82
|
-
B,
|
|
83
|
-
U,
|
|
84
|
-
q,
|
|
85
|
-
W
|
|
86
|
-
]), re = c(async (e) => {
|
|
87
|
-
await J.mutateAsync(e);
|
|
88
|
-
}, [J]), ie = F || z;
|
|
89
|
-
return /* @__PURE__ */ b("div", {
|
|
105
|
+
]), ae = s(async (e) => {
|
|
106
|
+
await Y.mutateAsync(e);
|
|
107
|
+
}, [Y]), oe = I || B;
|
|
108
|
+
return /* @__PURE__ */ v("div", {
|
|
90
109
|
className: "min-h-[calc(100vh-8rem)] p-4 md:p-6 bg-bg-canvas",
|
|
91
110
|
"data-tour": "main-content",
|
|
92
111
|
children: [
|
|
93
|
-
/* @__PURE__ */
|
|
112
|
+
/* @__PURE__ */ v("div", {
|
|
94
113
|
className: "relative overflow-hidden rounded-card -mx-1 px-1 pt-1",
|
|
95
|
-
children: [/* @__PURE__ */ y
|
|
96
|
-
icon: /* @__PURE__ */
|
|
97
|
-
title: /* @__PURE__ */
|
|
98
|
-
/* @__PURE__ */
|
|
114
|
+
children: [/* @__PURE__ */ _(y, { intensity: "subtle" }), /* @__PURE__ */ _(w, {
|
|
115
|
+
icon: /* @__PURE__ */ _(N, { className: "size-6" }),
|
|
116
|
+
title: /* @__PURE__ */ v(g, { children: [
|
|
117
|
+
/* @__PURE__ */ _(x, { children: M.noun }),
|
|
99
118
|
" ",
|
|
100
119
|
k("dashboard.titleSuffix", "Dashboard")
|
|
101
120
|
] }),
|
|
102
|
-
description:
|
|
103
|
-
actions: /* @__PURE__ */
|
|
121
|
+
description: M.subtitle,
|
|
122
|
+
actions: /* @__PURE__ */ v("div", {
|
|
104
123
|
className: "flex flex-wrap items-center gap-2",
|
|
105
124
|
"data-tour": "quick-actions",
|
|
106
|
-
children: [/* @__PURE__ */ b
|
|
125
|
+
children: [/* @__PURE__ */ v(b, {
|
|
107
126
|
variant: "outline",
|
|
108
127
|
size: "sm",
|
|
109
128
|
onClick: $,
|
|
110
|
-
disabled:
|
|
129
|
+
disabled: X,
|
|
111
130
|
className: "text-xs",
|
|
112
|
-
children: [
|
|
131
|
+
children: [X ? /* @__PURE__ */ _(p, { className: "size-3.5 sm:mr-1.5 animate-spin" }) : /* @__PURE__ */ _(m, { className: "size-3.5 sm:mr-1.5" }), /* @__PURE__ */ _("span", {
|
|
113
132
|
className: "hidden sm:inline",
|
|
114
133
|
children: k("dashboard.refresh", "Refresh")
|
|
115
134
|
})]
|
|
116
|
-
}), /* @__PURE__ */ b
|
|
135
|
+
}), /* @__PURE__ */ v(b, {
|
|
117
136
|
variant: "outline",
|
|
118
137
|
size: "sm",
|
|
119
138
|
onClick: () => A(!0),
|
|
120
139
|
className: "text-xs",
|
|
121
|
-
children: [/* @__PURE__ */
|
|
140
|
+
children: [/* @__PURE__ */ _(ne, { className: "size-3.5 sm:mr-1.5" }), /* @__PURE__ */ _("span", {
|
|
122
141
|
className: "hidden sm:inline",
|
|
123
142
|
children: k("dashboard.customize", "Customize")
|
|
124
143
|
})]
|
|
@@ -126,23 +145,23 @@ function O({ navigate: f, authToken: p, currentUser: _, productId: O = "workspac
|
|
|
126
145
|
})
|
|
127
146
|
})]
|
|
128
147
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
icon: /* @__PURE__ */
|
|
148
|
+
/* @__PURE__ */ _(S, {
|
|
149
|
+
icon: /* @__PURE__ */ _(N, { className: "size-4" }),
|
|
131
150
|
className: "mb-6 -mt-2",
|
|
132
|
-
children:
|
|
151
|
+
children: M.purpose
|
|
133
152
|
}),
|
|
134
|
-
|
|
153
|
+
oe && /* @__PURE__ */ v("div", {
|
|
135
154
|
className: "mb-4 p-3 bg-status-error-bg/10 border border-status-error-border/20 rounded-lg flex items-center gap-2",
|
|
136
|
-
children: [/* @__PURE__ */
|
|
155
|
+
children: [/* @__PURE__ */ _(u, { className: "size-4 text-status-error-text shrink-0" }), /* @__PURE__ */ v("p", {
|
|
137
156
|
className: "text-sm text-status-error-text",
|
|
138
157
|
children: [
|
|
139
158
|
k("dashboard.error.partialData", "Some data may be unavailable."),
|
|
140
159
|
" ",
|
|
141
|
-
|
|
160
|
+
I ? k("dashboard.error.workspaceDown", "Workspace services may be down.") : "",
|
|
142
161
|
" ",
|
|
143
|
-
|
|
162
|
+
B ? k("dashboard.error.globalDown", "Global services may be down.") : "",
|
|
144
163
|
" ",
|
|
145
|
-
/* @__PURE__ */
|
|
164
|
+
/* @__PURE__ */ _("button", {
|
|
146
165
|
type: "button",
|
|
147
166
|
className: "underline font-medium hover:text-status-error-text/80",
|
|
148
167
|
onClick: $,
|
|
@@ -151,26 +170,26 @@ function O({ navigate: f, authToken: p, currentUser: _, productId: O = "workspac
|
|
|
151
170
|
]
|
|
152
171
|
})]
|
|
153
172
|
}),
|
|
154
|
-
/* @__PURE__ */
|
|
173
|
+
/* @__PURE__ */ _(te, {
|
|
155
174
|
widgets: Q,
|
|
156
|
-
workspaceData:
|
|
157
|
-
globalData:
|
|
158
|
-
isLoading:
|
|
159
|
-
navigate:
|
|
160
|
-
productId:
|
|
175
|
+
workspaceData: ie,
|
|
176
|
+
globalData: R ?? null,
|
|
177
|
+
isLoading: X,
|
|
178
|
+
navigate: d,
|
|
179
|
+
productId: D
|
|
161
180
|
}),
|
|
162
|
-
/* @__PURE__ */
|
|
163
|
-
open:
|
|
181
|
+
/* @__PURE__ */ _(o, {
|
|
182
|
+
open: re,
|
|
164
183
|
onOpenChange: A,
|
|
165
184
|
widgets: Q,
|
|
166
|
-
onSave:
|
|
167
|
-
isSaving:
|
|
168
|
-
productId:
|
|
185
|
+
onSave: ae,
|
|
186
|
+
isSaving: Y.isPending,
|
|
187
|
+
productId: D
|
|
169
188
|
})
|
|
170
189
|
]
|
|
171
190
|
});
|
|
172
191
|
}
|
|
173
192
|
//#endregion
|
|
174
|
-
export {
|
|
193
|
+
export { D as DashboardPage };
|
|
175
194
|
|
|
176
195
|
//# sourceMappingURL=DashboardPage.js.map
|
|
@@ -1 +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, PagePurpose, AuroraBackground, GradientText } from '@burdenoff/fe-libs/ui';\nimport { PageHeader } from '@burdenoff/fe-libs/chrome';\nimport {\n Settings2,\n RefreshCw,\n Loader2,\n AlertCircle,\n Building2,\n Sparkles,\n GitBranch,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n useWorkspaceDashboardData,\n useGlobalDashboardData,\n useProjectsDashboardData,\n useVibecontrolsDashboardData,\n} from './hooks/useDashboardData';\nimport { useUpdateDashboardPreferences } from './hooks/useDashboardPreferences';\nimport { DashboardGrid } from './DashboardGrid';\nimport { DashboardCustomizer } from './DashboardCustomizer';\nimport { getEffectiveWidgets } from './config';\nimport type { WidgetConfig } from './types';\nimport { useWorkspacesPageView } from '../../hooks/useWorkspacesPageView';\n\ninterface ProductHeroCopy {\n noun: string;\n subtitle: string;\n purpose: string;\n Icon: LucideIcon;\n}\n\n/** Per-product hero heading/subtitle/purpose copy — keeps the dashboard from\n * reading as generic boilerplate for products layered on the shared page. */\nconst PRODUCT_HERO: Record<string, ProductHeroCopy> = {\n workspaces: {\n noun: 'Workspaces',\n subtitle: 'Your workspace overview at a glance',\n purpose:\n 'This is your home base — a single glance across everything that matters: your workspaces and projects, recent activity, upcoming events and live status. Use Customize to choose which cards appear and how they are arranged, and click any card to dive into the full view.',\n Icon: Building2,\n },\n vibecontrols: {\n noun: 'VibeControls',\n subtitle: 'Your workspace at a glance',\n purpose:\n 'This is your home base for this workspace — check on recent vibes, active sessions, and your agent fleet, then jump straight into whatever needs you. Use Customize to choose which cards appear and how they are arranged.',\n Icon: Sparkles,\n },\n fluidgrids: {\n noun: 'FluidGrids',\n subtitle: 'Your workflow automation at a glance',\n purpose:\n 'This is your home base — track workflow health, recent runs, and team activity, then jump straight into building or debugging. Use Customize to choose which cards appear and how they are arranged.',\n Icon: GitBranch,\n },\n};\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 * Host product identifier ('workspaces', 'vibecontrols', etc.). Drives\n * which widgets appear in the registry + default layout. Defaults to\n * 'workspaces' for legacy callers.\n */\n productId?: string;\n}\n\nexport function DashboardPage({\n navigate,\n authToken,\n currentUser: _currentUser,\n productId = 'workspaces',\n}: DashboardPageProps) {\n useWorkspacesPageView('workspaces.dashboard');\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 const hero = PRODUCT_HERO[productId] ?? PRODUCT_HERO.workspaces;\n const HeroIcon = hero.Icon;\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 isVibecontrols = productId === 'vibecontrols';\n const {\n data: vibecontrolsData,\n isLoading: vibecontrolsLoading,\n refetch: refetchVibecontrols,\n } = useVibecontrolsDashboardData(authToken, isVibecontrols);\n\n const updatePrefs = useUpdateDashboardPreferences(authToken);\n\n const isLoading = wsLoading || globalLoading || projectsLoading || vibecontrolsLoading;\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 && !vibecontrolsData) 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 // VibeControls-only data; undefined for other products\n recentVibes: vibecontrolsData?.recentVibes,\n activeSessions: vibecontrolsData?.activeSessions,\n agentFleet: vibecontrolsData?.agentFleet ?? null,\n };\n }, [workspaceData, globalData, projectsData, vibecontrolsData]);\n\n // ─── Widget Configuration ─────────────────────────────────────────────────\n const savedPrefs = globalData?.dashboardPreferences;\n const widgets = useMemo(\n () => getEffectiveWidgets(savedPrefs?.widgets ?? null, productId),\n [savedPrefs, productId]\n );\n\n // ─── Handlers ─────────────────────────────────────────────────────────────\n const handleRefresh = useCallback(() => {\n refetchWs();\n refetchGlobal();\n refetchProjects();\n if (isVibecontrols) refetchVibecontrols();\n }, [refetchWs, refetchGlobal, refetchProjects, refetchVibecontrols, isVibecontrols]);\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=\"relative overflow-hidden rounded-card -mx-1 px-1 pt-1\">\n <AuroraBackground intensity=\"subtle\" />\n <PageHeader\n icon={<HeroIcon className=\"size-6\" />}\n title={\n <>\n <GradientText>{tr(`dashboard.titleNoun.${productId}`, hero.noun)}</GradientText>{' '}\n {tr('dashboard.titleSuffix', 'Dashboard')}\n </>\n }\n description={tr(`dashboard.subtitle.${productId}`, hero.subtitle)}\n actions={\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=\"size-3.5 sm:mr-1.5 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-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=\"size-3.5 sm:mr-1.5\" />\n <span className=\"hidden sm:inline\">{tr('dashboard.customize', 'Customize')}</span>\n </Button>\n </div>\n }\n />\n </div>\n\n <PagePurpose icon={<HeroIcon className=\"size-4\" />} className=\"mb-6 -mt-2\">\n {tr(`dashboard.purpose.${productId}`, hero.purpose)}\n </PagePurpose>\n\n {/* Error Banner */}\n {hasError && (\n <div className=\"mb-4 p-3 bg-status-error-bg/10 border border-status-error-border/20 rounded-lg flex items-center gap-2\">\n <AlertCircle className=\"size-4 text-status-error-text shrink-0\" />\n <p className=\"text-sm text-status-error-text\">\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 type=\"button\"\n className=\"underline font-medium hover:text-status-error-text/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 productId={productId}\n />\n\n {/* Customizer */}\n <DashboardCustomizer\n open={customizerOpen}\n onOpenChange={setCustomizerOpen}\n widgets={widgets}\n onSave={handleSaveWidgets}\n isSaving={updatePrefs.isPending}\n productId={productId}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
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, PagePurpose, AuroraBackground, GradientText } from '@burdenoff/fe-libs/ui';\nimport { PageHeader } from '@burdenoff/fe-libs/chrome';\nimport {\n Settings2,\n RefreshCw,\n Loader2,\n AlertCircle,\n Building2,\n Sparkles,\n GitBranch,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n useWorkspaceDashboardData,\n useGlobalDashboardData,\n useProjectsDashboardData,\n useVibecontrolsDashboardData,\n} from './hooks/useDashboardData';\nimport { useUpdateDashboardPreferences } from './hooks/useDashboardPreferences';\nimport { DashboardGrid } from './DashboardGrid';\nimport { DashboardCustomizer } from './DashboardCustomizer';\nimport { getEffectiveWidgets } from './config';\nimport type { WidgetConfig } from './types';\nimport { useWorkspacesPageView } from '../../hooks/useWorkspacesPageView';\n\ninterface ProductHeroCopy {\n noun: string;\n subtitle: string;\n purpose: string;\n Icon: LucideIcon;\n}\n\n/** Per-product hero heading/subtitle/purpose copy — keeps the dashboard from\n * reading as generic boilerplate for products layered on the shared page. */\nconst PRODUCT_HERO: Record<string, ProductHeroCopy> = {\n workspaces: {\n noun: 'Workspaces',\n subtitle: 'Your workspace overview at a glance',\n purpose:\n 'This is your home base — a single glance across everything that matters: your workspaces and projects, recent activity, upcoming events and live status. Use Customize to choose which cards appear and how they are arranged, and click any card to dive into the full view.',\n Icon: Building2,\n },\n vibecontrols: {\n noun: 'VibeControls',\n subtitle: 'Your workspace at a glance',\n purpose:\n 'This is your home base for this workspace — check on recent vibes, active sessions, and your agent fleet, then jump straight into whatever needs you. Use Customize to choose which cards appear and how they are arranged.',\n Icon: Sparkles,\n },\n fluidgrids: {\n noun: 'FluidGrids',\n subtitle: 'Your workflow automation at a glance',\n purpose:\n 'This is your home base — track workflow health, recent runs, and team activity, then jump straight into building or debugging. Use Customize to choose which cards appear and how they are arranged.',\n Icon: GitBranch,\n },\n};\n\n/**\n * Resolve the per-product hero copy through i18n with **literal** keys.\n *\n * These three strings used to build their key by interpolating productId into\n * a template literal. The key extractor\n * (fluidgrids-app/scripts/extract-i18n-keys.ts) only collects string literals,\n * so an interpolated key is never extracted and never seeded — it can only ever\n * render its English fallback, in every locale, forever. Spelling each product\n * out gives the extractor something to find. [BOFF-5997]\n */\nfunction resolveHeroCopy(\n tr: (key: string, fallback: string) => string,\n productId: string,\n hero: ProductHeroCopy\n): { noun: string; subtitle: string; purpose: string } {\n switch (productId) {\n case 'vibecontrols':\n return {\n noun: tr('dashboard.titleNoun.vibecontrols', hero.noun),\n subtitle: tr('dashboard.subtitle.vibecontrols', hero.subtitle),\n purpose: tr('dashboard.purpose.vibecontrols', hero.purpose),\n };\n case 'fluidgrids':\n return {\n noun: tr('dashboard.titleNoun.fluidgrids', hero.noun),\n subtitle: tr('dashboard.subtitle.fluidgrids', hero.subtitle),\n purpose: tr('dashboard.purpose.fluidgrids', hero.purpose),\n };\n default:\n return {\n noun: tr('dashboard.titleNoun.workspaces', hero.noun),\n subtitle: tr('dashboard.subtitle.workspaces', hero.subtitle),\n purpose: tr('dashboard.purpose.workspaces', hero.purpose),\n };\n }\n}\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 * Host product identifier ('workspaces', 'vibecontrols', etc.). Drives\n * which widgets appear in the registry + default layout. Defaults to\n * 'workspaces' for legacy callers.\n */\n productId?: string;\n}\n\nexport function DashboardPage({\n navigate,\n authToken,\n currentUser: _currentUser,\n productId = 'workspaces',\n}: DashboardPageProps) {\n useWorkspacesPageView('workspaces.dashboard');\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 const hero = PRODUCT_HERO[productId] ?? PRODUCT_HERO.workspaces;\n const heroCopy = resolveHeroCopy(tr, productId, hero);\n const HeroIcon = hero.Icon;\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 isVibecontrols = productId === 'vibecontrols';\n const {\n data: vibecontrolsData,\n isLoading: vibecontrolsLoading,\n refetch: refetchVibecontrols,\n } = useVibecontrolsDashboardData(authToken, isVibecontrols);\n\n const updatePrefs = useUpdateDashboardPreferences(authToken);\n\n const isLoading = wsLoading || globalLoading || projectsLoading || vibecontrolsLoading;\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 && !vibecontrolsData) 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 // VibeControls-only data; undefined for other products\n recentVibes: vibecontrolsData?.recentVibes,\n activeSessions: vibecontrolsData?.activeSessions,\n agentFleet: vibecontrolsData?.agentFleet ?? null,\n };\n }, [workspaceData, globalData, projectsData, vibecontrolsData]);\n\n // ─── Widget Configuration ─────────────────────────────────────────────────\n const savedPrefs = globalData?.dashboardPreferences;\n const widgets = useMemo(\n () => getEffectiveWidgets(savedPrefs?.widgets ?? null, productId),\n [savedPrefs, productId]\n );\n\n // ─── Handlers ─────────────────────────────────────────────────────────────\n const handleRefresh = useCallback(() => {\n refetchWs();\n refetchGlobal();\n refetchProjects();\n if (isVibecontrols) refetchVibecontrols();\n }, [refetchWs, refetchGlobal, refetchProjects, refetchVibecontrols, isVibecontrols]);\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=\"relative overflow-hidden rounded-card -mx-1 px-1 pt-1\">\n <AuroraBackground intensity=\"subtle\" />\n <PageHeader\n icon={<HeroIcon className=\"size-6\" />}\n title={\n <>\n <GradientText>{heroCopy.noun}</GradientText>{' '}\n {tr('dashboard.titleSuffix', 'Dashboard')}\n </>\n }\n description={heroCopy.subtitle}\n actions={\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=\"size-3.5 sm:mr-1.5 animate-spin\" />\n ) : (\n <RefreshCw className=\"size-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=\"size-3.5 sm:mr-1.5\" />\n <span className=\"hidden sm:inline\">{tr('dashboard.customize', 'Customize')}</span>\n </Button>\n </div>\n }\n />\n </div>\n\n <PagePurpose icon={<HeroIcon className=\"size-4\" />} className=\"mb-6 -mt-2\">\n {heroCopy.purpose}\n </PagePurpose>\n\n {/* Error Banner */}\n {hasError && (\n <div className=\"mb-4 p-3 bg-status-error-bg/10 border border-status-error-border/20 rounded-lg flex items-center gap-2\">\n <AlertCircle className=\"size-4 text-status-error-text shrink-0\" />\n <p className=\"text-sm text-status-error-text\">\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 type=\"button\"\n className=\"underline font-medium hover:text-status-error-text/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 productId={productId}\n />\n\n {/* Customizer */}\n <DashboardCustomizer\n open={customizerOpen}\n onOpenChange={setCustomizerOpen}\n widgets={widgets}\n onSave={handleSaveWidgets}\n isSaving={updatePrefs.isPending}\n productId={productId}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -386,7 +386,83 @@ function s(t, i = e) {
|
|
|
386
386
|
});
|
|
387
387
|
return d.sort((e, t) => e.order - t.order);
|
|
388
388
|
}
|
|
389
|
+
function c(e, t) {
|
|
390
|
+
switch (t.id) {
|
|
391
|
+
case "welcome": return {
|
|
392
|
+
title: e("dashboard.widget.welcome.title", "Welcome"),
|
|
393
|
+
description: e("dashboard.widget.welcome.description", "Greeting and overview statistics")
|
|
394
|
+
};
|
|
395
|
+
case "quickActions": return {
|
|
396
|
+
title: e("dashboard.widget.quickActions.title", "Quick Actions"),
|
|
397
|
+
description: e("dashboard.widget.quickActions.description", "Frequently used actions and shortcuts")
|
|
398
|
+
};
|
|
399
|
+
case "workspaces": return {
|
|
400
|
+
title: e("dashboard.widget.workspaces.title", "Workspaces"),
|
|
401
|
+
description: e("dashboard.widget.workspaces.description", "Your workspaces overview and quick access")
|
|
402
|
+
};
|
|
403
|
+
case "projects": return {
|
|
404
|
+
title: e("dashboard.widget.projects.title", "Projects"),
|
|
405
|
+
description: e("dashboard.widget.projects.description", "Recent projects and status breakdown")
|
|
406
|
+
};
|
|
407
|
+
case "activity": return {
|
|
408
|
+
title: e("dashboard.widget.activity.title", "Recent Activity"),
|
|
409
|
+
description: e("dashboard.widget.activity.description", "Timeline of recent activity across modules")
|
|
410
|
+
};
|
|
411
|
+
case "calendar": return {
|
|
412
|
+
title: e("dashboard.widget.calendar.title", "Upcoming Events"),
|
|
413
|
+
description: e("dashboard.widget.calendar.description", "Next upcoming calendar events")
|
|
414
|
+
};
|
|
415
|
+
case "workflows": return {
|
|
416
|
+
title: e("dashboard.widget.workflows.title", "Workflows"),
|
|
417
|
+
description: e("dashboard.widget.workflows.description", "Active workflow stats and recent runs")
|
|
418
|
+
};
|
|
419
|
+
case "tags": return {
|
|
420
|
+
title: e("dashboard.widget.tags.title", "Tags"),
|
|
421
|
+
description: e("dashboard.widget.tags.description", "Popular tags across your workspace")
|
|
422
|
+
};
|
|
423
|
+
case "storage": return {
|
|
424
|
+
title: e("dashboard.widget.storage.title", "Storage"),
|
|
425
|
+
description: e("dashboard.widget.storage.description", "Storage usage and file statistics")
|
|
426
|
+
};
|
|
427
|
+
case "groups": return {
|
|
428
|
+
title: e("dashboard.widget.groups.title", "Groups"),
|
|
429
|
+
description: e("dashboard.widget.groups.description", "Your groups and teams")
|
|
430
|
+
};
|
|
431
|
+
case "members": return {
|
|
432
|
+
title: e("dashboard.widget.members.title", "Members"),
|
|
433
|
+
description: e("dashboard.widget.members.description", "Workspace member overview")
|
|
434
|
+
};
|
|
435
|
+
case "tips": return {
|
|
436
|
+
title: e("dashboard.widget.tips.title", "Tips & Resources"),
|
|
437
|
+
description: e("dashboard.widget.tips.description", "Getting started tips and documentation links")
|
|
438
|
+
};
|
|
439
|
+
case "vibes": return {
|
|
440
|
+
title: e("dashboard.widget.vibes.title", "Recent Vibes"),
|
|
441
|
+
description: e("dashboard.widget.vibes.description", "Your most recently active development vibes")
|
|
442
|
+
};
|
|
443
|
+
case "sessions": return {
|
|
444
|
+
title: e("dashboard.widget.sessions.title", "Active Sessions"),
|
|
445
|
+
description: e("dashboard.widget.sessions.description", "Running terminal and agent sessions")
|
|
446
|
+
};
|
|
447
|
+
case "agents": return {
|
|
448
|
+
title: e("dashboard.widget.agents.title", "Agent Fleet"),
|
|
449
|
+
description: e("dashboard.widget.agents.description", "Online, offline, and degraded agents at a glance")
|
|
450
|
+
};
|
|
451
|
+
case "workflowsOverview": return {
|
|
452
|
+
title: e("dashboard.widget.workflowsOverview.title", "Workflows"),
|
|
453
|
+
description: e("dashboard.widget.workflowsOverview.description", "Active/archived workflow counts and recently updated workflows")
|
|
454
|
+
};
|
|
455
|
+
case "workflowRuns": return {
|
|
456
|
+
title: e("dashboard.widget.workflowRuns.title", "Workflow Runs"),
|
|
457
|
+
description: e("dashboard.widget.workflowRuns.description", "Run health, success rate, and recent executions")
|
|
458
|
+
};
|
|
459
|
+
default: return {
|
|
460
|
+
title: t.title,
|
|
461
|
+
description: t.description
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
}
|
|
389
465
|
//#endregion
|
|
390
|
-
export { i as DEFAULT_DASHBOARD_WIDGETS, r as DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT, t as WIDGET_DEFINITIONS, s as getEffectiveWidgets, a as isWidgetAvailable };
|
|
466
|
+
export { i as DEFAULT_DASHBOARD_WIDGETS, r as DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT, t as WIDGET_DEFINITIONS, s as getEffectiveWidgets, a as isWidgetAvailable, c as resolveWidgetCopy };
|
|
391
467
|
|
|
392
468
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../../src/pages/dashboard/config.ts"],"sourcesContent":["/**\n * Dashboard Widget Registry & Default Configuration\n *\n * Product-aware. Hosts pass `productId` to filter widgets relevant for that\n * product. `availableInProducts` on each definition gates registry visibility;\n * `DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT` controls the default visible/order\n * layout for first-time users.\n */\nimport type { WidgetConfig, WidgetDefinition } from './types';\n\nexport const DEFAULT_PRODUCT_ID = 'workspaces';\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 availableInProducts: ['workspaces'],\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 availableInProducts: ['workspaces'],\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 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 // ── VibeControls-specific widgets ───────────────────────────────────────────\n vibes: {\n id: 'vibes',\n title: 'Recent Vibes',\n description: 'Your most recently active development vibes',\n icon: 'Sparkles',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['vibecontrols'],\n },\n sessions: {\n id: 'sessions',\n title: 'Active Sessions',\n description: 'Running terminal and agent sessions',\n icon: 'Terminal',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['vibecontrols'],\n },\n agents: {\n id: 'agents',\n title: 'Agent Fleet',\n description: 'Online, offline, and degraded agents at a glance',\n icon: 'Bot',\n defaultSize: 'small',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['vibecontrols'],\n },\n // ── FluidGrids-specific widgets ─────────────────────────────────────────────\n workflowsOverview: {\n id: 'workflowsOverview',\n title: 'Workflows',\n description: 'Active/archived workflow counts and recently updated workflows',\n icon: 'GitBranch',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['fluidgrids'],\n },\n workflowRuns: {\n id: 'workflowRuns',\n title: 'Workflow Runs',\n description: 'Run health, success rate, and recent executions',\n icon: 'Activity',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['fluidgrids'],\n },\n};\n\n// ─── Default Widget Layouts ───────────────────────────────────────────────────\n\nconst WORKSPACES_DEFAULT_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: 'tips', enabled: true, order: 11, size: 'small' },\n];\n\nconst VIBECONTROLS_DEFAULT_WIDGETS: WidgetConfig[] = [\n { widgetId: 'welcome', enabled: true, order: 0, size: 'large' },\n { widgetId: 'quickActions', enabled: true, order: 1, size: 'medium' },\n { widgetId: 'vibes', enabled: true, order: 2, size: 'medium' },\n { widgetId: 'sessions', enabled: true, order: 3, size: 'medium' },\n { widgetId: 'agents', enabled: true, order: 4, size: 'small' },\n { widgetId: 'workspaces', enabled: true, order: 5, size: 'medium' },\n { widgetId: 'projects', enabled: true, order: 6, size: 'medium' },\n { widgetId: 'activity', enabled: true, order: 7, size: 'large' },\n { widgetId: 'storage', enabled: true, order: 8, size: 'small' },\n { widgetId: 'members', enabled: true, order: 9, size: 'small' },\n { widgetId: 'tips', enabled: true, order: 10, size: 'small' },\n];\n\nconst FLUIDGRIDS_DEFAULT_WIDGETS: WidgetConfig[] = [\n { widgetId: 'welcome', enabled: true, order: 0, size: 'large' },\n { widgetId: 'quickActions', enabled: true, order: 1, size: 'medium' },\n { widgetId: 'workflowsOverview', enabled: true, order: 2, size: 'medium' },\n { widgetId: 'workflowRuns', enabled: true, order: 3, size: 'medium' },\n { widgetId: 'workspaces', enabled: true, order: 4, size: 'medium' },\n { widgetId: 'projects', enabled: true, order: 5, size: 'medium' },\n // Small widget placed right after projects so it fills the 1-column gap\n // left in that row (projects is 'medium' = 2 cols on a 3-col grid).\n { widgetId: 'tips', enabled: true, order: 6, size: 'small' },\n { widgetId: 'activity', enabled: true, order: 7, size: 'large' },\n { widgetId: 'groups', enabled: true, order: 8, size: 'small' },\n { widgetId: 'members', enabled: true, order: 9, size: 'small' },\n // tags/storage intentionally omitted from the default layout for FluidGrids\n // (not relevant to the workflow-automation use case) — still toggleable\n // via Customize, since getEffectiveWidgets() auto-appends them disabled.\n];\n\nexport const DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT: Record<string, WidgetConfig[]> = {\n workspaces: WORKSPACES_DEFAULT_WIDGETS,\n vibecontrols: VIBECONTROLS_DEFAULT_WIDGETS,\n fluidgrids: FLUIDGRIDS_DEFAULT_WIDGETS,\n};\n\n/** Backwards-compatible export — kept for callers that don't pass productId. */\nexport const DEFAULT_DASHBOARD_WIDGETS: WidgetConfig[] = WORKSPACES_DEFAULT_WIDGETS;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function isWidgetAvailable(\n widget: WidgetDefinition,\n productId: string = DEFAULT_PRODUCT_ID\n): boolean {\n if (!widget.availableInProducts || widget.availableInProducts.length === 0) {\n return true;\n }\n return widget.availableInProducts.includes(productId);\n}\n\nexport function getDefinitionsForProduct(\n productId: string = DEFAULT_PRODUCT_ID\n): Record<string, WidgetDefinition> {\n const out: Record<string, WidgetDefinition> = {};\n for (const [key, def] of Object.entries(WIDGET_DEFINITIONS)) {\n if (isWidgetAvailable(def, productId)) {\n out[key] = def;\n }\n }\n return out;\n}\n\n/**\n * Get the effective widget configuration, merging user prefs with defaults.\n * Filters out widgets that are not available for the given product.\n */\nexport function getEffectiveWidgets(\n userPrefs: WidgetConfig[] | null | undefined,\n productId: string = DEFAULT_PRODUCT_ID\n): WidgetConfig[] {\n const productDefaults =\n DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT[productId] ?? WORKSPACES_DEFAULT_WIDGETS;\n const availableDefinitions = getDefinitionsForProduct(productId);\n const availableIds = new Set(Object.keys(availableDefinitions));\n\n if (!userPrefs || userPrefs.length === 0) {\n return productDefaults.filter((w) => availableIds.has(w.widgetId));\n }\n\n // Drop saved prefs for widgets that no longer exist for this product (legacy\n // prefs e.g. systemHealth or workflows on vibecontrols).\n const filteredPrefs = userPrefs.filter((w) => availableIds.has(w.widgetId));\n const userWidgetIds = new Set(filteredPrefs.map((w) => w.widgetId));\n const merged = [...filteredPrefs];\n\n for (const def of Object.values(availableDefinitions)) {\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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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../../src/pages/dashboard/config.ts"],"sourcesContent":["/**\n * Dashboard Widget Registry & Default Configuration\n *\n * Product-aware. Hosts pass `productId` to filter widgets relevant for that\n * product. `availableInProducts` on each definition gates registry visibility;\n * `DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT` controls the default visible/order\n * layout for first-time users.\n */\nimport type { WidgetConfig, WidgetDefinition } from './types';\n\nexport const DEFAULT_PRODUCT_ID = 'workspaces';\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 availableInProducts: ['workspaces'],\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 availableInProducts: ['workspaces'],\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 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 // ── VibeControls-specific widgets ───────────────────────────────────────────\n vibes: {\n id: 'vibes',\n title: 'Recent Vibes',\n description: 'Your most recently active development vibes',\n icon: 'Sparkles',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['vibecontrols'],\n },\n sessions: {\n id: 'sessions',\n title: 'Active Sessions',\n description: 'Running terminal and agent sessions',\n icon: 'Terminal',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['vibecontrols'],\n },\n agents: {\n id: 'agents',\n title: 'Agent Fleet',\n description: 'Online, offline, and degraded agents at a glance',\n icon: 'Bot',\n defaultSize: 'small',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['vibecontrols'],\n },\n // ── FluidGrids-specific widgets ─────────────────────────────────────────────\n workflowsOverview: {\n id: 'workflowsOverview',\n title: 'Workflows',\n description: 'Active/archived workflow counts and recently updated workflows',\n icon: 'GitBranch',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['fluidgrids'],\n },\n workflowRuns: {\n id: 'workflowRuns',\n title: 'Workflow Runs',\n description: 'Run health, success rate, and recent executions',\n icon: 'Activity',\n defaultSize: 'medium',\n removable: true,\n dataSource: 'workspace',\n availableInProducts: ['fluidgrids'],\n },\n};\n\n// ─── Default Widget Layouts ───────────────────────────────────────────────────\n\nconst WORKSPACES_DEFAULT_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: 'tips', enabled: true, order: 11, size: 'small' },\n];\n\nconst VIBECONTROLS_DEFAULT_WIDGETS: WidgetConfig[] = [\n { widgetId: 'welcome', enabled: true, order: 0, size: 'large' },\n { widgetId: 'quickActions', enabled: true, order: 1, size: 'medium' },\n { widgetId: 'vibes', enabled: true, order: 2, size: 'medium' },\n { widgetId: 'sessions', enabled: true, order: 3, size: 'medium' },\n { widgetId: 'agents', enabled: true, order: 4, size: 'small' },\n { widgetId: 'workspaces', enabled: true, order: 5, size: 'medium' },\n { widgetId: 'projects', enabled: true, order: 6, size: 'medium' },\n { widgetId: 'activity', enabled: true, order: 7, size: 'large' },\n { widgetId: 'storage', enabled: true, order: 8, size: 'small' },\n { widgetId: 'members', enabled: true, order: 9, size: 'small' },\n { widgetId: 'tips', enabled: true, order: 10, size: 'small' },\n];\n\nconst FLUIDGRIDS_DEFAULT_WIDGETS: WidgetConfig[] = [\n { widgetId: 'welcome', enabled: true, order: 0, size: 'large' },\n { widgetId: 'quickActions', enabled: true, order: 1, size: 'medium' },\n { widgetId: 'workflowsOverview', enabled: true, order: 2, size: 'medium' },\n { widgetId: 'workflowRuns', enabled: true, order: 3, size: 'medium' },\n { widgetId: 'workspaces', enabled: true, order: 4, size: 'medium' },\n { widgetId: 'projects', enabled: true, order: 5, size: 'medium' },\n // Small widget placed right after projects so it fills the 1-column gap\n // left in that row (projects is 'medium' = 2 cols on a 3-col grid).\n { widgetId: 'tips', enabled: true, order: 6, size: 'small' },\n { widgetId: 'activity', enabled: true, order: 7, size: 'large' },\n { widgetId: 'groups', enabled: true, order: 8, size: 'small' },\n { widgetId: 'members', enabled: true, order: 9, size: 'small' },\n // tags/storage intentionally omitted from the default layout for FluidGrids\n // (not relevant to the workflow-automation use case) — still toggleable\n // via Customize, since getEffectiveWidgets() auto-appends them disabled.\n];\n\nexport const DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT: Record<string, WidgetConfig[]> = {\n workspaces: WORKSPACES_DEFAULT_WIDGETS,\n vibecontrols: VIBECONTROLS_DEFAULT_WIDGETS,\n fluidgrids: FLUIDGRIDS_DEFAULT_WIDGETS,\n};\n\n/** Backwards-compatible export — kept for callers that don't pass productId. */\nexport const DEFAULT_DASHBOARD_WIDGETS: WidgetConfig[] = WORKSPACES_DEFAULT_WIDGETS;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function isWidgetAvailable(\n widget: WidgetDefinition,\n productId: string = DEFAULT_PRODUCT_ID\n): boolean {\n if (!widget.availableInProducts || widget.availableInProducts.length === 0) {\n return true;\n }\n return widget.availableInProducts.includes(productId);\n}\n\nexport function getDefinitionsForProduct(\n productId: string = DEFAULT_PRODUCT_ID\n): Record<string, WidgetDefinition> {\n const out: Record<string, WidgetDefinition> = {};\n for (const [key, def] of Object.entries(WIDGET_DEFINITIONS)) {\n if (isWidgetAvailable(def, productId)) {\n out[key] = def;\n }\n }\n return out;\n}\n\n/**\n * Get the effective widget configuration, merging user prefs with defaults.\n * Filters out widgets that are not available for the given product.\n */\nexport function getEffectiveWidgets(\n userPrefs: WidgetConfig[] | null | undefined,\n productId: string = DEFAULT_PRODUCT_ID\n): WidgetConfig[] {\n const productDefaults =\n DEFAULT_DASHBOARD_WIDGETS_BY_PRODUCT[productId] ?? WORKSPACES_DEFAULT_WIDGETS;\n const availableDefinitions = getDefinitionsForProduct(productId);\n const availableIds = new Set(Object.keys(availableDefinitions));\n\n if (!userPrefs || userPrefs.length === 0) {\n return productDefaults.filter((w) => availableIds.has(w.widgetId));\n }\n\n // Drop saved prefs for widgets that no longer exist for this product (legacy\n // prefs e.g. systemHealth or workflows on vibecontrols).\n const filteredPrefs = userPrefs.filter((w) => availableIds.has(w.widgetId));\n const userWidgetIds = new Set(filteredPrefs.map((w) => w.widgetId));\n const merged = [...filteredPrefs];\n\n for (const def of Object.values(availableDefinitions)) {\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\n/**\n * Translate a widget definition's title/description with **literal** keys.\n *\n * `WIDGET_DEFINITIONS` is module scope, so it cannot call a hook, and the key\n * extractor (fluidgrids-app/scripts/extract-i18n-keys.ts) only collects string\n * literals — so neither a computed key nor a lookup table would ever be\n * extracted or seeded. Every widget is therefore spelled out. The English text\n * here stays in sync with `WIDGET_DEFINITIONS` above by being passed in as the\n * fallback, so it is impossible for the two to silently diverge. [BOFF-5997]\n */\nexport function resolveWidgetCopy(\n tr: (key: string, fallback: string) => string,\n def: WidgetDefinition\n): { title: string; description: string } {\n switch (def.id) {\n case 'welcome':\n return {\n title: tr('dashboard.widget.welcome.title', 'Welcome'),\n description: tr('dashboard.widget.welcome.description', 'Greeting and overview statistics'),\n };\n case 'quickActions':\n return {\n title: tr('dashboard.widget.quickActions.title', 'Quick Actions'),\n description: tr(\n 'dashboard.widget.quickActions.description',\n 'Frequently used actions and shortcuts'\n ),\n };\n case 'workspaces':\n return {\n title: tr('dashboard.widget.workspaces.title', 'Workspaces'),\n description: tr(\n 'dashboard.widget.workspaces.description',\n 'Your workspaces overview and quick access'\n ),\n };\n case 'projects':\n return {\n title: tr('dashboard.widget.projects.title', 'Projects'),\n description: tr(\n 'dashboard.widget.projects.description',\n 'Recent projects and status breakdown'\n ),\n };\n case 'activity':\n return {\n title: tr('dashboard.widget.activity.title', 'Recent Activity'),\n description: tr(\n 'dashboard.widget.activity.description',\n 'Timeline of recent activity across modules'\n ),\n };\n case 'calendar':\n return {\n title: tr('dashboard.widget.calendar.title', 'Upcoming Events'),\n description: tr('dashboard.widget.calendar.description', 'Next upcoming calendar events'),\n };\n case 'workflows':\n return {\n title: tr('dashboard.widget.workflows.title', 'Workflows'),\n description: tr(\n 'dashboard.widget.workflows.description',\n 'Active workflow stats and recent runs'\n ),\n };\n case 'tags':\n return {\n title: tr('dashboard.widget.tags.title', 'Tags'),\n description: tr('dashboard.widget.tags.description', 'Popular tags across your workspace'),\n };\n case 'storage':\n return {\n title: tr('dashboard.widget.storage.title', 'Storage'),\n description: tr(\n 'dashboard.widget.storage.description',\n 'Storage usage and file statistics'\n ),\n };\n case 'groups':\n return {\n title: tr('dashboard.widget.groups.title', 'Groups'),\n description: tr('dashboard.widget.groups.description', 'Your groups and teams'),\n };\n case 'members':\n return {\n title: tr('dashboard.widget.members.title', 'Members'),\n description: tr('dashboard.widget.members.description', 'Workspace member overview'),\n };\n case 'tips':\n return {\n title: tr('dashboard.widget.tips.title', 'Tips & Resources'),\n description: tr(\n 'dashboard.widget.tips.description',\n 'Getting started tips and documentation links'\n ),\n };\n case 'vibes':\n return {\n title: tr('dashboard.widget.vibes.title', 'Recent Vibes'),\n description: tr(\n 'dashboard.widget.vibes.description',\n 'Your most recently active development vibes'\n ),\n };\n case 'sessions':\n return {\n title: tr('dashboard.widget.sessions.title', 'Active Sessions'),\n description: tr(\n 'dashboard.widget.sessions.description',\n 'Running terminal and agent sessions'\n ),\n };\n case 'agents':\n return {\n title: tr('dashboard.widget.agents.title', 'Agent Fleet'),\n description: tr(\n 'dashboard.widget.agents.description',\n 'Online, offline, and degraded agents at a glance'\n ),\n };\n case 'workflowsOverview':\n return {\n title: tr('dashboard.widget.workflowsOverview.title', 'Workflows'),\n description: tr(\n 'dashboard.widget.workflowsOverview.description',\n 'Active/archived workflow counts and recently updated workflows'\n ),\n };\n case 'workflowRuns':\n return {\n title: tr('dashboard.widget.workflowRuns.title', 'Workflow Runs'),\n description: tr(\n 'dashboard.widget.workflowRuns.description',\n 'Run health, success rate, and recent executions'\n ),\n };\n default:\n return { title: def.title, description: def.description };\n }\n}\n"],"mappings":"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"}
|