@burdenoff/microfe-workspaces 2026.519.1 → 2026.528.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/WorkspacesRoot.js +4 -1
- package/dist/WorkspacesRoot.js.map +1 -1
- package/dist/WorkspacesRoutes.js +4 -4
- package/dist/WorkspacesRoutes.js.map +1 -1
- package/dist/components/CreateProjectDialog.js +1 -1
- package/dist/components/CreateProjectDialog.js.map +1 -1
- package/dist/components/CreateWorkspaceDialog.js +2 -2
- package/dist/components/CreateWorkspaceDialog.js.map +1 -1
- package/dist/components/InviteMemberDialog.js +2 -2
- package/dist/components/InviteMemberDialog.js.map +1 -1
- package/dist/components/MemberListItem.js +71 -86
- package/dist/components/MemberListItem.js.map +1 -1
- package/dist/components/ProjectCard.js +12 -10
- package/dist/components/ProjectCard.js.map +1 -1
- package/dist/components/WorkspaceCard.js.map +1 -1
- package/dist/components/WorkspacesErrorBoundary.js +12 -4
- package/dist/components/WorkspacesErrorBoundary.js.map +1 -1
- package/dist/components/tags/ProjectTagsWidget.js +248 -0
- package/dist/components/tags/ProjectTagsWidget.js.map +1 -0
- package/dist/generated/global-operations.js +9 -1
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/hooks/useOrgsWithPermission.js +55 -0
- package/dist/hooks/useOrgsWithPermission.js.map +1 -0
- package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
- package/dist/hooks/useWorkspacesPageView.js +6 -4
- package/dist/hooks/useWorkspacesPageView.js.map +1 -1
- package/dist/pages/CreateWorkspacePage.js +173 -149
- package/dist/pages/CreateWorkspacePage.js.map +1 -1
- package/dist/pages/InviteAcceptancePage.js +28 -28
- package/dist/pages/InviteAcceptancePage.js.map +1 -1
- package/dist/pages/MembersListPage.js +380 -352
- package/dist/pages/MembersListPage.js.map +1 -1
- package/dist/pages/ProjectDetailPage.js +96 -97
- package/dist/pages/ProjectDetailPage.js.map +1 -1
- package/dist/pages/ProjectsListPage.js +307 -304
- package/dist/pages/ProjectsListPage.js.map +1 -1
- package/dist/pages/WorkspaceSettingsPage.js +94 -91
- package/dist/pages/WorkspaceSettingsPage.js.map +1 -1
- package/dist/pages/WorkspacesListPage.js +1 -1
- package/dist/pages/WorkspacesListPage.js.map +1 -1
- package/dist/pages/dashboard/DashboardCustomizer.js +68 -68
- package/dist/pages/dashboard/DashboardCustomizer.js.map +1 -1
- package/dist/pages/dashboard/DashboardGrid.js +52 -41
- package/dist/pages/dashboard/DashboardGrid.js.map +1 -1
- package/dist/pages/dashboard/DashboardPage.js +74 -65
- package/dist/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/pages/dashboard/WidgetWrapper.js +3 -3
- package/dist/pages/dashboard/WidgetWrapper.js.map +1 -1
- package/dist/pages/dashboard/config.js +126 -30
- package/dist/pages/dashboard/config.js.map +1 -1
- package/dist/pages/dashboard/hooks/useDashboardData.js +39 -2
- package/dist/pages/dashboard/hooks/useDashboardData.js.map +1 -1
- package/dist/pages/dashboard/widgets/AgentsWidget.js +109 -0
- package/dist/pages/dashboard/widgets/AgentsWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/GroupsWidget.js +6 -5
- package/dist/pages/dashboard/widgets/GroupsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/MembersWidget.js +6 -6
- package/dist/pages/dashboard/widgets/MembersWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/ProjectsWidget.js +8 -7
- package/dist/pages/dashboard/widgets/ProjectsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js +72 -18
- package/dist/pages/dashboard/widgets/QuickActionsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js +3 -3
- package/dist/pages/dashboard/widgets/RecentActivityWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/SessionsWidget.js +78 -0
- package/dist/pages/dashboard/widgets/SessionsWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/StorageWidget.js +35 -20
- package/dist/pages/dashboard/widgets/StorageWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TagCloudWidget.js +2 -2
- package/dist/pages/dashboard/widgets/TagCloudWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/TipsWidget.js +81 -22
- package/dist/pages/dashboard/widgets/TipsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js +6 -5
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/VibesWidget.js +64 -0
- package/dist/pages/dashboard/widgets/VibesWidget.js.map +1 -0
- package/dist/pages/dashboard/widgets/WelcomeWidget.js +5 -5
- package/dist/pages/dashboard/widgets/WelcomeWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js +3 -3
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.js.map +1 -1
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js +6 -5
- package/dist/pages/dashboard/widgets/WorkspacesWidget.js.map +1 -1
- package/dist/providers/WorkspacesProvider.js +1 -1
- package/dist/providers/WorkspacesProvider.js.map +1 -1
- package/dist/store/workspacesStore.js.map +1 -1
- package/dist/utils/formatters.js +21 -16
- package/dist/utils/formatters.js.map +1 -1
- package/dist/utils/telemetryError.js +1 -1
- package/dist/utils/telemetryError.js.map +1 -1
- package/package.json +7 -7
- package/dist/WorkspacesRoot.d.ts +0 -35
- package/dist/WorkspacesRoot.d.ts.map +0 -1
- package/dist/WorkspacesRoutes.d.ts +0 -10
- package/dist/WorkspacesRoutes.d.ts.map +0 -1
- package/dist/components/CreateProjectDialog.d.ts +0 -6
- package/dist/components/CreateProjectDialog.d.ts.map +0 -1
- package/dist/components/CreateWorkspaceDialog.d.ts +0 -2
- package/dist/components/CreateWorkspaceDialog.d.ts.map +0 -1
- package/dist/components/InviteMemberDialog.d.ts +0 -7
- package/dist/components/InviteMemberDialog.d.ts.map +0 -1
- package/dist/components/MemberListItem.d.ts +0 -11
- package/dist/components/MemberListItem.d.ts.map +0 -1
- package/dist/components/ProjectCard.d.ts +0 -13
- package/dist/components/ProjectCard.d.ts.map +0 -1
- package/dist/components/WorkspaceCard.d.ts +0 -8
- package/dist/components/WorkspaceCard.d.ts.map +0 -1
- package/dist/components/WorkspacesErrorBoundary.d.ts +0 -27
- package/dist/components/WorkspacesErrorBoundary.d.ts.map +0 -1
- package/dist/components/index.d.ts +0 -8
- package/dist/components/index.d.ts.map +0 -1
- package/dist/constants/permissions.d.ts +0 -33
- package/dist/constants/permissions.d.ts.map +0 -1
- package/dist/generated/global-operations.d.ts +0 -279
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts +0 -23527
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2300
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts +0 -57851
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/hooks/index.d.ts +0 -8
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/useMemberMutations.d.ts +0 -61
- package/dist/hooks/useMemberMutations.d.ts.map +0 -1
- package/dist/hooks/useProjectMutations.d.ts +0 -26
- package/dist/hooks/useProjectMutations.d.ts.map +0 -1
- package/dist/hooks/useProjects.d.ts +0 -16
- package/dist/hooks/useProjects.d.ts.map +0 -1
- package/dist/hooks/useScopedNavigation.d.ts +0 -4
- package/dist/hooks/useScopedNavigation.d.ts.map +0 -1
- package/dist/hooks/useTenants.d.ts +0 -13
- package/dist/hooks/useTenants.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceActivity.d.ts +0 -12
- package/dist/hooks/useWorkspaceActivity.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceMembers.d.ts +0 -24
- package/dist/hooks/useWorkspaceMembers.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceMutations.d.ts +0 -36
- package/dist/hooks/useWorkspaceMutations.d.ts.map +0 -1
- package/dist/hooks/useWorkspacePermissions.d.ts +0 -29
- package/dist/hooks/useWorkspacePermissions.d.ts.map +0 -1
- package/dist/hooks/useWorkspaceRoles.d.ts +0 -8
- package/dist/hooks/useWorkspaceRoles.d.ts.map +0 -1
- package/dist/hooks/useWorkspaces.d.ts +0 -21
- package/dist/hooks/useWorkspaces.d.ts.map +0 -1
- package/dist/hooks/useWorkspacesEventEmitter.d.ts +0 -18
- package/dist/hooks/useWorkspacesEventEmitter.d.ts.map +0 -1
- package/dist/hooks/useWorkspacesPageView.d.ts +0 -27
- package/dist/hooks/useWorkspacesPageView.d.ts.map +0 -1
- package/dist/index.d.ts +0 -33
- package/dist/index.d.ts.map +0 -1
- package/dist/pages/ActivityListPage.d.ts +0 -2
- package/dist/pages/ActivityListPage.d.ts.map +0 -1
- package/dist/pages/CreateWorkspacePage.d.ts +0 -2
- package/dist/pages/CreateWorkspacePage.d.ts.map +0 -1
- package/dist/pages/InviteAcceptancePage.d.ts +0 -6
- package/dist/pages/InviteAcceptancePage.d.ts.map +0 -1
- package/dist/pages/MembersListPage.d.ts +0 -2
- package/dist/pages/MembersListPage.d.ts.map +0 -1
- package/dist/pages/ProjectDetailPage.d.ts +0 -2
- package/dist/pages/ProjectDetailPage.d.ts.map +0 -1
- package/dist/pages/ProjectsListPage.d.ts +0 -2
- package/dist/pages/ProjectsListPage.d.ts.map +0 -1
- package/dist/pages/WorkspaceDetailPage.d.ts +0 -2
- package/dist/pages/WorkspaceDetailPage.d.ts.map +0 -1
- package/dist/pages/WorkspaceSettingsPage.d.ts +0 -2
- package/dist/pages/WorkspaceSettingsPage.d.ts.map +0 -1
- package/dist/pages/WorkspacesListPage.d.ts +0 -2
- package/dist/pages/WorkspacesListPage.d.ts.map +0 -1
- package/dist/pages/dashboard/DashboardCustomizer.d.ts +0 -12
- package/dist/pages/dashboard/DashboardCustomizer.d.ts.map +0 -1
- package/dist/pages/dashboard/DashboardGrid.d.ts +0 -8
- package/dist/pages/dashboard/DashboardGrid.d.ts.map +0 -1
- package/dist/pages/dashboard/DashboardPage.d.ts +0 -14
- package/dist/pages/dashboard/DashboardPage.d.ts.map +0 -1
- package/dist/pages/dashboard/WidgetWrapper.d.ts +0 -17
- package/dist/pages/dashboard/WidgetWrapper.d.ts.map +0 -1
- package/dist/pages/dashboard/config.d.ts +0 -9
- package/dist/pages/dashboard/config.d.ts.map +0 -1
- package/dist/pages/dashboard/hooks/useDashboardData.d.ts +0 -9
- package/dist/pages/dashboard/hooks/useDashboardData.d.ts.map +0 -1
- package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts +0 -4
- package/dist/pages/dashboard/hooks/useDashboardPreferences.d.ts.map +0 -1
- package/dist/pages/dashboard/types.d.ts +0 -145
- package/dist/pages/dashboard/types.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/GroupsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/GroupsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/MembersWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/MembersWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/ProjectsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/QuickActionsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/RecentActivityWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/StorageWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/StorageWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/SystemHealthWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/SystemHealthWidget.js +0 -59
- package/dist/pages/dashboard/widgets/SystemHealthWidget.js.map +0 -1
- package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/TagCloudWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/TipsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/TipsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/UpcomingEventsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/WelcomeWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/WorkflowStatsWidget.d.ts.map +0 -1
- package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts +0 -4
- package/dist/pages/dashboard/widgets/WorkspacesWidget.d.ts.map +0 -1
- package/dist/providers/WorkspacesProvider.d.ts +0 -13
- package/dist/providers/WorkspacesProvider.d.ts.map +0 -1
- package/dist/store/workspacesStore.d.ts +0 -82
- package/dist/store/workspacesStore.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -280
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/formatters.d.ts +0 -60
- package/dist/utils/formatters.d.ts.map +0 -1
- package/dist/utils/i18n.d.ts +0 -13
- package/dist/utils/i18n.d.ts.map +0 -1
- package/dist/utils/index.d.ts +0 -3
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/nativeBridge.d.ts +0 -3
- package/dist/utils/nativeBridge.d.ts.map +0 -1
- package/dist/utils/projectTags.d.ts +0 -6
- package/dist/utils/projectTags.d.ts.map +0 -1
- package/dist/utils/slug.d.ts +0 -13
- package/dist/utils/slug.d.ts.map +0 -1
- package/dist/utils/telemetryError.d.ts +0 -2
- package/dist/utils/telemetryError.d.ts.map +0 -1
- package/dist/utils/tokenHelpers.d.ts +0 -114
- package/dist/utils/tokenHelpers.d.ts.map +0 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { WidgetWrapper as e } from "../WidgetWrapper.js";
|
|
2
|
+
import { Activity as t, ArrowRight as n, Terminal as r } from "lucide-react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
+
import { Badge as o, Button as s } from "@burdenoff/fe-libs/ui";
|
|
5
|
+
//#region src/pages/dashboard/widgets/SessionsWidget.tsx
|
|
6
|
+
var c = {
|
|
7
|
+
RUNNING: "bg-status-success-bg text-status-success-text",
|
|
8
|
+
ACTIVE: "bg-status-success-bg text-status-success-text",
|
|
9
|
+
STARTING: "bg-status-warning-bg text-status-warning-text",
|
|
10
|
+
STOPPED: "bg-text-tertiary/20 text-text-tertiary",
|
|
11
|
+
ERROR: "bg-status-error-bg text-status-error-text"
|
|
12
|
+
};
|
|
13
|
+
function l(e) {
|
|
14
|
+
if (!e) return "";
|
|
15
|
+
let t = Date.now() - new Date(e).getTime(), n = Math.floor(t / 6e4);
|
|
16
|
+
if (n < 1) return "just now";
|
|
17
|
+
if (n < 60) return `${n}m`;
|
|
18
|
+
let r = Math.floor(n / 60);
|
|
19
|
+
return r < 24 ? `${r}h` : new Date(e).toLocaleDateString(void 0, {
|
|
20
|
+
month: "short",
|
|
21
|
+
day: "numeric"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function u({ workspaceData: u, isLoading: d, navigate: f }) {
|
|
25
|
+
let p = u?.activeSessions ?? [];
|
|
26
|
+
return /* @__PURE__ */ i(e, {
|
|
27
|
+
title: "Active Sessions",
|
|
28
|
+
icon: /* @__PURE__ */ i(r, { className: "size-4" }),
|
|
29
|
+
size: "medium",
|
|
30
|
+
isLoading: d,
|
|
31
|
+
unavailable: !u,
|
|
32
|
+
headerAction: /* @__PURE__ */ a(s, {
|
|
33
|
+
variant: "ghost",
|
|
34
|
+
size: "sm",
|
|
35
|
+
className: "text-xs",
|
|
36
|
+
onClick: () => f("/vibecontrols/sessions"),
|
|
37
|
+
children: ["View all ", /* @__PURE__ */ i(n, { className: "ml-1 size-3" })]
|
|
38
|
+
}),
|
|
39
|
+
children: p.length === 0 ? /* @__PURE__ */ a("div", {
|
|
40
|
+
className: "text-center py-4",
|
|
41
|
+
children: [/* @__PURE__ */ i(t, { className: "mx-auto mb-2 size-5 text-muted-foreground" }), /* @__PURE__ */ i("p", {
|
|
42
|
+
className: "text-sm text-muted-foreground",
|
|
43
|
+
children: "No active sessions"
|
|
44
|
+
})]
|
|
45
|
+
}) : /* @__PURE__ */ i("ul", {
|
|
46
|
+
className: "space-y-1.5",
|
|
47
|
+
children: p.slice(0, 5).map((e) => /* @__PURE__ */ i("li", { children: /* @__PURE__ */ a("button", {
|
|
48
|
+
type: "button",
|
|
49
|
+
onClick: () => f(`/vibecontrols/sessions/${e.id}`),
|
|
50
|
+
className: "flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5",
|
|
51
|
+
children: [/* @__PURE__ */ a("div", {
|
|
52
|
+
className: "min-w-0 flex-1",
|
|
53
|
+
children: [/* @__PURE__ */ i("p", {
|
|
54
|
+
className: "truncate text-sm font-medium text-text-primary",
|
|
55
|
+
children: e.name || `Session ${e.id.slice(0, 8)}`
|
|
56
|
+
}), e.agentName ? /* @__PURE__ */ i("p", {
|
|
57
|
+
className: "truncate text-[11px] text-muted-foreground",
|
|
58
|
+
children: e.agentName
|
|
59
|
+
}) : null]
|
|
60
|
+
}), /* @__PURE__ */ a("div", {
|
|
61
|
+
className: "flex flex-col items-end gap-1",
|
|
62
|
+
children: [/* @__PURE__ */ i(o, {
|
|
63
|
+
variant: "outline",
|
|
64
|
+
className: `text-[10px] ${c[e.status] ?? ""}`,
|
|
65
|
+
children: e.status.toLowerCase()
|
|
66
|
+
}), e.startedAt ? /* @__PURE__ */ i("span", {
|
|
67
|
+
className: "text-[10px] text-muted-foreground",
|
|
68
|
+
children: l(e.startedAt)
|
|
69
|
+
}) : null]
|
|
70
|
+
})]
|
|
71
|
+
}) }, e.id))
|
|
72
|
+
})
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { u as SessionsWidget };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=SessionsWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/SessionsWidget.tsx"],"sourcesContent":["import { Terminal, ArrowRight, Activity } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst STATUS_BADGE: Record<string, string> = {\n RUNNING: 'bg-status-success-bg text-status-success-text',\n ACTIVE: 'bg-status-success-bg text-status-success-text',\n STARTING: 'bg-status-warning-bg text-status-warning-text',\n STOPPED: 'bg-text-tertiary/20 text-text-tertiary',\n ERROR: 'bg-status-error-bg text-status-error-text',\n};\n\nfunction formatRelative(dateString: string | null | undefined): string {\n if (!dateString) return '';\n const diffMs = Date.now() - new Date(dateString).getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return `${diffMin}m`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${diffHr}h`;\n return new Date(dateString).toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n });\n}\n\nexport function SessionsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const sessions = workspaceData?.activeSessions ?? [];\n\n return (\n <WidgetWrapper\n title=\"Active Sessions\"\n icon={<Terminal className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/vibecontrols/sessions')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {sessions.length === 0 ? (\n <div className=\"text-center py-4\">\n <Activity className=\"mx-auto mb-2 size-5 text-muted-foreground\" />\n <p className=\"text-sm text-muted-foreground\">No active sessions</p>\n </div>\n ) : (\n <ul className=\"space-y-1.5\">\n {sessions.slice(0, 5).map((s) => (\n <li key={s.id}>\n <button\n type=\"button\"\n onClick={() => navigate(`/vibecontrols/sessions/${s.id}`)}\n className=\"flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5\"\n >\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {s.name || `Session ${s.id.slice(0, 8)}`}\n </p>\n {s.agentName ? (\n <p className=\"truncate text-[11px] text-muted-foreground\">{s.agentName}</p>\n ) : null}\n </div>\n <div className=\"flex flex-col items-end gap-1\">\n <Badge\n variant=\"outline\"\n className={`text-[10px] ${STATUS_BADGE[s.status] ?? ''}`}\n >\n {s.status.toLowerCase()}\n </Badge>\n {s.startedAt ? (\n <span className=\"text-[10px] text-muted-foreground\">\n {formatRelative(s.startedAt)}\n </span>\n ) : null}\n </div>\n </button>\n </li>\n ))}\n </ul>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAuC;CAC3C,SAAS;CACT,QAAQ;CACR,UAAU;CACV,SAAS;CACT,OAAO;CACR;AAED,SAAS,EAAe,GAA+C;AACrE,KAAI,CAAC,EAAY,QAAO;CACxB,IAAM,IAAS,KAAK,KAAK,GAAG,IAAI,KAAK,EAAW,CAAC,SAAS,EACpD,IAAU,KAAK,MAAM,IAAS,IAAM;AAC1C,KAAI,IAAU,EAAG,QAAO;AACxB,KAAI,IAAU,GAAI,QAAO,GAAG,EAAQ;CACpC,IAAM,IAAS,KAAK,MAAM,IAAU,GAAG;AAEvC,QADI,IAAS,KAAW,GAAG,EAAO,KAC3B,IAAI,KAAK,EAAW,CAAC,mBAAmB,KAAA,GAAW;EACxD,OAAO;EACP,KAAK;EACN,CAAC;;AAGJ,SAAgB,EAAe,EAAE,kBAAe,cAAW,eAAyB;CAClF,IAAM,IAAW,GAAe,kBAAkB,EAAE;AAEpD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,yBAAyB;aAJnD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAS,WAAW,IACnB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAU,WAAU,6CAA8C,CAAA,EAClE,kBAAC,KAAD;IAAG,WAAU;cAAgC;IAAsB,CAAA,CAC/D;OAEN,kBAAC,MAAD;GAAI,WAAU;aACX,EAAS,MAAM,GAAG,EAAE,CAAC,KAAK,MACzB,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,0BAA0B,EAAE,KAAK;IACzD,WAAU;cAHZ,CAKE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAE,QAAQ,WAAW,EAAE,GAAG,MAAM,GAAG,EAAE;MACpC,CAAA,EACH,EAAE,YACD,kBAAC,KAAD;MAAG,WAAU;gBAA8C,EAAE;MAAc,CAAA,GACzE,KACA;QACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,SAAQ;MACR,WAAW,eAAe,EAAa,EAAE,WAAW;gBAEnD,EAAE,OAAO,aAAa;MACjB,CAAA,EACP,EAAE,YACD,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAe,EAAE,UAAU;MACvB,CAAA,GACL,KACA;OACC;OACN,EA5BI,EAAE,GA4BN,CACL;GACC,CAAA;EAEO,CAAA"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { WidgetWrapper as e } from "../WidgetWrapper.js";
|
|
2
2
|
import { HardDrive as t } from "lucide-react";
|
|
3
3
|
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
4
|
+
import { useUpgradePrompt as i } from "@burdenoff/fe-libs/shared/hooks";
|
|
4
5
|
//#region src/pages/dashboard/widgets/StorageWidget.tsx
|
|
5
|
-
|
|
6
|
+
var a = 50 * 1024 * 1024, o = 5 * 1024 * 1024 * 1024;
|
|
7
|
+
function s(e) {
|
|
6
8
|
if (e === 0) return "0 B";
|
|
7
9
|
let t = 1024, n = [
|
|
8
10
|
"B",
|
|
@@ -13,14 +15,26 @@ function i(e) {
|
|
|
13
15
|
], r = Math.floor(Math.log(e) / Math.log(t));
|
|
14
16
|
return `${parseFloat((e / t ** +r).toFixed(1))} ${n[r]}`;
|
|
15
17
|
}
|
|
16
|
-
function
|
|
17
|
-
let
|
|
18
|
+
function c(e, t) {
|
|
19
|
+
let n = 1024, r = [
|
|
20
|
+
"B",
|
|
21
|
+
"KB",
|
|
22
|
+
"MB",
|
|
23
|
+
"GB",
|
|
24
|
+
"TB"
|
|
25
|
+
];
|
|
26
|
+
if (t <= 0) return s(e);
|
|
27
|
+
let i = Math.min(Math.floor(Math.log(t) / Math.log(n)), r.length - 1), a = e / n ** +i;
|
|
28
|
+
return `${Number.isInteger(a) ? a.toString() : a.toFixed(1)} ${r[i]}`;
|
|
29
|
+
}
|
|
30
|
+
function l({ workspaceData: l, isLoading: u }) {
|
|
31
|
+
let { isFree: d } = i({ resource: "storage" }), f = l?.storageUsage, p = d ? a : o, m = f?.usedBytes ?? 0, h = f?.totalBytes && f.totalBytes > 0 ? f.totalBytes : p, g = h > 0 ? Math.min(m / h * 100, 100) : 0, _ = g > 80 ? "bg-status-error-bg" : g > 60 ? "bg-status-warning-bg" : "bg-status-success-bg";
|
|
18
32
|
return /* @__PURE__ */ n(e, {
|
|
19
33
|
title: "Storage",
|
|
20
|
-
icon: /* @__PURE__ */ n(t, { className: "
|
|
34
|
+
icon: /* @__PURE__ */ n(t, { className: "size-4" }),
|
|
21
35
|
size: "small",
|
|
22
|
-
isLoading:
|
|
23
|
-
children:
|
|
36
|
+
isLoading: u,
|
|
37
|
+
children: /* @__PURE__ */ r("div", {
|
|
24
38
|
className: "space-y-3",
|
|
25
39
|
children: [/* @__PURE__ */ r("div", {
|
|
26
40
|
className: "space-y-1.5",
|
|
@@ -28,42 +42,43 @@ function a({ workspaceData: a, isLoading: o }) {
|
|
|
28
42
|
/* @__PURE__ */ r("div", {
|
|
29
43
|
className: "flex justify-between text-xs",
|
|
30
44
|
children: [/* @__PURE__ */ n("span", {
|
|
31
|
-
className: "text-
|
|
45
|
+
className: "text-text-secondary",
|
|
32
46
|
children: "Used"
|
|
33
47
|
}), /* @__PURE__ */ r("span", {
|
|
34
48
|
className: "font-medium text-text-primary",
|
|
35
|
-
children: [
|
|
49
|
+
children: [
|
|
50
|
+
c(m, h),
|
|
51
|
+
" / ",
|
|
52
|
+
s(h)
|
|
53
|
+
]
|
|
36
54
|
})]
|
|
37
55
|
}),
|
|
38
56
|
/* @__PURE__ */ n("div", {
|
|
39
|
-
className: "h-2 w-full bg-
|
|
57
|
+
className: "h-2 w-full bg-bg-canvas rounded-full overflow-hidden",
|
|
40
58
|
children: /* @__PURE__ */ n("div", {
|
|
41
|
-
className: `h-full rounded-full ${
|
|
42
|
-
style: { width: `${
|
|
59
|
+
className: `h-full rounded-full ${_} transition-all duration-500`,
|
|
60
|
+
style: { width: `${g}%` }
|
|
43
61
|
})
|
|
44
62
|
}),
|
|
45
63
|
/* @__PURE__ */ n("p", {
|
|
46
|
-
className: "text-[11px] text-
|
|
47
|
-
children:
|
|
64
|
+
className: "text-[11px] text-text-secondary text-right",
|
|
65
|
+
children: `${g.toFixed(1)}% used`
|
|
48
66
|
})
|
|
49
67
|
]
|
|
50
|
-
}),
|
|
68
|
+
}), f?.fileCount != null && /* @__PURE__ */ r("div", {
|
|
51
69
|
className: "flex items-center justify-between text-xs",
|
|
52
70
|
children: [/* @__PURE__ */ n("span", {
|
|
53
|
-
className: "text-
|
|
71
|
+
className: "text-text-secondary",
|
|
54
72
|
children: "Total files"
|
|
55
73
|
}), /* @__PURE__ */ n("span", {
|
|
56
74
|
className: "font-medium text-text-primary",
|
|
57
|
-
children:
|
|
75
|
+
children: f.fileCount.toLocaleString()
|
|
58
76
|
})]
|
|
59
77
|
})]
|
|
60
|
-
}) : /* @__PURE__ */ n("p", {
|
|
61
|
-
className: "text-xs text-muted-foreground",
|
|
62
|
-
children: "Storage metrics are unavailable."
|
|
63
78
|
})
|
|
64
79
|
});
|
|
65
80
|
}
|
|
66
81
|
//#endregion
|
|
67
|
-
export {
|
|
82
|
+
export { l as StorageWidget };
|
|
68
83
|
|
|
69
84
|
//# sourceMappingURL=StorageWidget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/StorageWidget.tsx"],"sourcesContent":["import { HardDrive } from 'lucide-react';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n}\n\nexport function StorageWidget({ workspaceData, isLoading }: WidgetProps) {\n const storage = workspaceData?.storageUsage;\n\n const usedBytes = storage?.usedBytes ?? 0;\n const totalBytes
|
|
1
|
+
{"version":3,"file":"StorageWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/StorageWidget.tsx"],"sourcesContent":["import { HardDrive } from 'lucide-react';\nimport { useUpgradePrompt } from '@burdenoff/fe-libs/shared/hooks';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst FREE_TIER_TOTAL_BYTES = 50 * 1024 * 1024; // 50 MB\nconst PAID_TIER_TOTAL_BYTES = 5 * 1024 * 1024 * 1024; // 5 GB\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) {\n // For 0 we want to render the unit the user will see for the total\n // (e.g. \"0 MB / 50 MB\"), so let the caller pick a unit explicitly.\n return '0 B';\n }\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n}\n\n/**\n * Pick the display unit of the *total* so the \"used / total\" line is\n * consistent (e.g. \"0 MB / 50 MB\" not \"0 B / 50 MB\").\n */\nfunction formatBytesAs(bytes: number, totalBytes: number): string {\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];\n if (totalBytes <= 0) return formatBytes(bytes);\n const totalIdx = Math.min(Math.floor(Math.log(totalBytes) / Math.log(k)), sizes.length - 1);\n const value = bytes / Math.pow(k, totalIdx);\n // Render as integer when exact (e.g. 0, 50); else one decimal.\n const rendered = Number.isInteger(value) ? value.toString() : value.toFixed(1);\n return `${rendered} ${sizes[totalIdx]}`;\n}\n\nexport function StorageWidget({ workspaceData, isLoading }: WidgetProps) {\n const { isFree } = useUpgradePrompt({ resource: 'storage' });\n const storage = workspaceData?.storageUsage;\n\n // Fall back to plan-tier defaults when the backend hasn't reported usage\n // yet. Storage is core, so \"metrics unavailable\" is not an acceptable UX.\n const fallbackTotalBytes = isFree ? FREE_TIER_TOTAL_BYTES : PAID_TIER_TOTAL_BYTES;\n const usedBytes = storage?.usedBytes ?? 0;\n const totalBytes =\n storage?.totalBytes && storage.totalBytes > 0 ? storage.totalBytes : fallbackTotalBytes;\n const percentage = totalBytes > 0 ? Math.min((usedBytes / totalBytes) * 100, 100) : 0;\n const barColor =\n percentage > 80\n ? 'bg-status-error-bg'\n : percentage > 60\n ? 'bg-status-warning-bg'\n : 'bg-status-success-bg';\n\n return (\n <WidgetWrapper\n title=\"Storage\"\n icon={<HardDrive className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n >\n <div className=\"space-y-3\">\n <div className=\"space-y-1.5\">\n <div className=\"flex justify-between text-xs\">\n <span className=\"text-text-secondary\">Used</span>\n <span className=\"font-medium text-text-primary\">\n {formatBytesAs(usedBytes, totalBytes)} / {formatBytes(totalBytes)}\n </span>\n </div>\n <div className=\"h-2 w-full bg-bg-canvas rounded-full overflow-hidden\">\n <div\n className={`h-full rounded-full ${barColor} transition-all duration-500`}\n style={{ width: `${percentage}%` }}\n />\n </div>\n <p className=\"text-[11px] text-text-secondary text-right\">\n {`${percentage.toFixed(1)}% used`}\n </p>\n </div>\n {storage?.fileCount != null && (\n <div className=\"flex items-center justify-between text-xs\">\n <span className=\"text-text-secondary\">Total files</span>\n <span className=\"font-medium text-text-primary\">\n {storage.fileCount.toLocaleString()}\n </span>\n </div>\n )}\n </div>\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAwB,KAAK,OAAO,MACpC,IAAwB,IAAI,OAAO,OAAO;AAEhD,SAAS,EAAY,GAAuB;AAC1C,KAAI,MAAU,EAGZ,QAAO;CAET,IAAM,IAAI,MACJ,IAAQ;EAAC;EAAK;EAAM;EAAM;EAAM;EAAK,EACrC,IAAI,KAAK,MAAM,KAAK,IAAI,EAAM,GAAG,KAAK,IAAI,EAAE,CAAC;AACnD,QAAO,GAAG,YAAY,IAAiB,MAAG,GAAI,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAM;;AAOrE,SAAS,EAAc,GAAe,GAA4B;CAChE,IAAM,IAAI,MACJ,IAAQ;EAAC;EAAK;EAAM;EAAM;EAAM;EAAK;AAC3C,KAAI,KAAc,EAAG,QAAO,EAAY,EAAM;CAC9C,IAAM,IAAW,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,EAAW,GAAG,KAAK,IAAI,EAAE,CAAC,EAAE,EAAM,SAAS,EAAE,EACrF,IAAQ,IAAiB,MAAG;AAGlC,QAAO,GADU,OAAO,UAAU,EAAM,GAAG,EAAM,UAAU,GAAG,EAAM,QAAQ,EAAE,CAC3D,GAAG,EAAM;;AAG9B,SAAgB,EAAc,EAAE,kBAAe,gBAA0B;CACvE,IAAM,EAAE,cAAW,EAAiB,EAAE,UAAU,WAAW,CAAC,EACtD,IAAU,GAAe,cAIzB,IAAqB,IAAS,IAAwB,GACtD,IAAY,GAAS,aAAa,GAClC,IACJ,GAAS,cAAc,EAAQ,aAAa,IAAI,EAAQ,aAAa,GACjE,IAAa,IAAa,IAAI,KAAK,IAAK,IAAY,IAAc,KAAK,IAAI,GAAG,GAC9E,IACJ,IAAa,KACT,uBACA,IAAa,KACX,yBACA;AAER,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA;EACtC,MAAK;EACM;YAEX,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD;OAAM,WAAU;iBAAsB;OAAW,CAAA,EACjD,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QACG,EAAc,GAAW,EAAW;QAAC;QAAI,EAAY,EAAW;QAC5D;SACH;;KACN,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,OAAD;OACE,WAAW,uBAAuB,EAAS;OAC3C,OAAO,EAAE,OAAO,GAAG,EAAW,IAAI;OAClC,CAAA;MACE,CAAA;KACN,kBAAC,KAAD;MAAG,WAAU;gBACV,GAAG,EAAW,QAAQ,EAAE,CAAC;MACxB,CAAA;KACA;OACL,GAAS,aAAa,QACrB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAU;eAAsB;KAAkB,CAAA,EACxD,kBAAC,QAAD;KAAM,WAAU;eACb,EAAQ,UAAU,gBAAgB;KAC9B,CAAA,CACH;MAEJ;;EACQ,CAAA"}
|
|
@@ -17,7 +17,7 @@ function c({ workspaceData: c, isLoading: l, navigate: u }) {
|
|
|
17
17
|
let d = c?.tags.items ?? [], f = c?.tags.total ?? 0;
|
|
18
18
|
return /* @__PURE__ */ r(e, {
|
|
19
19
|
title: "Tags",
|
|
20
|
-
icon: /* @__PURE__ */ r(n, { className: "
|
|
20
|
+
icon: /* @__PURE__ */ r(n, { className: "size-4" }),
|
|
21
21
|
size: "small",
|
|
22
22
|
isLoading: l,
|
|
23
23
|
unavailable: !c,
|
|
@@ -26,7 +26,7 @@ function c({ workspaceData: c, isLoading: l, navigate: u }) {
|
|
|
26
26
|
size: "sm",
|
|
27
27
|
className: "text-xs",
|
|
28
28
|
onClick: () => u("/tags"),
|
|
29
|
-
children: /* @__PURE__ */ r(t, { className: "
|
|
29
|
+
children: /* @__PURE__ */ r(t, { className: "size-3" })
|
|
30
30
|
}),
|
|
31
31
|
children: d.length === 0 ? /* @__PURE__ */ r("div", {
|
|
32
32
|
className: "text-center py-3",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TagCloudWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/TagCloudWidget.tsx"],"sourcesContent":["import { Tags, ArrowRight } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst tagColors = [\n 'bg-status-info-bg-subtle text-status-info-text border-border-default',\n 'bg-status-success-bg-subtle text-status-success-text border-border-default',\n 'bg-accent-purple-subtle text-accent-purple border-border-default',\n 'bg-status-warning-bg-subtle text-status-warning-text border-border-default',\n 'bg-accent-pink-subtle text-accent-pink border-border-default',\n 'bg-accent-cyan-subtle text-accent-cyan border-border-default',\n 'bg-accent-orange-subtle text-accent-orange border-border-default',\n 'bg-accent-rose-subtle text-accent-rose border-border-default',\n];\n\nexport function TagCloudWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const tags = workspaceData?.tags.items ?? [];\n const total = workspaceData?.tags.total ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Tags\"\n icon={<Tags className=\"
|
|
1
|
+
{"version":3,"file":"TagCloudWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/TagCloudWidget.tsx"],"sourcesContent":["import { Tags, ArrowRight } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nconst tagColors = [\n 'bg-status-info-bg-subtle text-status-info-text border-border-default',\n 'bg-status-success-bg-subtle text-status-success-text border-border-default',\n 'bg-accent-purple-subtle text-accent-purple border-border-default',\n 'bg-status-warning-bg-subtle text-status-warning-text border-border-default',\n 'bg-accent-pink-subtle text-accent-pink border-border-default',\n 'bg-accent-cyan-subtle text-accent-cyan border-border-default',\n 'bg-accent-orange-subtle text-accent-orange border-border-default',\n 'bg-accent-rose-subtle text-accent-rose border-border-default',\n];\n\nexport function TagCloudWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const tags = workspaceData?.tags.items ?? [];\n const total = workspaceData?.tags.total ?? 0;\n\n return (\n <WidgetWrapper\n title=\"Tags\"\n icon={<Tags className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button variant=\"ghost\" size=\"sm\" className=\"text-xs\" onClick={() => navigate('/tags')}>\n <ArrowRight className=\"size-3\" />\n </Button>\n }\n >\n {tags.length === 0 ? (\n <div className=\"text-center py-3\">\n <p className=\"text-xs text-muted-foreground\">No tags created yet</p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n <div className=\"flex flex-wrap gap-1.5\">\n {tags.slice(0, 12).map((tag, idx) => (\n <Badge\n key={tag.id}\n variant=\"outline\"\n className={`text-[11px] cursor-pointer hover:opacity-80 transition-opacity ${tagColors[idx % tagColors.length]}`}\n onClick={() => navigate('/tags')}\n >\n {tag.label}\n </Badge>\n ))}\n </div>\n {total > 12 && (\n <p className=\"text-[11px] text-muted-foreground text-center\">+{total - 12} more tags</p>\n )}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,IAAM,IAAY;CAChB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAgB,EAAe,EAAE,kBAAe,cAAW,eAAyB;CAClF,IAAM,IAAO,GAAe,KAAK,SAAS,EAAE,EACtC,IAAQ,GAAe,KAAK,SAAS;AAE3C,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA;EACjC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GAAQ,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAU,eAAe,EAAS,QAAQ;aACpF,kBAAC,GAAD,EAAY,WAAU,UAAW,CAAA;GAC1B,CAAA;YAGV,EAAK,WAAW,IACf,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,KAAD;IAAG,WAAU;cAAgC;IAAuB,CAAA;GAChE,CAAA,GAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAK,MAAM,GAAG,GAAG,CAAC,KAAK,GAAK,MAC3B,kBAAC,GAAD;KAEE,SAAQ;KACR,WAAW,kEAAkE,EAAU,IAAM,EAAU;KACvG,eAAe,EAAS,QAAQ;eAE/B,EAAI;KACC,EAND,EAAI,GAMH,CACR;IACE,CAAA,EACL,IAAQ,MACP,kBAAC,KAAD;IAAG,WAAU;cAAb;KAA6D;KAAE,IAAQ;KAAG;KAAc;MAEtF;;EAEM,CAAA"}
|
|
@@ -1,67 +1,126 @@
|
|
|
1
1
|
import { WidgetWrapper as e } from "../WidgetWrapper.js";
|
|
2
|
-
import { BookOpen as t, ExternalLink as n, Lightbulb as r,
|
|
3
|
-
import { jsx as
|
|
2
|
+
import { BookOpen as t, ExternalLink as n, Lightbulb as r, Newspaper as i, Puzzle as a, Rocket as o, Shield as s, Sparkles as c, Users as l, Workflow as u } from "lucide-react";
|
|
3
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
4
4
|
//#region src/pages/dashboard/widgets/TipsWidget.tsx
|
|
5
|
-
var
|
|
5
|
+
var p = [
|
|
6
|
+
{
|
|
7
|
+
icon: t,
|
|
8
|
+
title: "Read the docs",
|
|
9
|
+
description: "Guides, references, and tutorials at docs.vibecontrols.com.",
|
|
10
|
+
href: "https://docs.vibecontrols.com",
|
|
11
|
+
external: !0,
|
|
12
|
+
color: "text-accent-blue"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
icon: l,
|
|
16
|
+
title: "Join the community",
|
|
17
|
+
description: "Ask questions, share workflows, and chat with the team.",
|
|
18
|
+
href: "https://community.vibecontrols.com",
|
|
19
|
+
external: !0,
|
|
20
|
+
color: "text-accent-purple"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
icon: a,
|
|
24
|
+
title: "Browse plugins",
|
|
25
|
+
description: "50+ plugins for terminals, AI, tunnels, sandboxes, and more.",
|
|
26
|
+
href: "/vibecontrols/plugins",
|
|
27
|
+
color: "text-status-success-text"
|
|
28
|
+
},
|
|
6
29
|
{
|
|
7
30
|
icon: i,
|
|
31
|
+
title: "Latest from the blog",
|
|
32
|
+
description: "Product updates, deep dives, and engineering posts.",
|
|
33
|
+
href: "https://vibecontrols.com/blog",
|
|
34
|
+
external: !0,
|
|
35
|
+
color: "text-status-warning-text"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
icon: c,
|
|
39
|
+
title: "Feature previews",
|
|
40
|
+
description: "Try opt-in features before they ship to everyone.",
|
|
41
|
+
href: "/feature-previews",
|
|
42
|
+
color: "text-accent-pink"
|
|
43
|
+
}
|
|
44
|
+
], m = [
|
|
45
|
+
{
|
|
46
|
+
icon: o,
|
|
8
47
|
title: "Create your first workspace",
|
|
9
48
|
description: "Organize your team with a dedicated workspace.",
|
|
10
|
-
|
|
49
|
+
href: "/workspaces/list",
|
|
11
50
|
color: "text-accent-blue"
|
|
12
51
|
},
|
|
13
52
|
{
|
|
14
|
-
icon:
|
|
53
|
+
icon: u,
|
|
15
54
|
title: "Automate with workflows",
|
|
16
55
|
description: "Build automation workflows to streamline your processes.",
|
|
17
|
-
|
|
56
|
+
href: "/workflows",
|
|
18
57
|
color: "text-status-success-text"
|
|
19
58
|
},
|
|
20
59
|
{
|
|
21
|
-
icon:
|
|
60
|
+
icon: s,
|
|
22
61
|
title: "Set up permissions",
|
|
23
62
|
description: "Configure role-based access for your workspace members.",
|
|
24
|
-
|
|
63
|
+
href: "/rbac",
|
|
25
64
|
color: "text-accent-purple"
|
|
26
65
|
},
|
|
27
66
|
{
|
|
28
67
|
icon: t,
|
|
29
68
|
title: "Explore the API",
|
|
30
69
|
description: "Check out our developer portal for API documentation.",
|
|
31
|
-
|
|
70
|
+
href: "/devportal",
|
|
32
71
|
color: "text-status-warning-text"
|
|
33
72
|
}
|
|
34
73
|
];
|
|
35
|
-
function
|
|
36
|
-
return
|
|
74
|
+
function h(e) {
|
|
75
|
+
return e === "vibecontrols" ? p : m;
|
|
76
|
+
}
|
|
77
|
+
function g({ navigate: t, isLoading: i, productId: a }) {
|
|
78
|
+
let o = h(a);
|
|
79
|
+
return /* @__PURE__ */ d(e, {
|
|
37
80
|
title: "Tips & Resources",
|
|
38
|
-
icon: /* @__PURE__ */
|
|
81
|
+
icon: /* @__PURE__ */ d(r, { className: "size-4" }),
|
|
39
82
|
size: "small",
|
|
40
83
|
isLoading: i,
|
|
41
|
-
children: /* @__PURE__ */
|
|
84
|
+
children: /* @__PURE__ */ d("div", {
|
|
42
85
|
className: "space-y-2",
|
|
43
|
-
children:
|
|
44
|
-
|
|
45
|
-
|
|
86
|
+
children: o.map((e) => e.external ? /* @__PURE__ */ f("a", {
|
|
87
|
+
href: e.href,
|
|
88
|
+
target: "_blank",
|
|
89
|
+
rel: "noopener noreferrer",
|
|
90
|
+
className: "w-full flex items-start gap-2 p-1.5 rounded hover:bg-accent/5 transition-colors text-left",
|
|
46
91
|
children: [
|
|
47
|
-
/* @__PURE__ */
|
|
48
|
-
/* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ d(e.icon, { className: `size-4 mt-0.5 shrink-0 ${e.color}` }),
|
|
93
|
+
/* @__PURE__ */ f("div", {
|
|
49
94
|
className: "min-w-0",
|
|
50
|
-
children: [/* @__PURE__ */
|
|
95
|
+
children: [/* @__PURE__ */ d("p", {
|
|
51
96
|
className: "text-xs font-medium text-text-primary leading-tight",
|
|
52
97
|
children: e.title
|
|
53
|
-
}), /* @__PURE__ */
|
|
98
|
+
}), /* @__PURE__ */ d("p", {
|
|
54
99
|
className: "text-[11px] text-muted-foreground leading-tight mt-0.5",
|
|
55
100
|
children: e.description
|
|
56
101
|
})]
|
|
57
102
|
}),
|
|
58
|
-
/* @__PURE__ */
|
|
103
|
+
/* @__PURE__ */ d(n, { className: "size-3 text-muted-foreground shrink-0 mt-0.5" })
|
|
59
104
|
]
|
|
105
|
+
}, e.title) : /* @__PURE__ */ f("button", {
|
|
106
|
+
type: "button",
|
|
107
|
+
className: "w-full flex items-start gap-2 p-1.5 rounded hover:bg-accent/5 cursor-pointer transition-colors text-left",
|
|
108
|
+
onClick: () => t(e.href),
|
|
109
|
+
children: [/* @__PURE__ */ d(e.icon, { className: `size-4 mt-0.5 shrink-0 ${e.color}` }), /* @__PURE__ */ f("div", {
|
|
110
|
+
className: "min-w-0",
|
|
111
|
+
children: [/* @__PURE__ */ d("p", {
|
|
112
|
+
className: "text-xs font-medium text-text-primary leading-tight",
|
|
113
|
+
children: e.title
|
|
114
|
+
}), /* @__PURE__ */ d("p", {
|
|
115
|
+
className: "text-[11px] text-muted-foreground leading-tight mt-0.5",
|
|
116
|
+
children: e.description
|
|
117
|
+
})]
|
|
118
|
+
})]
|
|
60
119
|
}, e.title))
|
|
61
120
|
})
|
|
62
121
|
});
|
|
63
122
|
}
|
|
64
123
|
//#endregion
|
|
65
|
-
export {
|
|
124
|
+
export { g as TipsWidget };
|
|
66
125
|
|
|
67
126
|
//# sourceMappingURL=TipsWidget.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TipsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/TipsWidget.tsx"],"sourcesContent":["import { Lightbulb
|
|
1
|
+
{"version":3,"file":"TipsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/TipsWidget.tsx"],"sourcesContent":["import type { LucideIcon } from 'lucide-react';\nimport {\n Lightbulb,\n ExternalLink,\n BookOpen,\n Rocket,\n Shield,\n Workflow,\n Users,\n Puzzle,\n Newspaper,\n Sparkles,\n} from 'lucide-react';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\ninterface Tip {\n icon: LucideIcon;\n title: string;\n description: string;\n href: string;\n external?: boolean;\n color: string;\n}\n\nconst VIBECONTROLS_TIPS: Tip[] = [\n {\n icon: BookOpen,\n title: 'Read the docs',\n description: 'Guides, references, and tutorials at docs.vibecontrols.com.',\n href: 'https://docs.vibecontrols.com',\n external: true,\n color: 'text-accent-blue',\n },\n {\n icon: Users,\n title: 'Join the community',\n description: 'Ask questions, share workflows, and chat with the team.',\n href: 'https://community.vibecontrols.com',\n external: true,\n color: 'text-accent-purple',\n },\n {\n icon: Puzzle,\n title: 'Browse plugins',\n description: '50+ plugins for terminals, AI, tunnels, sandboxes, and more.',\n href: '/vibecontrols/plugins',\n color: 'text-status-success-text',\n },\n {\n icon: Newspaper,\n title: 'Latest from the blog',\n description: 'Product updates, deep dives, and engineering posts.',\n href: 'https://vibecontrols.com/blog',\n external: true,\n color: 'text-status-warning-text',\n },\n {\n icon: Sparkles,\n title: 'Feature previews',\n description: 'Try opt-in features before they ship to everyone.',\n href: '/feature-previews',\n color: 'text-accent-pink',\n },\n];\n\nconst WORKSPACES_TIPS: Tip[] = [\n {\n icon: Rocket,\n title: 'Create your first workspace',\n description: 'Organize your team with a dedicated workspace.',\n href: '/workspaces/list',\n color: 'text-accent-blue',\n },\n {\n icon: Workflow,\n title: 'Automate with workflows',\n description: 'Build automation workflows to streamline your processes.',\n href: '/workflows',\n color: 'text-status-success-text',\n },\n {\n icon: Shield,\n title: 'Set up permissions',\n description: 'Configure role-based access for your workspace members.',\n href: '/rbac',\n color: 'text-accent-purple',\n },\n {\n icon: BookOpen,\n title: 'Explore the API',\n description: 'Check out our developer portal for API documentation.',\n href: '/devportal',\n color: 'text-status-warning-text',\n },\n];\n\nfunction pickTips(productId?: string): Tip[] {\n if (productId === 'vibecontrols') return VIBECONTROLS_TIPS;\n return WORKSPACES_TIPS;\n}\n\nexport function TipsWidget({ navigate, isLoading, productId }: WidgetProps) {\n const tips = pickTips(productId);\n\n return (\n <WidgetWrapper\n title=\"Tips & Resources\"\n icon={<Lightbulb className=\"size-4\" />}\n size=\"small\"\n isLoading={isLoading}\n >\n <div className=\"space-y-2\">\n {tips.map((tip) =>\n tip.external ? (\n <a\n key={tip.title}\n href={tip.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"w-full flex items-start gap-2 p-1.5 rounded hover:bg-accent/5 transition-colors text-left\"\n >\n <tip.icon className={`size-4 mt-0.5 shrink-0 ${tip.color}`} />\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-text-primary leading-tight\">{tip.title}</p>\n <p className=\"text-[11px] text-muted-foreground leading-tight mt-0.5\">\n {tip.description}\n </p>\n </div>\n <ExternalLink className=\"size-3 text-muted-foreground shrink-0 mt-0.5\" />\n </a>\n ) : (\n <button\n key={tip.title}\n type=\"button\"\n className=\"w-full flex items-start gap-2 p-1.5 rounded hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate(tip.href)}\n >\n <tip.icon className={`size-4 mt-0.5 shrink-0 ${tip.color}`} />\n <div className=\"min-w-0\">\n <p className=\"text-xs font-medium text-text-primary leading-tight\">{tip.title}</p>\n <p className=\"text-[11px] text-muted-foreground leading-tight mt-0.5\">\n {tip.description}\n </p>\n </div>\n </button>\n )\n )}\n </div>\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;AAyBA,IAAM,IAA2B;CAC/B;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,UAAU;EACV,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,UAAU;EACV,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,UAAU;EACV,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,OAAO;EACR;CACF,EAEK,IAAyB;CAC7B;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,OAAO;EACR;CACD;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,MAAM;EACN,OAAO;EACR;CACF;AAED,SAAS,EAAS,GAA2B;AAE3C,QADI,MAAc,iBAAuB,IAClC;;AAGT,SAAgB,EAAW,EAAE,aAAU,cAAW,gBAA0B;CAC1E,IAAM,IAAO,EAAS,EAAU;AAEhC,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA;EACtC,MAAK;EACM;YAEX,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAK,KAAK,MACT,EAAI,WACF,kBAAC,KAAD;IAEE,MAAM,EAAI;IACV,QAAO;IACP,KAAI;IACJ,WAAU;cALZ;KAOE,kBAAC,EAAI,MAAL,EAAU,WAAW,0BAA0B,EAAI,SAAW,CAAA;KAC9D,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAuD,EAAI;OAAU,CAAA,EAClF,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAI;OACH,CAAA,CACA;;KACN,kBAAC,GAAD,EAAc,WAAU,gDAAiD,CAAA;KACvE;MAdG,EAAI,MAcP,GAEJ,kBAAC,UAAD;IAEE,MAAK;IACL,WAAU;IACV,eAAe,EAAS,EAAI,KAAK;cAJnC,CAME,kBAAC,EAAI,MAAL,EAAU,WAAW,0BAA0B,EAAI,SAAW,CAAA,EAC9D,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,KAAD;MAAG,WAAU;gBAAuD,EAAI;MAAU,CAAA,EAClF,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAI;MACH,CAAA,CACA;OACC;MAZF,EAAI,MAYF,CAEZ;GACG,CAAA;EACQ,CAAA"}
|
|
@@ -24,7 +24,7 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
|
|
|
24
24
|
let f = l?.upcomingEvents ?? [];
|
|
25
25
|
return /* @__PURE__ */ i(e, {
|
|
26
26
|
title: "Upcoming Events",
|
|
27
|
-
icon: /* @__PURE__ */ i(n, { className: "
|
|
27
|
+
icon: /* @__PURE__ */ i(n, { className: "size-4" }),
|
|
28
28
|
size: "medium",
|
|
29
29
|
isLoading: u,
|
|
30
30
|
unavailable: !l,
|
|
@@ -33,7 +33,7 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
|
|
|
33
33
|
size: "sm",
|
|
34
34
|
className: "text-xs",
|
|
35
35
|
onClick: () => d("/calendar"),
|
|
36
|
-
children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1
|
|
36
|
+
children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1 size-3" })]
|
|
37
37
|
}),
|
|
38
38
|
children: f.length === 0 ? /* @__PURE__ */ a("div", {
|
|
39
39
|
className: "text-center py-4",
|
|
@@ -49,13 +49,14 @@ function l({ workspaceData: l, isLoading: u, navigate: d }) {
|
|
|
49
49
|
})]
|
|
50
50
|
}) : /* @__PURE__ */ i("div", {
|
|
51
51
|
className: "space-y-2",
|
|
52
|
-
children: f.map((e) => /* @__PURE__ */ a("
|
|
53
|
-
|
|
52
|
+
children: f.map((e) => /* @__PURE__ */ a("button", {
|
|
53
|
+
type: "button",
|
|
54
|
+
className: "w-full flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left",
|
|
54
55
|
onClick: () => d("/calendar"),
|
|
55
56
|
children: [
|
|
56
57
|
/* @__PURE__ */ i("div", {
|
|
57
58
|
className: "rounded-md bg-accent-pink-subtle text-accent-pink p-1.5 shrink-0",
|
|
58
|
-
children: /* @__PURE__ */ i(r, { className: "
|
|
59
|
+
children: /* @__PURE__ */ i(r, { className: "size-3.5" })
|
|
59
60
|
}),
|
|
60
61
|
/* @__PURE__ */ a("div", {
|
|
61
62
|
className: "min-w-0 flex-1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpcomingEventsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/UpcomingEventsWidget.tsx"],"sourcesContent":["import { Calendar, ArrowRight, Clock } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nfunction formatEventDate(dateStr: string): string {\n const d = new Date(dateStr);\n const now = new Date();\n const isToday = d.toDateString() === now.toDateString();\n const tomorrow = new Date(now);\n tomorrow.setDate(tomorrow.getDate() + 1);\n const isTomorrow = d.toDateString() === tomorrow.toDateString();\n\n if (isToday)\n return `Today at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n if (isTomorrow)\n return `Tomorrow at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n return d.toLocaleDateString([], {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function UpcomingEventsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const events = workspaceData?.upcomingEvents ?? [];\n\n return (\n <WidgetWrapper\n title=\"Upcoming Events\"\n icon={<Calendar className=\"
|
|
1
|
+
{"version":3,"file":"UpcomingEventsWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/UpcomingEventsWidget.tsx"],"sourcesContent":["import { Calendar, ArrowRight, Clock } from 'lucide-react';\nimport { Badge, Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nfunction formatEventDate(dateStr: string): string {\n const d = new Date(dateStr);\n const now = new Date();\n const isToday = d.toDateString() === now.toDateString();\n const tomorrow = new Date(now);\n tomorrow.setDate(tomorrow.getDate() + 1);\n const isTomorrow = d.toDateString() === tomorrow.toDateString();\n\n if (isToday)\n return `Today at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n if (isTomorrow)\n return `Tomorrow at ${d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;\n return d.toLocaleDateString([], {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport function UpcomingEventsWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const events = workspaceData?.upcomingEvents ?? [];\n\n return (\n <WidgetWrapper\n title=\"Upcoming Events\"\n icon={<Calendar className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button variant=\"ghost\" size=\"sm\" className=\"text-xs\" onClick={() => navigate('/calendar')}>\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {events.length === 0 ? (\n <div className=\"text-center py-4\">\n <p className=\"text-sm text-muted-foreground\">No upcoming events</p>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-2\"\n onClick={() => navigate('/calendar')}\n >\n Schedule an event\n </Button>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {events.map((event) => (\n <button\n key={event.id}\n type=\"button\"\n className=\"w-full flex items-start gap-3 p-2 rounded-md hover:bg-accent/5 cursor-pointer transition-colors text-left\"\n onClick={() => navigate('/calendar')}\n >\n <div className=\"rounded-md bg-accent-pink-subtle text-accent-pink p-1.5 shrink-0\">\n <Clock className=\"size-3.5\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-text-primary truncate\">{event.title}</p>\n <p className=\"text-xs text-muted-foreground\">{formatEventDate(event.startTime)}</p>\n </div>\n {event.allDay && (\n <Badge variant=\"secondary\" className=\"text-[10px] shrink-0\">\n All day\n </Badge>\n )}\n </button>\n ))}\n </div>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,EAAgB,GAAyB;CAChD,IAAM,IAAI,IAAI,KAAK,EAAQ,EACrB,oBAAM,IAAI,MAAM,EAChB,IAAU,EAAE,cAAc,KAAK,EAAI,cAAc,EACjD,IAAW,IAAI,KAAK,EAAI;AAC9B,GAAS,QAAQ,EAAS,SAAS,GAAG,EAAE;CACxC,IAAM,IAAa,EAAE,cAAc,KAAK,EAAS,cAAc;AAM/D,QAJI,IACK,YAAY,EAAE,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC,KACjF,IACK,eAAe,EAAE,mBAAmB,EAAE,EAAE;EAAE,MAAM;EAAW,QAAQ;EAAW,CAAC,KACjF,EAAE,mBAAmB,EAAE,EAAE;EAC9B,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT,CAAC;;AAGJ,SAAgB,EAAqB,EAAE,kBAAe,cAAW,eAAyB;CACxF,IAAM,IAAS,GAAe,kBAAkB,EAAE;AAElD,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GAAQ,SAAQ;GAAQ,MAAK;GAAK,WAAU;GAAU,eAAe,EAAS,YAAY;aAA1F,CAA4F,aACjF,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAO,WAAW,IACjB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAgC;IAAsB,CAAA,EACnE,kBAAC,GAAD;IACE,SAAQ;IACR,MAAK;IACL,WAAU;IACV,eAAe,EAAS,YAAY;cACrC;IAEQ,CAAA,CACL;OAEN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAO,KAAK,MACX,kBAAC,UAAD;IAEE,MAAK;IACL,WAAU;IACV,eAAe,EAAS,YAAY;cAJtC;KAME,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAO,WAAU,YAAa,CAAA;MAC1B,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAkD,EAAM;OAAU,CAAA,EAC/E,kBAAC,KAAD;OAAG,WAAU;iBAAiC,EAAgB,EAAM,UAAU;OAAK,CAAA,CAC/E;;KACL,EAAM,UACL,kBAAC,GAAD;MAAO,SAAQ;MAAY,WAAU;gBAAuB;MAEpD,CAAA;KAEH;MAjBF,EAAM,GAiBJ,CACT;GACE,CAAA;EAEM,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { WidgetWrapper as e } from "../WidgetWrapper.js";
|
|
2
|
+
import { ArrowRight as t, Plus as n, Sparkles as r } from "lucide-react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
+
import { Button as o } from "@burdenoff/fe-libs/ui";
|
|
5
|
+
//#region src/pages/dashboard/widgets/VibesWidget.tsx
|
|
6
|
+
function s(e) {
|
|
7
|
+
let t = Date.now() - new Date(e).getTime(), n = Math.floor(t / 6e4);
|
|
8
|
+
if (n < 1) return "just now";
|
|
9
|
+
if (n < 60) return `${n}m ago`;
|
|
10
|
+
let r = Math.floor(n / 60);
|
|
11
|
+
if (r < 24) return `${r}h ago`;
|
|
12
|
+
let i = Math.floor(r / 24);
|
|
13
|
+
return i < 7 ? `${i}d ago` : new Date(e).toLocaleDateString(void 0, {
|
|
14
|
+
month: "short",
|
|
15
|
+
day: "numeric"
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function c({ workspaceData: c, isLoading: l, navigate: u }) {
|
|
19
|
+
let d = c?.recentVibes ?? [];
|
|
20
|
+
return /* @__PURE__ */ i(e, {
|
|
21
|
+
title: "Recent Vibes",
|
|
22
|
+
icon: /* @__PURE__ */ i(r, { className: "size-4" }),
|
|
23
|
+
size: "medium",
|
|
24
|
+
isLoading: l,
|
|
25
|
+
unavailable: !c,
|
|
26
|
+
headerAction: /* @__PURE__ */ a(o, {
|
|
27
|
+
variant: "ghost",
|
|
28
|
+
size: "sm",
|
|
29
|
+
className: "text-xs",
|
|
30
|
+
onClick: () => u("/vibecontrols/vibes"),
|
|
31
|
+
children: ["View all ", /* @__PURE__ */ i(t, { className: "ml-1 size-3" })]
|
|
32
|
+
}),
|
|
33
|
+
children: d.length === 0 ? /* @__PURE__ */ a("div", {
|
|
34
|
+
className: "text-center py-4",
|
|
35
|
+
children: [/* @__PURE__ */ i("p", {
|
|
36
|
+
className: "text-sm text-muted-foreground mb-2",
|
|
37
|
+
children: "No vibes yet"
|
|
38
|
+
}), /* @__PURE__ */ a(o, {
|
|
39
|
+
variant: "outline",
|
|
40
|
+
size: "sm",
|
|
41
|
+
onClick: () => u("/vibecontrols/vibes/new"),
|
|
42
|
+
children: [/* @__PURE__ */ i(n, { className: "mr-1.5 size-3.5" }), " Create your first vibe"]
|
|
43
|
+
})]
|
|
44
|
+
}) : /* @__PURE__ */ i("ul", {
|
|
45
|
+
className: "space-y-1.5",
|
|
46
|
+
children: d.slice(0, 5).map((e) => /* @__PURE__ */ i("li", { children: /* @__PURE__ */ a("button", {
|
|
47
|
+
type: "button",
|
|
48
|
+
onClick: () => u(`/vibecontrols/vibes/${e.id}`),
|
|
49
|
+
className: "flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5",
|
|
50
|
+
children: [/* @__PURE__ */ i("span", {
|
|
51
|
+
className: "truncate text-sm font-medium text-text-primary",
|
|
52
|
+
children: e.name
|
|
53
|
+
}), /* @__PURE__ */ i("span", {
|
|
54
|
+
className: "shrink-0 text-[11px] text-muted-foreground",
|
|
55
|
+
children: s(e.updatedAt)
|
|
56
|
+
})]
|
|
57
|
+
}) }, e.id))
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { c as VibesWidget };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=VibesWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VibesWidget.js","names":[],"sources":["../../../../src/pages/dashboard/widgets/VibesWidget.tsx"],"sourcesContent":["import { Sparkles, ArrowRight, Plus } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { WidgetWrapper } from '../WidgetWrapper';\nimport type { WidgetProps } from '../types';\n\nfunction formatRelative(dateString: string): string {\n const diffMs = Date.now() - new Date(dateString).getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${diffHr}h ago`;\n const diffDay = Math.floor(diffHr / 24);\n if (diffDay < 7) return `${diffDay}d ago`;\n return new Date(dateString).toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n });\n}\n\nexport function VibesWidget({ workspaceData, isLoading, navigate }: WidgetProps) {\n const vibes = workspaceData?.recentVibes ?? [];\n\n return (\n <WidgetWrapper\n title=\"Recent Vibes\"\n icon={<Sparkles className=\"size-4\" />}\n size=\"medium\"\n isLoading={isLoading}\n unavailable={!workspaceData}\n headerAction={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-xs\"\n onClick={() => navigate('/vibecontrols/vibes')}\n >\n View all <ArrowRight className=\"ml-1 size-3\" />\n </Button>\n }\n >\n {vibes.length === 0 ? (\n <div className=\"text-center py-4\">\n <p className=\"text-sm text-muted-foreground mb-2\">No vibes yet</p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => navigate('/vibecontrols/vibes/new')}>\n <Plus className=\"mr-1.5 size-3.5\" /> Create your first vibe\n </Button>\n </div>\n ) : (\n <ul className=\"space-y-1.5\">\n {vibes.slice(0, 5).map((vibe) => (\n <li key={vibe.id}>\n <button\n type=\"button\"\n onClick={() => navigate(`/vibecontrols/vibes/${vibe.id}`)}\n className=\"flex w-full items-center justify-between gap-2 rounded-md p-2 text-left transition-colors hover:bg-accent/5\"\n >\n <span className=\"truncate text-sm font-medium text-text-primary\">{vibe.name}</span>\n <span className=\"shrink-0 text-[11px] text-muted-foreground\">\n {formatRelative(vibe.updatedAt)}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n </WidgetWrapper>\n );\n}\n"],"mappings":";;;;;AAKA,SAAS,EAAe,GAA4B;CAClD,IAAM,IAAS,KAAK,KAAK,GAAG,IAAI,KAAK,EAAW,CAAC,SAAS,EACpD,IAAU,KAAK,MAAM,IAAS,IAAM;AAC1C,KAAI,IAAU,EAAG,QAAO;AACxB,KAAI,IAAU,GAAI,QAAO,GAAG,EAAQ;CACpC,IAAM,IAAS,KAAK,MAAM,IAAU,GAAG;AACvC,KAAI,IAAS,GAAI,QAAO,GAAG,EAAO;CAClC,IAAM,IAAU,KAAK,MAAM,IAAS,GAAG;AAEvC,QADI,IAAU,IAAU,GAAG,EAAQ,SAC5B,IAAI,KAAK,EAAW,CAAC,mBAAmB,KAAA,GAAW;EACxD,OAAO;EACP,KAAK;EACN,CAAC;;AAGJ,SAAgB,EAAY,EAAE,kBAAe,cAAW,eAAyB;CAC/E,IAAM,IAAQ,GAAe,eAAe,EAAE;AAE9C,QACE,kBAAC,GAAD;EACE,OAAM;EACN,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;EACrC,MAAK;EACM;EACX,aAAa,CAAC;EACd,cACE,kBAAC,GAAD;GACE,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,EAAS,sBAAsB;aAJhD,CAKC,aACU,kBAAC,GAAD,EAAY,WAAU,eAAgB,CAAA,CACxC;;YAGV,EAAM,WAAW,IAChB,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,KAAD;IAAG,WAAU;cAAqC;IAAgB,CAAA,EAClE,kBAAC,GAAD;IAAQ,SAAQ;IAAU,MAAK;IAAK,eAAe,EAAS,0BAA0B;cAAtF,CACE,kBAAC,GAAD,EAAM,WAAU,mBAAoB,CAAA,EAAA,0BAC7B;MACL;OAEN,kBAAC,MAAD;GAAI,WAAU;aACX,EAAM,MAAM,GAAG,EAAE,CAAC,KAAK,MACtB,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAS,uBAAuB,EAAK,KAAK;IACzD,WAAU;cAHZ,CAKE,kBAAC,QAAD;KAAM,WAAU;eAAkD,EAAK;KAAY,CAAA,EACnF,kBAAC,QAAD;KAAM,WAAU;eACb,EAAe,EAAK,UAAU;KAC1B,CAAA,CACA;OACN,EAXI,EAAK,GAWT,CACL;GACC,CAAA;EAEO,CAAA"}
|
|
@@ -21,7 +21,7 @@ function l({ workspaceData: l, globalData: u, isLoading: d }) {
|
|
|
21
21
|
let f = u?.currentUser, p = f?.firstName || f?.name?.split(" ")[0] || "there", m = (/* @__PURE__ */ new Date()).getHours(), h = m < 12 ? "Good morning" : m < 18 ? "Good afternoon" : "Good evening", g = l?.workspaces.total ?? 0, _ = l?.projects.total ?? 0, v = l?.groups.totalCount ?? 0, y = l?.recentActivities.length ?? 0;
|
|
22
22
|
return /* @__PURE__ */ o(e, {
|
|
23
23
|
title: "Dashboard",
|
|
24
|
-
icon: /* @__PURE__ */ o(i, { className: "
|
|
24
|
+
icon: /* @__PURE__ */ o(i, { className: "size-4" }),
|
|
25
25
|
size: "large",
|
|
26
26
|
isLoading: d,
|
|
27
27
|
children: /* @__PURE__ */ s("div", {
|
|
@@ -41,22 +41,22 @@ function l({ workspaceData: l, globalData: u, isLoading: d }) {
|
|
|
41
41
|
className: "grid grid-cols-2 sm:grid-cols-4 gap-3",
|
|
42
42
|
children: [
|
|
43
43
|
/* @__PURE__ */ o(c, {
|
|
44
|
-
icon: /* @__PURE__ */ o(n, { className: "
|
|
44
|
+
icon: /* @__PURE__ */ o(n, { className: "size-4" }),
|
|
45
45
|
label: "Workspaces",
|
|
46
46
|
value: g
|
|
47
47
|
}),
|
|
48
48
|
/* @__PURE__ */ o(c, {
|
|
49
|
-
icon: /* @__PURE__ */ o(r, { className: "
|
|
49
|
+
icon: /* @__PURE__ */ o(r, { className: "size-4" }),
|
|
50
50
|
label: "Projects",
|
|
51
51
|
value: _
|
|
52
52
|
}),
|
|
53
53
|
/* @__PURE__ */ o(c, {
|
|
54
|
-
icon: /* @__PURE__ */ o(a, { className: "
|
|
54
|
+
icon: /* @__PURE__ */ o(a, { className: "size-4" }),
|
|
55
55
|
label: "Groups",
|
|
56
56
|
value: v
|
|
57
57
|
}),
|
|
58
58
|
/* @__PURE__ */ o(c, {
|
|
59
|
-
icon: /* @__PURE__ */ o(t, { className: "
|
|
59
|
+
icon: /* @__PURE__ */ o(t, { className: "size-4" }),
|
|
60
60
|
label: "Recent Activity",
|
|
61
61
|
value: y
|
|
62
62
|
})
|