@burdenoff/microfe-bigconsole 2026.812.2 → 2026.827.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/bigconsole/components/builder/inspector/LayoutSection.js +71 -0
- package/dist/bigconsole/components/builder/inspector/LayoutSection.js.map +1 -0
- package/dist/bigconsole/components/builder/inspector/index.js +1 -0
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +137 -121
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +204 -93
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +259 -133
- package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js +87 -39
- package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +88 -68
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +213 -199
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/workflow/WorkflowCard.js +46 -27
- package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +44 -47
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
- package/dist/bigconsole/customWidget/proposalSource.js +31 -24
- package/dist/bigconsole/customWidget/proposalSource.js.map +1 -1
- package/dist/bigconsole/hooks/useDashboardOperations.js +74 -64
- package/dist/bigconsole/hooks/useDashboardOperations.js.map +1 -1
- package/dist/bigconsole/hooks/useDataSinkOperations.js +2 -2
- package/dist/bigconsole/hooks/useDataSinkOperations.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +386 -316
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +251 -206
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +646 -378
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +153 -108
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/utils/format.js +18 -0
- package/dist/bigconsole/utils/format.js.map +1 -0
- package/dist/bigconsole/utils/widgetPositioning.js +1 -1
- package/dist/generated/wspace-operations.js +1 -0
- package/dist/generated/wspace-operations.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,128 +1,148 @@
|
|
|
1
1
|
import { SECTION_FOCUS_RING as e } from "../common/sectionStyles.js";
|
|
2
2
|
import "../common/index.js";
|
|
3
3
|
import t from "./DataSinkStatusBadge.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { formatByteSize as n } from "../../utils/format.js";
|
|
5
|
+
import { memo as r, useCallback as i } from "react";
|
|
6
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
+
import { formatDistanceToNow as s } from "date-fns";
|
|
7
8
|
//#region src/bigconsole/components/datasink/DataSinkCard.tsx
|
|
8
|
-
var
|
|
9
|
-
let
|
|
10
|
-
t.stopPropagation(), c?.(e.id);
|
|
11
|
-
}, [e.id, c]), v = r((t) => {
|
|
9
|
+
var c = `inline-flex min-h-[var(--size-controlHeight-md)] items-center justify-center rounded-button px-3 py-1.5 text-xs font-medium motion-safe:transition-colors ${e}`, l = r(function({ dataSink: e, setupState: r, onView: l, onEdit: u, onRefresh: d, onExport: f, onDelete: p, onContinueSetup: m, canEdit: h = !0, canRefresh: g = !0, canDelete: _ = !0 }) {
|
|
10
|
+
let v = i((t) => {
|
|
12
11
|
t.stopPropagation(), l?.(e.id);
|
|
13
|
-
}, [e.id, l]), y =
|
|
12
|
+
}, [e.id, l]), y = i((t) => {
|
|
14
13
|
t.stopPropagation(), u?.(e.id);
|
|
15
|
-
}, [e.id, u]), b =
|
|
14
|
+
}, [e.id, u]), b = i((t) => {
|
|
16
15
|
t.stopPropagation(), d?.(e.id);
|
|
17
|
-
}, [e.id, d]), x =
|
|
16
|
+
}, [e.id, d]), x = i((t) => {
|
|
18
17
|
t.stopPropagation(), f?.(e.id);
|
|
19
|
-
}, [e.id, f]), S =
|
|
18
|
+
}, [e.id, f]), S = i((t) => {
|
|
20
19
|
t.stopPropagation(), p?.(e.id);
|
|
21
|
-
}, [e.id, p]), C = (
|
|
22
|
-
|
|
20
|
+
}, [e.id, p]), C = i((t) => {
|
|
21
|
+
t.stopPropagation(), m?.(e.id);
|
|
22
|
+
}, [e.id, m]), w = (r ?? e.setupState) === "completed", T = e.lastRefreshedAt ? s(new Date(e.lastRefreshedAt), { addSuffix: !0 }) : "Never";
|
|
23
|
+
return /* @__PURE__ */ o("article", {
|
|
23
24
|
className: "\n min-w-0\n cursor-pointer\n rounded-card\n border border-transparent\n bg-bg-sunken\n p-card-padding\n hover:border-[var(--color-action-primary-bg)]\n motion-safe:transition-colors\n ",
|
|
24
|
-
onClick:
|
|
25
|
+
onClick: v,
|
|
25
26
|
children: [
|
|
26
|
-
/* @__PURE__ */
|
|
27
|
+
/* @__PURE__ */ o("div", {
|
|
27
28
|
className: "mb-3 flex items-start justify-between gap-icon-gap",
|
|
28
|
-
children: [/* @__PURE__ */
|
|
29
|
+
children: [/* @__PURE__ */ o("div", {
|
|
29
30
|
className: "min-w-0 flex-1",
|
|
30
|
-
children: [/* @__PURE__ */
|
|
31
|
+
children: [/* @__PURE__ */ a("h3", {
|
|
31
32
|
className: "truncate text-sm font-semibold text-text-primary",
|
|
32
33
|
children: e.name || "Untitled data sink"
|
|
33
|
-
}), /* @__PURE__ */
|
|
34
|
+
}), /* @__PURE__ */ a("p", {
|
|
34
35
|
className: "mt-0.5 truncate font-mono text-xs text-text-secondary",
|
|
35
36
|
children: e.key
|
|
36
37
|
})]
|
|
37
|
-
}), /* @__PURE__ */
|
|
38
|
+
}), /* @__PURE__ */ a(t, {
|
|
38
39
|
status: e.status,
|
|
39
40
|
size: "sm"
|
|
40
41
|
})]
|
|
41
42
|
}),
|
|
42
|
-
e.description && /* @__PURE__ */
|
|
43
|
+
e.description && /* @__PURE__ */ a("p", {
|
|
43
44
|
className: "mb-3 line-clamp-2 text-xs text-text-secondary",
|
|
44
45
|
children: e.description
|
|
45
46
|
}),
|
|
46
|
-
/* @__PURE__ */
|
|
47
|
+
/* @__PURE__ */ o("div", {
|
|
47
48
|
className: "mb-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary",
|
|
48
|
-
children: [
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
fill: "none",
|
|
53
|
-
stroke: "currentColor",
|
|
54
|
-
viewBox: "0 0 24 24",
|
|
55
|
-
children: /* @__PURE__ */ i("path", {
|
|
56
|
-
strokeLinecap: "round",
|
|
57
|
-
strokeLinejoin: "round",
|
|
58
|
-
strokeWidth: 2,
|
|
59
|
-
d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
60
|
-
})
|
|
61
|
-
}), w]
|
|
62
|
-
}), e.linkedWorkflowCount !== void 0 && e.linkedWorkflowCount > 0 && /* @__PURE__ */ a("span", {
|
|
63
|
-
className: "flex items-center gap-1",
|
|
64
|
-
children: [
|
|
65
|
-
/* @__PURE__ */ i("svg", {
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ o("span", {
|
|
51
|
+
className: "flex items-center gap-1",
|
|
52
|
+
children: [/* @__PURE__ */ a("svg", {
|
|
66
53
|
className: "w-3.5 h-3.5",
|
|
67
54
|
fill: "none",
|
|
68
55
|
stroke: "currentColor",
|
|
69
56
|
viewBox: "0 0 24 24",
|
|
70
|
-
children: /* @__PURE__ */
|
|
57
|
+
children: /* @__PURE__ */ a("path", {
|
|
71
58
|
strokeLinecap: "round",
|
|
72
59
|
strokeLinejoin: "round",
|
|
73
60
|
strokeWidth: 2,
|
|
74
|
-
d: "
|
|
61
|
+
d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
75
62
|
})
|
|
76
|
-
}),
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
63
|
+
}), T]
|
|
64
|
+
}),
|
|
65
|
+
/* @__PURE__ */ o("span", {
|
|
66
|
+
className: "flex items-center gap-1",
|
|
67
|
+
title: "Stored payload size",
|
|
68
|
+
children: [/* @__PURE__ */ a("svg", {
|
|
69
|
+
className: "w-3.5 h-3.5",
|
|
70
|
+
fill: "none",
|
|
71
|
+
stroke: "currentColor",
|
|
72
|
+
viewBox: "0 0 24 24",
|
|
73
|
+
children: /* @__PURE__ */ a("path", {
|
|
74
|
+
strokeLinecap: "round",
|
|
75
|
+
strokeLinejoin: "round",
|
|
76
|
+
strokeWidth: 2,
|
|
77
|
+
d: "M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4"
|
|
78
|
+
})
|
|
79
|
+
}), n(e.sizeBytes)]
|
|
80
|
+
}),
|
|
81
|
+
e.linkedWorkflowCount !== void 0 && e.linkedWorkflowCount > 0 && /* @__PURE__ */ o("span", {
|
|
82
|
+
className: "flex items-center gap-1",
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ a("svg", {
|
|
85
|
+
className: "w-3.5 h-3.5",
|
|
86
|
+
fill: "none",
|
|
87
|
+
stroke: "currentColor",
|
|
88
|
+
viewBox: "0 0 24 24",
|
|
89
|
+
children: /* @__PURE__ */ a("path", {
|
|
90
|
+
strokeLinecap: "round",
|
|
91
|
+
strokeLinejoin: "round",
|
|
92
|
+
strokeWidth: 2,
|
|
93
|
+
d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
e.linkedWorkflowCount,
|
|
97
|
+
" workflow",
|
|
98
|
+
e.linkedWorkflowCount === 1 ? "" : "s"
|
|
99
|
+
]
|
|
100
|
+
})
|
|
101
|
+
]
|
|
82
102
|
}),
|
|
83
|
-
!
|
|
103
|
+
!w && /* @__PURE__ */ o("div", {
|
|
84
104
|
className: "mb-3 flex items-center justify-between gap-icon-gap rounded-input border border-[var(--color-status-warning-border)] bg-[var(--color-status-warning-bgSubtle)] p-2",
|
|
85
|
-
children: [/* @__PURE__ */
|
|
105
|
+
children: [/* @__PURE__ */ a("span", {
|
|
86
106
|
className: "text-xs text-[var(--color-status-warning-text)]",
|
|
87
107
|
children: "Setup incomplete"
|
|
88
|
-
}), /* @__PURE__ */
|
|
108
|
+
}), /* @__PURE__ */ a("button", {
|
|
89
109
|
type: "button",
|
|
90
|
-
onClick:
|
|
110
|
+
onClick: C,
|
|
91
111
|
className: "rounded-button px-1 text-xs font-medium text-text-link hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg-surface",
|
|
92
112
|
children: "Continue"
|
|
93
113
|
})]
|
|
94
114
|
}),
|
|
95
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ o("div", {
|
|
96
116
|
className: "flex flex-wrap items-center gap-2 border-t border-[var(--color-border-subtle)] pt-2",
|
|
97
117
|
children: [
|
|
98
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ a("button", {
|
|
99
119
|
type: "button",
|
|
100
|
-
onClick:
|
|
101
|
-
className: `${
|
|
120
|
+
onClick: v,
|
|
121
|
+
className: `${c} flex-1 bg-bg-surface text-text-primary hover:bg-bg-elevated`,
|
|
102
122
|
children: "View"
|
|
103
123
|
}),
|
|
104
|
-
|
|
124
|
+
h && /* @__PURE__ */ a("button", {
|
|
105
125
|
type: "button",
|
|
106
|
-
onClick:
|
|
107
|
-
className: `${
|
|
126
|
+
onClick: y,
|
|
127
|
+
className: `${c} text-text-secondary hover:bg-bg-surface hover:text-text-primary`,
|
|
108
128
|
children: "Edit"
|
|
109
129
|
}),
|
|
110
|
-
|
|
130
|
+
g && /* @__PURE__ */ a("button", {
|
|
111
131
|
type: "button",
|
|
112
|
-
onClick:
|
|
113
|
-
className: `${
|
|
132
|
+
onClick: b,
|
|
133
|
+
className: `${c} text-text-secondary hover:bg-bg-surface hover:text-text-primary`,
|
|
114
134
|
children: "Refresh"
|
|
115
135
|
}),
|
|
116
|
-
|
|
136
|
+
f && /* @__PURE__ */ a("button", {
|
|
117
137
|
type: "button",
|
|
118
|
-
onClick:
|
|
119
|
-
className: `${
|
|
138
|
+
onClick: x,
|
|
139
|
+
className: `${c} text-text-secondary hover:bg-bg-surface hover:text-text-primary`,
|
|
120
140
|
children: "Export"
|
|
121
141
|
}),
|
|
122
|
-
|
|
142
|
+
_ && /* @__PURE__ */ a("button", {
|
|
123
143
|
type: "button",
|
|
124
|
-
onClick:
|
|
125
|
-
className: `${
|
|
144
|
+
onClick: S,
|
|
145
|
+
className: `${c} text-status-error-text hover:bg-[var(--color-status-error-bgSubtle)]`,
|
|
126
146
|
children: "Delete"
|
|
127
147
|
})
|
|
128
148
|
]
|
|
@@ -131,6 +151,6 @@ var s = `inline-flex min-h-[var(--size-controlHeight-md)] items-center justify-c
|
|
|
131
151
|
});
|
|
132
152
|
});
|
|
133
153
|
//#endregion
|
|
134
|
-
export {
|
|
154
|
+
export { l as default };
|
|
135
155
|
|
|
136
156
|
//# sourceMappingURL=DataSinkCard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataSinkCard.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/DataSinkCard.tsx"],"sourcesContent":["/**\n * DataSink Card\n *\n * Card component for displaying DataSink information in a list/grid view.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { DataSinkStatusBadge } from './DataSinkStatusBadge';\nimport { SECTION_FOCUS_RING } from '../common';\nimport type { DataSink, DataSinkSetupState } from '../../types';\n\n/**\n * Shared class recipe for the card's five action buttons. `min-h-[var(--size-controlHeight-md)]`\n * keeps every one at the 40px touch minimum once the row wraps on mobile.\n */\nconst CARD_ACTION =\n `inline-flex min-h-[var(--size-controlHeight-md)] items-center justify-center rounded-button px-3 py-1.5 text-xs font-medium motion-safe:transition-colors ${SECTION_FOCUS_RING}` as const;\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface DataSinkCardProps {\n /** DataSink data */\n dataSink: DataSink;\n /** Setup state override */\n setupState?: DataSinkSetupState;\n /** Callback when view is clicked */\n onView?: (id: string) => void;\n /** Callback when edit is clicked */\n onEdit?: (id: string) => void;\n /** Callback when refresh is clicked */\n onRefresh?: (id: string) => void;\n /** Callback when export is clicked */\n onExport?: (id: string) => void;\n /** Callback when delete is clicked */\n onDelete?: (id: string) => void;\n /** Callback to continue setup */\n onContinueSetup?: (id: string) => void;\n /** Whether the current actor may edit this DataSink (gates the Edit action). Defaults to true. */\n canEdit?: boolean;\n /** Whether the current actor may refresh this DataSink (gates the Refresh action). Defaults to true. */\n canRefresh?: boolean;\n /** Whether the current actor may delete this DataSink (gates the Delete action). Defaults to true. */\n canDelete?: boolean;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const DataSinkCard = memo(function DataSinkCard({\n dataSink,\n setupState,\n onView,\n onEdit,\n onRefresh,\n onExport,\n onDelete,\n onContinueSetup,\n canEdit = true,\n canRefresh = true,\n canDelete = true,\n}: DataSinkCardProps) {\n // Event handlers\n const handleView = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onView?.(dataSink.id);\n },\n [dataSink.id, onView]\n );\n\n const handleEdit = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(dataSink.id);\n },\n [dataSink.id, onEdit]\n );\n\n const handleRefresh = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRefresh?.(dataSink.id);\n },\n [dataSink.id, onRefresh]\n );\n\n const handleExport = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onExport?.(dataSink.id);\n },\n [dataSink.id, onExport]\n );\n\n const handleDelete = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(dataSink.id);\n },\n [dataSink.id, onDelete]\n );\n\n const handleContinueSetup = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onContinueSetup?.(dataSink.id);\n },\n [dataSink.id, onContinueSetup]\n );\n\n const currentSetupState = setupState ?? dataSink.setupState;\n const isSetupComplete = currentSetupState === 'completed';\n\n // Format last refreshed time\n const lastRefreshedText = dataSink.lastRefreshedAt\n ? formatDistanceToNow(new Date(dataSink.lastRefreshedAt), { addSuffix: true })\n : 'Never';\n\n return (\n // A card is a tile inside the page's `primary` results section, so it steps\n // down to the `muted` recipe (recessed surface, transparent border) instead\n // of competing with the panel that contains it.\n <article\n className={`\n min-w-0\n cursor-pointer\n rounded-card\n border border-transparent\n bg-bg-sunken\n p-card-padding\n hover:border-[var(--color-action-primary-bg)]\n motion-safe:transition-colors\n `}\n onClick={handleView}\n >\n {/* Identity */}\n <div className=\"mb-3 flex items-start justify-between gap-icon-gap\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate text-sm font-semibold text-text-primary\">{dataSink.name || 'Untitled data sink'}</h3>\n <p className=\"mt-0.5 truncate font-mono text-xs text-text-secondary\">{dataSink.key}</p>\n </div>\n <DataSinkStatusBadge status={dataSink.status} size=\"sm\" />\n </div>\n\n {/* Description */}\n {dataSink.description && <p className=\"mb-3 line-clamp-2 text-xs text-text-secondary\">{dataSink.description}</p>}\n\n {/* Stats */}\n <div className=\"mb-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n {lastRefreshedText}\n </span>\n {dataSink.linkedWorkflowCount !== undefined && dataSink.linkedWorkflowCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\"\n />\n </svg>\n {dataSink.linkedWorkflowCount} workflow{dataSink.linkedWorkflowCount !== 1 ? 's' : ''}\n </span>\n )}\n </div>\n\n {/* Setup state — a warning strip, so it carries the warning tone. */}\n {!isSetupComplete && (\n <div className=\"mb-3 flex items-center justify-between gap-icon-gap rounded-input border border-[var(--color-status-warning-border)] bg-[var(--color-status-warning-bgSubtle)] p-2\">\n <span className=\"text-xs text-[var(--color-status-warning-text)]\">Setup incomplete</span>\n <button\n type=\"button\"\n onClick={handleContinueSetup}\n className={`rounded-button px-1 text-xs font-medium text-text-link hover:underline ${SECTION_FOCUS_RING}`}\n >\n Continue\n </button>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-wrap items-center gap-2 border-t border-[var(--color-border-subtle)] pt-2\">\n <button\n type=\"button\"\n onClick={handleView}\n className={`${CARD_ACTION} flex-1 bg-bg-surface text-text-primary hover:bg-bg-elevated`}\n >\n View\n </button>\n {canEdit && (\n <button\n type=\"button\"\n onClick={handleEdit}\n className={`${CARD_ACTION} text-text-secondary hover:bg-bg-surface hover:text-text-primary`}\n >\n Edit\n </button>\n )}\n {canRefresh && (\n <button\n type=\"button\"\n onClick={handleRefresh}\n className={`${CARD_ACTION} text-text-secondary hover:bg-bg-surface hover:text-text-primary`}\n >\n Refresh\n </button>\n )}\n {onExport && (\n <button\n type=\"button\"\n onClick={handleExport}\n className={`${CARD_ACTION} text-text-secondary hover:bg-bg-surface hover:text-text-primary`}\n >\n Export\n </button>\n )}\n {canDelete && (\n <button\n type=\"button\"\n onClick={handleDelete}\n className={`${CARD_ACTION} text-status-error-text hover:bg-[var(--color-status-error-bgSubtle)]`}\n >\n Delete\n </button>\n )}\n </div>\n </article>\n );\n});\n\nexport default DataSinkCard;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataSinkCard.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/DataSinkCard.tsx"],"sourcesContent":["/**\n * DataSink Card\n *\n * Card component for displaying DataSink information in a list/grid view.\n */\n\nimport { memo, useCallback } from 'react';\nimport { formatDistanceToNow } from 'date-fns';\nimport { DataSinkStatusBadge } from './DataSinkStatusBadge';\nimport { SECTION_FOCUS_RING } from '../common';\nimport { formatByteSize } from '../../utils';\nimport type { DataSink, DataSinkSetupState } from '../../types';\n\n/**\n * Shared class recipe for the card's five action buttons. `min-h-[var(--size-controlHeight-md)]`\n * keeps every one at the 40px touch minimum once the row wraps on mobile.\n */\nconst CARD_ACTION =\n `inline-flex min-h-[var(--size-controlHeight-md)] items-center justify-center rounded-button px-3 py-1.5 text-xs font-medium motion-safe:transition-colors ${SECTION_FOCUS_RING}` as const;\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface DataSinkCardProps {\n /** DataSink data */\n dataSink: DataSink;\n /** Setup state override */\n setupState?: DataSinkSetupState;\n /** Callback when view is clicked */\n onView?: (id: string) => void;\n /** Callback when edit is clicked */\n onEdit?: (id: string) => void;\n /** Callback when refresh is clicked */\n onRefresh?: (id: string) => void;\n /** Callback when export is clicked */\n onExport?: (id: string) => void;\n /** Callback when delete is clicked */\n onDelete?: (id: string) => void;\n /** Callback to continue setup */\n onContinueSetup?: (id: string) => void;\n /** Whether the current actor may edit this DataSink (gates the Edit action). Defaults to true. */\n canEdit?: boolean;\n /** Whether the current actor may refresh this DataSink (gates the Refresh action). Defaults to true. */\n canRefresh?: boolean;\n /** Whether the current actor may delete this DataSink (gates the Delete action). Defaults to true. */\n canDelete?: boolean;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const DataSinkCard = memo(function DataSinkCard({\n dataSink,\n setupState,\n onView,\n onEdit,\n onRefresh,\n onExport,\n onDelete,\n onContinueSetup,\n canEdit = true,\n canRefresh = true,\n canDelete = true,\n}: DataSinkCardProps) {\n // Event handlers\n const handleView = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onView?.(dataSink.id);\n },\n [dataSink.id, onView]\n );\n\n const handleEdit = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(dataSink.id);\n },\n [dataSink.id, onEdit]\n );\n\n const handleRefresh = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onRefresh?.(dataSink.id);\n },\n [dataSink.id, onRefresh]\n );\n\n const handleExport = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onExport?.(dataSink.id);\n },\n [dataSink.id, onExport]\n );\n\n const handleDelete = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onDelete?.(dataSink.id);\n },\n [dataSink.id, onDelete]\n );\n\n const handleContinueSetup = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n onContinueSetup?.(dataSink.id);\n },\n [dataSink.id, onContinueSetup]\n );\n\n const currentSetupState = setupState ?? dataSink.setupState;\n const isSetupComplete = currentSetupState === 'completed';\n\n // Format last refreshed time\n const lastRefreshedText = dataSink.lastRefreshedAt\n ? formatDistanceToNow(new Date(dataSink.lastRefreshedAt), { addSuffix: true })\n : 'Never';\n\n return (\n // A card is a tile inside the page's `primary` results section, so it steps\n // down to the `muted` recipe (recessed surface, transparent border) instead\n // of competing with the panel that contains it.\n <article\n className={`\n min-w-0\n cursor-pointer\n rounded-card\n border border-transparent\n bg-bg-sunken\n p-card-padding\n hover:border-[var(--color-action-primary-bg)]\n motion-safe:transition-colors\n `}\n onClick={handleView}\n >\n {/* Identity */}\n <div className=\"mb-3 flex items-start justify-between gap-icon-gap\">\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate text-sm font-semibold text-text-primary\">{dataSink.name || 'Untitled data sink'}</h3>\n <p className=\"mt-0.5 truncate font-mono text-xs text-text-secondary\">{dataSink.key}</p>\n </div>\n <DataSinkStatusBadge status={dataSink.status} size=\"sm\" />\n </div>\n\n {/* Description */}\n {dataSink.description && <p className=\"mb-3 line-clamp-2 text-xs text-text-secondary\">{dataSink.description}</p>}\n\n {/* Stats */}\n <div className=\"mb-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n {lastRefreshedText}\n </span>\n {/* `sizeBytes` ships in DataSinkListItem on every list query but was\n never shown here — it is how you tell a populated sink from an empty\n one without opening it. */}\n <span className=\"flex items-center gap-1\" title=\"Stored payload size\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4\"\n />\n </svg>\n {formatByteSize(dataSink.sizeBytes)}\n </span>\n {dataSink.linkedWorkflowCount !== undefined && dataSink.linkedWorkflowCount > 0 && (\n <span className=\"flex items-center gap-1\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\"\n />\n </svg>\n {dataSink.linkedWorkflowCount} workflow{dataSink.linkedWorkflowCount !== 1 ? 's' : ''}\n </span>\n )}\n </div>\n\n {/* Setup state — a warning strip, so it carries the warning tone. */}\n {!isSetupComplete && (\n <div className=\"mb-3 flex items-center justify-between gap-icon-gap rounded-input border border-[var(--color-status-warning-border)] bg-[var(--color-status-warning-bgSubtle)] p-2\">\n <span className=\"text-xs text-[var(--color-status-warning-text)]\">Setup incomplete</span>\n <button\n type=\"button\"\n onClick={handleContinueSetup}\n className={`rounded-button px-1 text-xs font-medium text-text-link hover:underline ${SECTION_FOCUS_RING}`}\n >\n Continue\n </button>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-wrap items-center gap-2 border-t border-[var(--color-border-subtle)] pt-2\">\n <button\n type=\"button\"\n onClick={handleView}\n className={`${CARD_ACTION} flex-1 bg-bg-surface text-text-primary hover:bg-bg-elevated`}\n >\n View\n </button>\n {canEdit && (\n <button\n type=\"button\"\n onClick={handleEdit}\n className={`${CARD_ACTION} text-text-secondary hover:bg-bg-surface hover:text-text-primary`}\n >\n Edit\n </button>\n )}\n {canRefresh && (\n <button\n type=\"button\"\n onClick={handleRefresh}\n className={`${CARD_ACTION} text-text-secondary hover:bg-bg-surface hover:text-text-primary`}\n >\n Refresh\n </button>\n )}\n {onExport && (\n <button\n type=\"button\"\n onClick={handleExport}\n className={`${CARD_ACTION} text-text-secondary hover:bg-bg-surface hover:text-text-primary`}\n >\n Export\n </button>\n )}\n {canDelete && (\n <button\n type=\"button\"\n onClick={handleDelete}\n className={`${CARD_ACTION} text-status-error-text hover:bg-[var(--color-status-error-bgSubtle)]`}\n >\n Delete\n </button>\n )}\n </div>\n </article>\n );\n});\n\nexport default DataSinkCard;\n"],"mappings":"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"}
|