@burdenoff/microfe-workspaces 2026.627.2 → 2026.711.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/wspace-operations.js +11 -0
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/pages/dashboard/DashboardGrid.js +60 -48
- package/dist/pages/dashboard/DashboardGrid.js.map +1 -1
- package/dist/pages/dashboard/DashboardPage.js +107 -82
- package/dist/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/pages/dashboard/WidgetWrapper.js +2 -2
- package/dist/pages/dashboard/WidgetWrapper.js.map +1 -1
- package/dist/pages/dashboard/config.js +82 -0
- package/dist/pages/dashboard/config.js.map +1 -1
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js +66 -23
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TipsWidget.js +68 -30
- package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowRunsWidget.js +139 -0
- package/dist/pages/dashboard/widgets/WorkflowRunsWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/WorkflowsOverviewWidget.js +91 -0
- package/dist/pages/dashboard/widgets/WorkflowsOverviewWidget.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,66 +1,78 @@
|
|
|
1
1
|
import { tWithFallback as e } from "../../utils/i18n.js";
|
|
2
2
|
import { WIDGET_DEFINITIONS as t, isWidgetAvailable as n } from "./config.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
3
|
+
import { getColSpan as r } from "./WidgetWrapper.js";
|
|
4
|
+
import { WelcomeWidget as i } from "./widgets/WelcomeWidget.js";
|
|
5
|
+
import { QuickActionsWidget as a } from "./widgets/QuickActionsWidget.js";
|
|
6
|
+
import { WorkspacesWidget as o } from "./widgets/WorkspacesWidget.js";
|
|
7
|
+
import { ProjectsWidget as s } from "./widgets/ProjectsWidget.js";
|
|
8
|
+
import { RecentActivityWidget as c } from "./widgets/RecentActivityWidget.js";
|
|
9
|
+
import { UpcomingEventsWidget as l } from "./widgets/UpcomingEventsWidget.js";
|
|
10
|
+
import { WorkflowStatsWidget as u } from "./widgets/WorkflowStatsWidget.js";
|
|
11
|
+
import { TagCloudWidget as d } from "./widgets/TagCloudWidget.js";
|
|
12
|
+
import { StorageWidget as f } from "./widgets/StorageWidget.js";
|
|
13
|
+
import { GroupsWidget as p } from "./widgets/GroupsWidget.js";
|
|
14
|
+
import { MembersWidget as m } from "./widgets/MembersWidget.js";
|
|
15
|
+
import { TipsWidget as h } from "./widgets/TipsWidget.js";
|
|
16
|
+
import { VibesWidget as g } from "./widgets/VibesWidget.js";
|
|
17
|
+
import { SessionsWidget as _ } from "./widgets/SessionsWidget.js";
|
|
18
|
+
import { AgentsWidget as v } from "./widgets/AgentsWidget.js";
|
|
19
|
+
import { WorkflowsOverviewWidget as y } from "./widgets/WorkflowsOverviewWidget.js";
|
|
20
|
+
import { WorkflowRunsWidget as b } from "./widgets/WorkflowRunsWidget.js";
|
|
21
|
+
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
22
|
+
import { useI18n as C } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
23
|
+
import { MotionItem as w, MotionList as T } from "@burdenoff/fe-libs/shared/motion";
|
|
20
24
|
//#region src/pages/dashboard/DashboardGrid.tsx
|
|
21
|
-
var
|
|
22
|
-
welcome:
|
|
23
|
-
quickActions:
|
|
24
|
-
workspaces:
|
|
25
|
-
projects:
|
|
26
|
-
activity:
|
|
27
|
-
calendar:
|
|
28
|
-
workflows:
|
|
29
|
-
tags:
|
|
30
|
-
storage:
|
|
31
|
-
groups:
|
|
32
|
-
members:
|
|
33
|
-
tips:
|
|
34
|
-
vibes:
|
|
35
|
-
sessions:
|
|
36
|
-
agents:
|
|
25
|
+
var E = {
|
|
26
|
+
welcome: i,
|
|
27
|
+
quickActions: a,
|
|
28
|
+
workspaces: o,
|
|
29
|
+
projects: s,
|
|
30
|
+
activity: c,
|
|
31
|
+
calendar: l,
|
|
32
|
+
workflows: u,
|
|
33
|
+
tags: d,
|
|
34
|
+
storage: f,
|
|
35
|
+
groups: p,
|
|
36
|
+
members: m,
|
|
37
|
+
tips: h,
|
|
38
|
+
vibes: g,
|
|
39
|
+
sessions: _,
|
|
40
|
+
agents: v,
|
|
41
|
+
workflowsOverview: y,
|
|
42
|
+
workflowRuns: b
|
|
37
43
|
};
|
|
38
|
-
function
|
|
39
|
-
let { t:
|
|
44
|
+
function D({ widgets: i, productId: a, ...o }) {
|
|
45
|
+
let { t: s } = C(), c = i.filter((e) => e.enabled).filter((e) => {
|
|
40
46
|
let r = t[e.widgetId];
|
|
41
|
-
return r ? n(r,
|
|
47
|
+
return r ? n(r, a) : !1;
|
|
42
48
|
}).sort((e, t) => e.order - t.order);
|
|
43
|
-
return
|
|
49
|
+
return c.length === 0 ? /* @__PURE__ */ S("div", {
|
|
44
50
|
className: "text-center py-12",
|
|
45
|
-
children: [/* @__PURE__ */
|
|
51
|
+
children: [/* @__PURE__ */ x("p", {
|
|
46
52
|
className: "text-lg text-text-secondary",
|
|
47
|
-
children: e(
|
|
48
|
-
}), /* @__PURE__ */
|
|
53
|
+
children: e(s, "dashboardGrid.noWidgetsEnabled", "No widgets enabled")
|
|
54
|
+
}), /* @__PURE__ */ x("p", {
|
|
49
55
|
className: "text-sm text-text-secondary mt-1",
|
|
50
|
-
children: e(
|
|
56
|
+
children: e(s, "dashboardGrid.noWidgetsHint", "Click \"Customize\" to add widgets to your dashboard")
|
|
51
57
|
})]
|
|
52
|
-
}) : /* @__PURE__ */
|
|
58
|
+
}) : /* @__PURE__ */ x(T, {
|
|
53
59
|
className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
stagger: .06,
|
|
61
|
+
children: c.map((e) => {
|
|
62
|
+
let t = E[e.widgetId];
|
|
63
|
+
return t ? /* @__PURE__ */ x(w, {
|
|
64
|
+
className: r(e.size),
|
|
65
|
+
variant: "fadeUp",
|
|
66
|
+
hoverable: !0,
|
|
67
|
+
children: /* @__PURE__ */ x(t, {
|
|
68
|
+
productId: a,
|
|
69
|
+
...o
|
|
70
|
+
})
|
|
59
71
|
}, e.widgetId) : null;
|
|
60
72
|
})
|
|
61
73
|
});
|
|
62
74
|
}
|
|
63
75
|
//#endregion
|
|
64
|
-
export {
|
|
76
|
+
export { D as DashboardGrid };
|
|
65
77
|
|
|
66
78
|
//# sourceMappingURL=DashboardGrid.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardGrid.js","names":[],"sources":["../../../src/pages/dashboard/DashboardGrid.tsx"],"sourcesContent":["/**\n * DashboardGrid — Renders the configured widgets in a responsive grid.\n */\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig, WidgetProps } from './types';\nimport { isWidgetAvailable, WIDGET_DEFINITIONS } from './config';\n\n// Widget components\nimport { WelcomeWidget } from './widgets/WelcomeWidget';\nimport { QuickActionsWidget } from './widgets/QuickActionsWidget';\nimport { WorkspacesWidget } from './widgets/WorkspacesWidget';\nimport { ProjectsWidget } from './widgets/ProjectsWidget';\nimport { RecentActivityWidget } from './widgets/RecentActivityWidget';\nimport { UpcomingEventsWidget } from './widgets/UpcomingEventsWidget';\nimport { WorkflowStatsWidget } from './widgets/WorkflowStatsWidget';\nimport { TagCloudWidget } from './widgets/TagCloudWidget';\nimport { StorageWidget } from './widgets/StorageWidget';\nimport { GroupsWidget } from './widgets/GroupsWidget';\nimport { MembersWidget } from './widgets/MembersWidget';\nimport { TipsWidget } from './widgets/TipsWidget';\nimport { VibesWidget } from './widgets/VibesWidget';\nimport { SessionsWidget } from './widgets/SessionsWidget';\nimport { AgentsWidget } from './widgets/AgentsWidget';\n\n// Widget component registry\nconst WIDGET_COMPONENTS: Record<string, React.FC<WidgetProps>> = {\n welcome: WelcomeWidget,\n quickActions: QuickActionsWidget,\n workspaces: WorkspacesWidget,\n projects: ProjectsWidget,\n activity: RecentActivityWidget,\n calendar: UpcomingEventsWidget,\n workflows: WorkflowStatsWidget,\n tags: TagCloudWidget,\n storage: StorageWidget,\n groups: GroupsWidget,\n members: MembersWidget,\n tips: TipsWidget,\n vibes: VibesWidget,\n sessions: SessionsWidget,\n agents: AgentsWidget,\n};\n\ninterface DashboardGridProps extends WidgetProps {\n widgets: WidgetConfig[];\n}\n\nexport function DashboardGrid({ widgets, productId, ...widgetProps }: DashboardGridProps) {\n const { t } = useI18n();\n\n const enabledWidgets = widgets\n .filter((w) => w.enabled)\n .filter((w) => {\n const def = WIDGET_DEFINITIONS[w.widgetId];\n if (!def) return false;\n return isWidgetAvailable(def, productId);\n })\n .sort((a, b) => a.order - b.order);\n\n if (enabledWidgets.length === 0) {\n return (\n <div className=\"text-center py-12\">\n <p className=\"text-lg text-text-secondary\">\n {tWithFallback(t, 'dashboardGrid.noWidgetsEnabled', 'No widgets enabled')}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tWithFallback(\n t,\n 'dashboardGrid.noWidgetsHint',\n 'Click \"Customize\" to add widgets to your dashboard'\n )}\n </p>\n </div>\n );\n }\n\n return (\n <
|
|
1
|
+
{"version":3,"file":"DashboardGrid.js","names":[],"sources":["../../../src/pages/dashboard/DashboardGrid.tsx"],"sourcesContent":["/**\n * DashboardGrid — Renders the configured widgets in a responsive grid.\n */\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { tWithFallback } from '../../utils/i18n';\nimport type { WidgetConfig, WidgetProps } from './types';\nimport { isWidgetAvailable, WIDGET_DEFINITIONS } from './config';\nimport { getColSpan } from './WidgetWrapper';\n\n// Widget components\nimport { WelcomeWidget } from './widgets/WelcomeWidget';\nimport { QuickActionsWidget } from './widgets/QuickActionsWidget';\nimport { WorkspacesWidget } from './widgets/WorkspacesWidget';\nimport { ProjectsWidget } from './widgets/ProjectsWidget';\nimport { RecentActivityWidget } from './widgets/RecentActivityWidget';\nimport { UpcomingEventsWidget } from './widgets/UpcomingEventsWidget';\nimport { WorkflowStatsWidget } from './widgets/WorkflowStatsWidget';\nimport { TagCloudWidget } from './widgets/TagCloudWidget';\nimport { StorageWidget } from './widgets/StorageWidget';\nimport { GroupsWidget } from './widgets/GroupsWidget';\nimport { MembersWidget } from './widgets/MembersWidget';\nimport { TipsWidget } from './widgets/TipsWidget';\nimport { VibesWidget } from './widgets/VibesWidget';\nimport { SessionsWidget } from './widgets/SessionsWidget';\nimport { AgentsWidget } from './widgets/AgentsWidget';\nimport { WorkflowsOverviewWidget } from './widgets/WorkflowsOverviewWidget';\nimport { WorkflowRunsWidget } from './widgets/WorkflowRunsWidget';\n\n// Widget component registry\nconst WIDGET_COMPONENTS: Record<string, React.FC<WidgetProps>> = {\n welcome: WelcomeWidget,\n quickActions: QuickActionsWidget,\n workspaces: WorkspacesWidget,\n projects: ProjectsWidget,\n activity: RecentActivityWidget,\n calendar: UpcomingEventsWidget,\n workflows: WorkflowStatsWidget,\n tags: TagCloudWidget,\n storage: StorageWidget,\n groups: GroupsWidget,\n members: MembersWidget,\n tips: TipsWidget,\n vibes: VibesWidget,\n sessions: SessionsWidget,\n agents: AgentsWidget,\n workflowsOverview: WorkflowsOverviewWidget,\n workflowRuns: WorkflowRunsWidget,\n};\n\ninterface DashboardGridProps extends WidgetProps {\n widgets: WidgetConfig[];\n}\n\nexport function DashboardGrid({ widgets, productId, ...widgetProps }: DashboardGridProps) {\n const { t } = useI18n();\n\n const enabledWidgets = widgets\n .filter((w) => w.enabled)\n .filter((w) => {\n const def = WIDGET_DEFINITIONS[w.widgetId];\n if (!def) return false;\n return isWidgetAvailable(def, productId);\n })\n .sort((a, b) => a.order - b.order);\n\n if (enabledWidgets.length === 0) {\n return (\n <div className=\"text-center py-12\">\n <p className=\"text-lg text-text-secondary\">\n {tWithFallback(t, 'dashboardGrid.noWidgetsEnabled', 'No widgets enabled')}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">\n {tWithFallback(\n t,\n 'dashboardGrid.noWidgetsHint',\n 'Click \"Customize\" to add widgets to your dashboard'\n )}\n </p>\n </div>\n );\n }\n\n return (\n <MotionList className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\" stagger={0.06}>\n {enabledWidgets.map((widgetConfig) => {\n const Component = WIDGET_COMPONENTS[widgetConfig.widgetId];\n if (!Component) return null;\n\n return (\n <MotionItem\n key={widgetConfig.widgetId}\n className={getColSpan(widgetConfig.size)}\n variant=\"fadeUp\"\n hoverable\n >\n <Component productId={productId} {...widgetProps} />\n </MotionItem>\n );\n })}\n </MotionList>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAM,IAA2D;CAC/D,SAAS;CACT,cAAc;CACd,YAAY;CACZ,UAAU;CACV,UAAU;CACV,UAAU;CACV,WAAW;CACX,MAAM;CACN,SAAS;CACT,QAAQ;CACR,SAAS;CACT,MAAM;CACN,OAAO;CACP,UAAU;CACV,QAAQ;CACR,mBAAmB;CACnB,cAAc;CACf;AAMD,SAAgB,EAAc,EAAE,YAAS,cAAW,GAAG,KAAmC;CACxF,IAAM,EAAE,SAAM,GAAS,EAEjB,IAAiB,EACpB,QAAQ,MAAM,EAAE,QAAQ,CACxB,QAAQ,MAAM;EACb,IAAM,IAAM,EAAmB,EAAE;AAEjC,SADK,IACE,EAAkB,GAAK,EAAU,GADvB;GAEjB,CACD,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;AAmBpC,QAjBI,EAAe,WAAW,IAE1B,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,KAAD;GAAG,WAAU;aACV,EAAc,GAAG,kCAAkC,qBAAqB;GACvE,CAAA,EACJ,kBAAC,KAAD;GAAG,WAAU;aACV,EACC,GACA,+BACA,uDACD;GACC,CAAA,CACA;MAKR,kBAAC,GAAD;EAAY,WAAU;EAAuD,SAAS;YACnF,EAAe,KAAK,MAAiB;GACpC,IAAM,IAAY,EAAkB,EAAa;AAGjD,UAFK,IAGH,kBAAC,GAAD;IAEE,WAAW,EAAW,EAAa,KAAK;IACxC,SAAQ;IACR,WAAA;cAEA,kBAAC,GAAD;KAAsB;KAAW,GAAI;KAAe,CAAA;IACzC,EANN,EAAa,SAMP,GAVQ;IAYvB;EACS,CAAA"}
|
|
@@ -3,20 +3,41 @@ import { useGlobalDashboardData as t, useProjectsDashboardData as n, useVibecont
|
|
|
3
3
|
import { useUpdateDashboardPreferences as a } from "./hooks/useDashboardPreferences.js";
|
|
4
4
|
import { getEffectiveWidgets as o } from "./config.js";
|
|
5
5
|
import { DashboardGrid as s } from "./DashboardGrid.js";
|
|
6
|
-
import { DashboardCustomizer as
|
|
7
|
-
import { useCallback as
|
|
8
|
-
import { AlertCircle as f,
|
|
9
|
-
import { jsx as
|
|
10
|
-
import { Button as
|
|
11
|
-
import { useI18n as
|
|
6
|
+
import { DashboardCustomizer as ee } from "./DashboardCustomizer.js";
|
|
7
|
+
import { useCallback as c, useMemo as l, useState as u } from "react";
|
|
8
|
+
import { AlertCircle as d, Building2 as f, GitBranch as p, Loader2 as m, RefreshCw as h, Settings2 as g, Sparkles as _ } from "lucide-react";
|
|
9
|
+
import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
10
|
+
import { AuroraBackground as x, Button as S, GradientText as C, PagePurpose as w } from "@burdenoff/fe-libs/ui";
|
|
11
|
+
import { useI18n as T } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
12
|
+
import { PageHeader as E } from "@burdenoff/fe-libs/chrome";
|
|
12
13
|
//#region src/pages/dashboard/DashboardPage.tsx
|
|
13
|
-
|
|
14
|
+
var D = {
|
|
15
|
+
workspaces: {
|
|
16
|
+
noun: "Workspaces",
|
|
17
|
+
subtitle: "Your workspace overview at a glance",
|
|
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: f
|
|
20
|
+
},
|
|
21
|
+
vibecontrols: {
|
|
22
|
+
noun: "VibeControls",
|
|
23
|
+
subtitle: "Your workspace at a glance",
|
|
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: _
|
|
26
|
+
},
|
|
27
|
+
fluidgrids: {
|
|
28
|
+
noun: "FluidGrids",
|
|
29
|
+
subtitle: "Your workflow automation at a glance",
|
|
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: p
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
function O({ navigate: f, authToken: p, currentUser: _, productId: O = "workspaces" }) {
|
|
14
35
|
e("workspaces.dashboard");
|
|
15
|
-
let { t:
|
|
16
|
-
let n =
|
|
36
|
+
let { t: te } = T(), k = (e, t) => {
|
|
37
|
+
let n = te(e);
|
|
17
38
|
return n === e ? t : n;
|
|
18
|
-
}, [
|
|
19
|
-
...
|
|
39
|
+
}, [ne, A] = u(!1), j = D[O] ?? D.workspaces, M = j.Icon, { data: N, isLoading: P, error: F, refetch: I } = i(p), { data: L, isLoading: R, error: z, refetch: B } = t(p), { data: V, isLoading: H, refetch: U } = n(p), W = O === "vibecontrols", { data: G, isLoading: K, refetch: q } = r(p, W), J = a(p), Y = P || R || H || K, X = l(() => !N && !L && !V && !G ? null : {
|
|
40
|
+
...N ?? {
|
|
20
41
|
workspaces: {
|
|
21
42
|
items: [],
|
|
22
43
|
total: 0
|
|
@@ -38,114 +59,118 @@ function x({ navigate: x, authToken: S, currentUser: C, productId: w = "workspac
|
|
|
38
59
|
workflowStats: null,
|
|
39
60
|
storageUsage: null
|
|
40
61
|
},
|
|
41
|
-
workspaces:
|
|
62
|
+
workspaces: L?.workspaces ?? {
|
|
42
63
|
items: [],
|
|
43
64
|
total: 0
|
|
44
65
|
},
|
|
45
|
-
projects:
|
|
66
|
+
projects: V ?? {
|
|
46
67
|
items: [],
|
|
47
68
|
total: 0
|
|
48
69
|
},
|
|
49
|
-
recentVibes:
|
|
50
|
-
activeSessions:
|
|
51
|
-
agentFleet:
|
|
70
|
+
recentVibes: G?.recentVibes,
|
|
71
|
+
activeSessions: G?.activeSessions,
|
|
72
|
+
agentFleet: G?.agentFleet ?? null
|
|
52
73
|
}, [
|
|
53
|
-
k,
|
|
54
74
|
N,
|
|
55
75
|
L,
|
|
56
|
-
V
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
V,
|
|
77
|
+
G
|
|
78
|
+
]), Z = L?.dashboardPreferences, Q = l(() => o(Z?.widgets ?? null, O), [Z, O]), $ = c(() => {
|
|
79
|
+
I(), B(), U(), W && q();
|
|
59
80
|
}, [
|
|
60
|
-
M,
|
|
61
81
|
I,
|
|
62
|
-
|
|
82
|
+
B,
|
|
63
83
|
U,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
84
|
+
q,
|
|
85
|
+
W
|
|
86
|
+
]), re = c(async (e) => {
|
|
87
|
+
await J.mutateAsync(e);
|
|
88
|
+
}, [J]), ie = F || z;
|
|
89
|
+
return /* @__PURE__ */ b("div", {
|
|
69
90
|
className: "min-h-[calc(100vh-8rem)] p-4 md:p-6 bg-bg-canvas",
|
|
70
91
|
"data-tour": "main-content",
|
|
71
92
|
children: [
|
|
72
|
-
/* @__PURE__ */
|
|
73
|
-
className: "
|
|
74
|
-
children: [/* @__PURE__ */
|
|
75
|
-
className: "
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
className: "
|
|
91
|
-
children:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
className: "
|
|
100
|
-
children:
|
|
93
|
+
/* @__PURE__ */ b("div", {
|
|
94
|
+
className: "relative overflow-hidden rounded-card -mx-1 px-1 pt-1",
|
|
95
|
+
children: [/* @__PURE__ */ y(x, { intensity: "subtle" }), /* @__PURE__ */ y(E, {
|
|
96
|
+
icon: /* @__PURE__ */ y(M, { className: "size-6" }),
|
|
97
|
+
title: /* @__PURE__ */ b(v, { children: [
|
|
98
|
+
/* @__PURE__ */ y(C, { children: k(`dashboard.titleNoun.${O}`, j.noun) }),
|
|
99
|
+
" ",
|
|
100
|
+
k("dashboard.titleSuffix", "Dashboard")
|
|
101
|
+
] }),
|
|
102
|
+
description: k(`dashboard.subtitle.${O}`, j.subtitle),
|
|
103
|
+
actions: /* @__PURE__ */ b("div", {
|
|
104
|
+
className: "flex flex-wrap items-center gap-2",
|
|
105
|
+
"data-tour": "quick-actions",
|
|
106
|
+
children: [/* @__PURE__ */ b(S, {
|
|
107
|
+
variant: "outline",
|
|
108
|
+
size: "sm",
|
|
109
|
+
onClick: $,
|
|
110
|
+
disabled: Y,
|
|
111
|
+
className: "text-xs",
|
|
112
|
+
children: [Y ? /* @__PURE__ */ y(m, { className: "size-3.5 sm:mr-1.5 animate-spin" }) : /* @__PURE__ */ y(h, { className: "size-3.5 sm:mr-1.5" }), /* @__PURE__ */ y("span", {
|
|
113
|
+
className: "hidden sm:inline",
|
|
114
|
+
children: k("dashboard.refresh", "Refresh")
|
|
115
|
+
})]
|
|
116
|
+
}), /* @__PURE__ */ b(S, {
|
|
117
|
+
variant: "outline",
|
|
118
|
+
size: "sm",
|
|
119
|
+
onClick: () => A(!0),
|
|
120
|
+
className: "text-xs",
|
|
121
|
+
children: [/* @__PURE__ */ y(g, { className: "size-3.5 sm:mr-1.5" }), /* @__PURE__ */ y("span", {
|
|
122
|
+
className: "hidden sm:inline",
|
|
123
|
+
children: k("dashboard.customize", "Customize")
|
|
124
|
+
})]
|
|
101
125
|
})]
|
|
102
|
-
})
|
|
126
|
+
})
|
|
103
127
|
})]
|
|
104
128
|
}),
|
|
105
|
-
/* @__PURE__ */
|
|
129
|
+
/* @__PURE__ */ y(w, {
|
|
130
|
+
icon: /* @__PURE__ */ y(M, { className: "size-4" }),
|
|
106
131
|
className: "mb-6 -mt-2",
|
|
107
|
-
children:
|
|
132
|
+
children: k(`dashboard.purpose.${O}`, j.purpose)
|
|
108
133
|
}),
|
|
109
|
-
|
|
134
|
+
ie && /* @__PURE__ */ b("div", {
|
|
110
135
|
className: "mb-4 p-3 bg-status-error-bg/10 border border-status-error-border/20 rounded-lg flex items-center gap-2",
|
|
111
|
-
children: [/* @__PURE__ */
|
|
136
|
+
children: [/* @__PURE__ */ y(d, { className: "size-4 text-status-error-text shrink-0" }), /* @__PURE__ */ b("p", {
|
|
112
137
|
className: "text-sm text-status-error-text",
|
|
113
138
|
children: [
|
|
114
|
-
|
|
139
|
+
k("dashboard.error.partialData", "Some data may be unavailable."),
|
|
115
140
|
" ",
|
|
116
|
-
|
|
141
|
+
F ? k("dashboard.error.workspaceDown", "Workspace services may be down.") : "",
|
|
117
142
|
" ",
|
|
118
|
-
|
|
143
|
+
z ? k("dashboard.error.globalDown", "Global services may be down.") : "",
|
|
119
144
|
" ",
|
|
120
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ y("button", {
|
|
121
146
|
type: "button",
|
|
122
147
|
className: "underline font-medium hover:text-status-error-text/80",
|
|
123
|
-
onClick:
|
|
124
|
-
children:
|
|
148
|
+
onClick: $,
|
|
149
|
+
children: k("dashboard.error.tryRefreshing", "Try refreshing")
|
|
125
150
|
})
|
|
126
151
|
]
|
|
127
152
|
})]
|
|
128
153
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
widgets:
|
|
131
|
-
workspaceData:
|
|
132
|
-
globalData:
|
|
133
|
-
isLoading:
|
|
134
|
-
navigate:
|
|
135
|
-
productId:
|
|
154
|
+
/* @__PURE__ */ y(s, {
|
|
155
|
+
widgets: Q,
|
|
156
|
+
workspaceData: X,
|
|
157
|
+
globalData: L ?? null,
|
|
158
|
+
isLoading: Y,
|
|
159
|
+
navigate: f,
|
|
160
|
+
productId: O
|
|
136
161
|
}),
|
|
137
|
-
/* @__PURE__ */
|
|
138
|
-
open:
|
|
139
|
-
onOpenChange:
|
|
140
|
-
widgets:
|
|
141
|
-
onSave:
|
|
142
|
-
isSaving:
|
|
143
|
-
productId:
|
|
162
|
+
/* @__PURE__ */ y(ee, {
|
|
163
|
+
open: ne,
|
|
164
|
+
onOpenChange: A,
|
|
165
|
+
widgets: Q,
|
|
166
|
+
onSave: re,
|
|
167
|
+
isSaving: J.isPending,
|
|
168
|
+
productId: O
|
|
144
169
|
})
|
|
145
170
|
]
|
|
146
171
|
});
|
|
147
172
|
}
|
|
148
173
|
//#endregion
|
|
149
|
-
export {
|
|
174
|
+
export { O as DashboardPage };
|
|
150
175
|
|
|
151
176
|
//# 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 } from '@burdenoff/fe-libs/ui';\nimport { Settings2, RefreshCw, Loader2, AlertCircle } 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 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\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=\"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-text-secondary 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=\"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 </div>\n\n <PagePurpose className=\"mb-6 -mt-2\">\n {tr(\n 'dashboard.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 )}\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\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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"}
|
|
@@ -51,7 +51,7 @@ function m() {
|
|
|
51
51
|
function h({ title: e, icon: t, size: n, isLoading: l, error: u, unavailable: h, headerAction: g, children: _, className: v = "" }) {
|
|
52
52
|
return /* @__PURE__ */ i(c, {
|
|
53
53
|
treatment: "insight",
|
|
54
|
-
className:
|
|
54
|
+
className: `h-full ${d(n)} border-border-seam bg-bg-surface ${v}`,
|
|
55
55
|
children: [/* @__PURE__ */ i(o, {
|
|
56
56
|
className: "flex flex-row items-center justify-between pb-2 gap-y-0",
|
|
57
57
|
children: [/* @__PURE__ */ i(s, {
|
|
@@ -65,6 +65,6 @@ function h({ title: e, icon: t, size: n, isLoading: l, error: u, unavailable: h,
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
//#endregion
|
|
68
|
-
export { h as WidgetWrapper };
|
|
68
|
+
export { h as WidgetWrapper, d as getColSpan };
|
|
69
69
|
|
|
70
70
|
//# sourceMappingURL=WidgetWrapper.js.map
|
|
@@ -1 +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 } from 'react';\nimport { GlassCard, 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 { tWithFallback } from '../../utils/i18n';\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\
|
|
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 } from 'react';\nimport { GlassCard, 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 { tWithFallback } from '../../utils/i18n';\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\nexport function 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-status-error-bg/10 p-2 mb-2\">\n <AlertCircle className=\"size-5 text-status-error-text\" />\n </div>\n <p className=\"text-sm text-text-secondary\">{message}</p>\n </div>\n );\n}\n\nfunction UnavailableState() {\n const { t } = useI18n();\n\n return (\n <div className=\"flex flex-col items-center justify-center py-6 text-center\">\n <div className=\"rounded-full bg-bg-sunken p-2 mb-2\">\n <WifiOff className=\"size-5 text-text-secondary\" />\n </div>\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(t, '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 <GlassCard\n treatment=\"insight\"\n className={`h-full ${colSpan} border-border-seam bg-bg-surface ${className}`}\n >\n <CardHeader className=\"flex flex-row items-center justify-between pb-2 gap-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 </GlassCard>\n );\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,EAAW,GAA0B;AACnD,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,iCAAkC,CAAA;GACrD,CAAA,EACN,kBAAC,KAAD;GAAG,WAAU;aAA+B;GAAY,CAAA,CACpD;;;AAIV,SAAS,IAAmB;CAC1B,IAAM,EAAE,MAAM,GAAS;AAEvB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAS,WAAU,8BAA+B,CAAA;GAC9C,CAAA,EACN,kBAAC,KAAD;GAAG,WAAU;aACV,EAAc,GAAG,oCAAoC,sBAAsB;GAC1E,CAAA,CACA;;;AAIV,SAAgB,EAAc,EAC5B,UACA,SACA,SACA,cACA,UACA,gBACA,iBACA,aACA,eAAY,MACS;AAGrB,QACE,kBAAC,GAAD;EACE,WAAU;EACV,WAAW,UALC,EAAW,EAAK,CAKC,oCAAoC;YAFnE,CAIE,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,CACJ"}
|
|
@@ -139,6 +139,26 @@ var e = "workspaces", t = {
|
|
|
139
139
|
removable: !0,
|
|
140
140
|
dataSource: "workspace",
|
|
141
141
|
availableInProducts: ["vibecontrols"]
|
|
142
|
+
},
|
|
143
|
+
workflowsOverview: {
|
|
144
|
+
id: "workflowsOverview",
|
|
145
|
+
title: "Workflows",
|
|
146
|
+
description: "Active/archived workflow counts and recently updated workflows",
|
|
147
|
+
icon: "GitBranch",
|
|
148
|
+
defaultSize: "medium",
|
|
149
|
+
removable: !0,
|
|
150
|
+
dataSource: "workspace",
|
|
151
|
+
availableInProducts: ["fluidgrids"]
|
|
152
|
+
},
|
|
153
|
+
workflowRuns: {
|
|
154
|
+
id: "workflowRuns",
|
|
155
|
+
title: "Workflow Runs",
|
|
156
|
+
description: "Run health, success rate, and recent executions",
|
|
157
|
+
icon: "Activity",
|
|
158
|
+
defaultSize: "medium",
|
|
159
|
+
removable: !0,
|
|
160
|
+
dataSource: "workspace",
|
|
161
|
+
availableInProducts: ["fluidgrids"]
|
|
142
162
|
}
|
|
143
163
|
}, n = [
|
|
144
164
|
{
|
|
@@ -282,6 +302,68 @@ var e = "workspaces", t = {
|
|
|
282
302
|
order: 10,
|
|
283
303
|
size: "small"
|
|
284
304
|
}
|
|
305
|
+
],
|
|
306
|
+
fluidgrids: [
|
|
307
|
+
{
|
|
308
|
+
widgetId: "welcome",
|
|
309
|
+
enabled: !0,
|
|
310
|
+
order: 0,
|
|
311
|
+
size: "large"
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
widgetId: "quickActions",
|
|
315
|
+
enabled: !0,
|
|
316
|
+
order: 1,
|
|
317
|
+
size: "medium"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
widgetId: "workflowsOverview",
|
|
321
|
+
enabled: !0,
|
|
322
|
+
order: 2,
|
|
323
|
+
size: "medium"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
widgetId: "workflowRuns",
|
|
327
|
+
enabled: !0,
|
|
328
|
+
order: 3,
|
|
329
|
+
size: "medium"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
widgetId: "workspaces",
|
|
333
|
+
enabled: !0,
|
|
334
|
+
order: 4,
|
|
335
|
+
size: "medium"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
widgetId: "projects",
|
|
339
|
+
enabled: !0,
|
|
340
|
+
order: 5,
|
|
341
|
+
size: "medium"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
widgetId: "tips",
|
|
345
|
+
enabled: !0,
|
|
346
|
+
order: 6,
|
|
347
|
+
size: "small"
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
widgetId: "activity",
|
|
351
|
+
enabled: !0,
|
|
352
|
+
order: 7,
|
|
353
|
+
size: "large"
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
widgetId: "groups",
|
|
357
|
+
enabled: !0,
|
|
358
|
+
order: 8,
|
|
359
|
+
size: "small"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
widgetId: "members",
|
|
363
|
+
enabled: !0,
|
|
364
|
+
order: 9,
|
|
365
|
+
size: "small"
|
|
366
|
+
}
|
|
285
367
|
]
|
|
286
368
|
}, i = n;
|
|
287
369
|
function a(t, n = e) {
|