@burdenoff/microfe-bigconsole 2026.805.1 → 2026.805.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/dist/bigconsole/AdminRoot.js +21 -16
  2. package/dist/bigconsole/AdminRoot.js.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoot.js +44 -39
  4. package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
  5. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +109 -113
  6. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  7. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +115 -113
  8. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  9. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +71 -62
  10. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  11. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +116 -100
  12. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  13. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +56 -54
  14. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  15. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +126 -125
  16. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
  17. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +151 -150
  18. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  19. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +77 -76
  20. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
  21. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +97 -96
  22. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  23. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +172 -191
  24. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  25. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
  26. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
  27. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
  28. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
  29. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +151 -154
  30. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
  31. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +187 -193
  32. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
  33. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
  34. package/dist/bigconsole/components/dashboard/WidgetPalette.js +110 -108
  35. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  36. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +102 -103
  37. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  38. package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
  39. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  40. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +36 -41
  41. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  42. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +38 -37
  43. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  44. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
  45. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
  46. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +182 -197
  47. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  48. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +166 -168
  49. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  50. package/dist/bigconsole/components/parser/DataSinkSelector.js +87 -86
  51. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  52. package/dist/bigconsole/components/parser/ImportParserDialog.js +196 -211
  53. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  54. package/dist/bigconsole/components/parser/ParserSelector.js +130 -128
  55. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  56. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +66 -63
  57. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
  58. package/dist/bigconsole/components/preview/AiPreviewPanel.js +95 -91
  59. package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
  60. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +243 -230
  61. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  62. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +149 -145
  63. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  64. package/dist/bigconsole/components/widgets/PropertiesPanel.js +504 -470
  65. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  66. package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
  67. package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
  68. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +44 -47
  69. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  70. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +143 -142
  71. package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
  72. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +101 -88
  73. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  74. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +135 -134
  75. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  76. package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
  77. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  78. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +69 -68
  79. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
  80. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +64 -72
  81. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
  82. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +60 -59
  83. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  84. package/dist/bigconsole/components/widgets/list/ListConfig.js +57 -56
  85. package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
  86. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +70 -69
  87. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
  88. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
  89. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
  90. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
  91. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
  92. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +178 -177
  93. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  94. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +76 -75
  95. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  96. package/dist/bigconsole/components/widgets/table/TableConfig.js +183 -168
  97. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  98. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +187 -180
  99. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  100. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
  101. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  102. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +40 -38
  103. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
  104. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +150 -148
  105. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  106. package/dist/bigconsole/pages/DashboardBuilderPage.js +189 -175
  107. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  108. package/dist/bigconsole/pages/DashboardViewPage.js +200 -187
  109. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  110. package/dist/bigconsole/pages/DashboardsPage.js +379 -324
  111. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  112. package/dist/bigconsole/pages/DataParsersPage.js +185 -178
  113. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  114. package/dist/bigconsole/pages/DataSinkBuilderPage.js +195 -170
  115. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  116. package/dist/bigconsole/pages/DataSinkViewPage.js +224 -200
  117. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  118. package/dist/bigconsole/pages/DataSinksPage.js +281 -268
  119. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  120. package/dist/bigconsole/pages/DataSourcesPage.js +8 -7
  121. package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
  122. package/dist/bigconsole/pages/InsightsPage.js +238 -208
  123. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  124. package/dist/bigconsole/pages/ParserBuilderPage.js +480 -413
  125. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  126. package/dist/bigconsole/pages/ParserViewPage.js +192 -172
  127. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  128. package/dist/bigconsole/pages/PipelineBuilderPage.js +198 -163
  129. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  130. package/dist/bigconsole/pages/PipelineViewPage.js +138 -133
  131. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  132. package/dist/bigconsole/pages/PipelinesPage.js +162 -136
  133. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  134. package/dist/bigconsole/pages/SettingsPage.js +177 -172
  135. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  136. package/dist/bigconsole/pages/WidgetDemoPage.js +121 -83
  137. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  138. package/dist/bigconsole/pages/WorkflowViewPage.js +269 -242
  139. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  140. package/dist/bigconsole/pages/WorkflowsPage.js +153 -138
  141. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  142. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
  143. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
  144. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
  145. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
  146. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
  147. package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
  148. package/dist/constants/permissions.js +83 -0
  149. package/dist/constants/permissions.js.map +1 -0
  150. package/package.json +2 -1
@@ -3,59 +3,91 @@ import { useAppNavigate as t } from "../contexts/NavigationContext.js";
3
3
  import "../contexts/index.js";
4
4
  import n from "../hooks/useWorkflowOperations.js";
5
5
  import { newWorkflowPath as r } from "../BigConsoleRoutes.js";
6
- import { isNative as i, nativeNotify as a } from "../../utils/nativeBridge.js";
7
- import o from "../components/workflow/WorkflowDeleteDialog.js";
8
- import s from "../components/workflow/WorkflowCard.js";
9
- import { memo as c, useCallback as l, useMemo as u, useState as d } from "react";
10
- import { AlertCircle as f, Plus as p, Search as m, Workflow as h } from "lucide-react";
11
- import { AuroraBackground as g, Button as _, Card as v, CardContent as y, GlassCard as b, GradientText as x, IllustratedEmptyState as S, Input as C, PagePurpose as w, Spinner as T } from "@burdenoff/fe-libs/ui";
12
- import { jsx as E, jsxs as D } from "react/jsx-runtime";
6
+ import { BIGCONSOLE_PERMISSIONS as i } from "../../constants/permissions.js";
7
+ import { isNative as a, nativeNotify as o } from "../../utils/nativeBridge.js";
8
+ import s from "../components/workflow/WorkflowDeleteDialog.js";
9
+ import c from "../components/workflow/WorkflowCard.js";
10
+ import { memo as l, useCallback as u, useMemo as d, useState as f } from "react";
11
+ import { AccessDenied as p, PermissionButton as m } from "@burdenoff/fe-libs/shared/components";
12
+ import { usePermissions as h } from "@burdenoff/fe-libs/shared/providers/shell";
13
+ import { AlertCircle as g, Plus as _, Search as v, Workflow as y } from "lucide-react";
14
+ import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
+ import { AuroraBackground as x, Button as S, Card as C, CardContent as w, GlassCard as T, GradientText as E, IllustratedEmptyState as D, Input as O, PagePurpose as k, Spinner as A } from "@burdenoff/fe-libs/ui";
16
+ import { jsx as j, jsxs as M } from "react/jsx-runtime";
13
17
  //#region src/bigconsole/pages/WorkflowsPage.tsx
14
- var O = c(function() {
15
- let c = t(), [O, k] = d("all"), A = e((e) => e.searchQuery), j = e((e) => e.setSearchQuery), M = e((e) => e.deleteDialogOpen), N = e((e) => e.currentWorkflow), P = e((e) => e.openDeleteDialog), F = e((e) => e.closeDeleteDialog), { loading: I, error: L, workflows: R, deleteWorkflow: z, refetch: B } = n(), V = u(() => {
16
- let e = [...R];
17
- if (O !== "all" && (e = e.filter((e) => e.status === O)), A.trim()) {
18
- let t = A.toLowerCase();
18
+ var N = l(function() {
19
+ let l = t(), { t: N } = b(), { hasPermission: P, isLoading: F } = h(), I = P(i.WORKFLOW_READ), L = P(i.WORKFLOW_UPDATE), R = P(i.WORKFLOW_DELETE), [z, B] = f("all"), V = e((e) => e.searchQuery), H = e((e) => e.setSearchQuery), U = e((e) => e.deleteDialogOpen), W = e((e) => e.currentWorkflow), G = e((e) => e.openDeleteDialog), K = e((e) => e.closeDeleteDialog), { loading: q, error: J, workflows: Y, deleteWorkflow: X, refetch: Z } = n(), Q = d(() => {
20
+ let e = [...Y];
21
+ if (z !== "all" && (e = e.filter((e) => e.status === z)), V.trim()) {
22
+ let t = V.toLowerCase();
19
23
  e = e.filter((e) => e.name.toLowerCase().includes(t) || e.key.toLowerCase().includes(t) || e.description?.toLowerCase().includes(t));
20
24
  }
21
25
  return e.sort((e, t) => new Date(t.updatedAt).getTime() - new Date(e.updatedAt).getTime());
22
26
  }, [
23
- R,
24
- O,
25
- A
26
- ]), H = l(() => {
27
- c(r());
28
- }, [c]), U = l((e) => {
29
- c(`/workflows/${e}`);
30
- }, [c]), W = l((e) => {
31
- c(`/workflows/${e}/edit`);
32
- }, [c]), G = l((e) => {
33
- let t = R.find((t) => t.id === e);
34
- t && P(t);
35
- }, [R, P]), K = l(async () => {
36
- if (N) {
27
+ Y,
28
+ z,
29
+ V
30
+ ]), $ = u(() => {
31
+ l(r());
32
+ }, [l]), ee = u((e) => {
33
+ l(`/workflows/${e}`);
34
+ }, [l]), te = u((e) => {
35
+ l(`/workflows/${e}/edit`);
36
+ }, [l]), ne = u((e) => {
37
+ let t = Y.find((t) => t.id === e);
38
+ t && G(t);
39
+ }, [Y, G]), re = u(async () => {
40
+ if (W) {
37
41
  try {
38
- await z(N.id), i() && a("success");
42
+ await X(W.id), a() && o("success");
39
43
  } catch (e) {
40
- throw i() && a("error"), e;
44
+ throw a() && o("error"), e;
41
45
  }
42
- F();
46
+ K();
43
47
  }
44
48
  }, [
45
- N,
46
- z,
47
- F
48
- ]);
49
- return L ? /* @__PURE__ */ E("div", {
49
+ W,
50
+ X,
51
+ K
52
+ ]), ie = [
53
+ {
54
+ value: "all",
55
+ label: N("bigconsole.workflows.filters.all", "All")
56
+ },
57
+ {
58
+ value: "draft",
59
+ label: N("bigconsole.workflows.status.draft", "Draft")
60
+ },
61
+ {
62
+ value: "active",
63
+ label: N("bigconsole.workflows.status.active", "Active")
64
+ },
65
+ {
66
+ value: "paused",
67
+ label: N("bigconsole.workflows.status.paused", "Paused")
68
+ },
69
+ {
70
+ value: "error",
71
+ label: N("bigconsole.workflows.status.error", "Error")
72
+ },
73
+ {
74
+ value: "archived",
75
+ label: N("bigconsole.workflows.status.archived", "Archived")
76
+ }
77
+ ];
78
+ return !F && !I ? /* @__PURE__ */ j(p, {
79
+ title: N("bigconsole.workflows.errors.accessDeniedTitle", "Access Denied"),
80
+ description: N("bigconsole.workflows.errors.accessDeniedListDescription", "You don't have permission to view workflows.")
81
+ }) : J ? /* @__PURE__ */ j("div", {
50
82
  style: { padding: "var(--space-pagePadding)" },
51
- children: /* @__PURE__ */ E(v, {
83
+ children: /* @__PURE__ */ j(C, {
52
84
  style: {
53
85
  borderColor: "var(--color-status-error-border)",
54
86
  backgroundColor: "var(--color-status-error-bgSubtle)"
55
87
  },
56
- children: /* @__PURE__ */ E(y, {
88
+ children: /* @__PURE__ */ j(w, {
57
89
  style: { padding: "var(--space-pagePadding)" },
58
- children: /* @__PURE__ */ D("div", {
90
+ children: /* @__PURE__ */ M("div", {
59
91
  style: {
60
92
  display: "flex",
61
93
  flexDirection: "column",
@@ -63,68 +95,68 @@ var O = c(function() {
63
95
  textAlign: "center"
64
96
  },
65
97
  children: [
66
- /* @__PURE__ */ E("div", {
98
+ /* @__PURE__ */ j("div", {
67
99
  style: {
68
100
  padding: "var(--space-controlGap)",
69
101
  borderRadius: "50%",
70
102
  backgroundColor: "var(--color-status-error-bgSubtle)",
71
103
  marginBottom: "var(--space-formGap)"
72
104
  },
73
- children: /* @__PURE__ */ E(f, { style: {
105
+ children: /* @__PURE__ */ j(g, { style: {
74
106
  height: "var(--size-icon-xl)",
75
107
  width: "var(--size-icon-xl)",
76
108
  color: "var(--color-status-error-text)"
77
109
  } })
78
110
  }),
79
- /* @__PURE__ */ E("h3", {
111
+ /* @__PURE__ */ j("h3", {
80
112
  style: {
81
113
  fontSize: "var(--font-size-body-lg)",
82
114
  fontWeight: "var(--font-weight-medium)",
83
115
  color: "var(--color-status-error-text)",
84
116
  marginBottom: "var(--space-controlGap)"
85
117
  },
86
- children: "Failed to load Workflows"
118
+ children: N("bigconsole.workflows.errors.loadFailedTitle", "Failed to load Workflows")
87
119
  }),
88
- /* @__PURE__ */ E("p", {
120
+ /* @__PURE__ */ j("p", {
89
121
  style: {
90
122
  fontSize: "var(--font-size-body-sm)",
91
123
  color: "var(--color-text-secondary)",
92
124
  marginBottom: "var(--space-formGap)"
93
125
  },
94
- children: L.message
126
+ children: J.message
95
127
  }),
96
- /* @__PURE__ */ E(_, {
128
+ /* @__PURE__ */ j(S, {
97
129
  size: "sm",
98
- onClick: () => B(),
99
- children: "Try Again"
130
+ onClick: () => Z(),
131
+ children: N("bigconsole.workflows.actions.tryAgain", "Try Again")
100
132
  })
101
133
  ]
102
134
  })
103
135
  })
104
136
  })
105
- }) : /* @__PURE__ */ D("div", {
137
+ }) : /* @__PURE__ */ M("div", {
106
138
  style: {
107
139
  minHeight: "100vh",
108
140
  backgroundColor: "var(--color-bg-canvas)"
109
141
  },
110
142
  children: [
111
- /* @__PURE__ */ D("div", {
143
+ /* @__PURE__ */ M("div", {
112
144
  className: "relative overflow-hidden border-b border-border-seam bg-gloss-card",
113
- children: [/* @__PURE__ */ E(g, { intensity: "subtle" }), /* @__PURE__ */ E("div", {
145
+ children: [/* @__PURE__ */ j(x, { intensity: "subtle" }), /* @__PURE__ */ j("div", {
114
146
  style: { padding: "var(--space-pagePadding)" },
115
- children: /* @__PURE__ */ D("div", {
147
+ children: /* @__PURE__ */ M("div", {
116
148
  style: {
117
149
  display: "flex",
118
150
  alignItems: "center",
119
151
  justifyContent: "space-between"
120
152
  },
121
- children: [/* @__PURE__ */ D("div", {
153
+ children: [/* @__PURE__ */ M("div", {
122
154
  style: {
123
155
  display: "flex",
124
156
  alignItems: "center",
125
157
  gap: "var(--space-formGap)"
126
158
  },
127
- children: [/* @__PURE__ */ E("div", {
159
+ children: [/* @__PURE__ */ j("div", {
128
160
  style: {
129
161
  display: "flex",
130
162
  height: "var(--size-controlHeight-lg)",
@@ -134,55 +166,59 @@ var O = c(function() {
134
166
  borderRadius: "var(--radius-card)",
135
167
  backgroundColor: "var(--color-action-primary-bg)"
136
168
  },
137
- children: /* @__PURE__ */ E(h, { style: {
169
+ children: /* @__PURE__ */ j(y, { style: {
138
170
  height: "var(--size-icon-lg)",
139
171
  width: "var(--size-icon-lg)",
140
172
  color: "var(--color-action-primary-text)"
141
173
  } })
142
- }), /* @__PURE__ */ D("div", { children: [/* @__PURE__ */ E("h1", {
174
+ }), /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("h1", {
143
175
  style: {
144
176
  fontSize: "var(--font-size-heading-h4)",
145
177
  fontWeight: "var(--font-weight-bold)",
146
178
  margin: 0,
147
179
  color: "var(--color-text-primary)"
148
180
  },
149
- children: /* @__PURE__ */ E(x, { children: "Workflows" })
150
- }), /* @__PURE__ */ E("p", {
181
+ children: /* @__PURE__ */ j(E, { children: N("bigconsole.workflows.list.title", "Workflows") })
182
+ }), /* @__PURE__ */ j("p", {
151
183
  style: {
152
184
  fontSize: "var(--font-size-body-sm)",
153
185
  color: "var(--color-text-secondary)",
154
186
  margin: 0
155
187
  },
156
- children: "Design ETL workflows with FluidGrids and link them to DataSinks"
188
+ children: N("bigconsole.workflows.list.subtitle", "Design ETL workflows with FluidGrids and link them to DataSinks")
157
189
  })] })]
158
- }), /* @__PURE__ */ E("div", {
190
+ }), /* @__PURE__ */ j("div", {
159
191
  style: {
160
192
  display: "flex",
161
193
  alignItems: "center",
162
194
  gap: "var(--space-controlGap)"
163
195
  },
164
- children: /* @__PURE__ */ D(_, {
165
- onClick: H,
166
- children: [/* @__PURE__ */ E(p, { style: {
167
- marginRight: "var(--space-iconGap)",
168
- height: "var(--size-icon-sm)",
169
- width: "var(--size-icon-sm)"
170
- } }), "Design Workflow"]
196
+ children: /* @__PURE__ */ j(m, {
197
+ permission: i.WORKFLOW_CREATE,
198
+ deniedBehavior: "disable",
199
+ children: /* @__PURE__ */ M(S, {
200
+ onClick: $,
201
+ children: [/* @__PURE__ */ j(_, { style: {
202
+ marginRight: "var(--space-iconGap)",
203
+ height: "var(--size-icon-sm)",
204
+ width: "var(--size-icon-sm)"
205
+ } }), N("bigconsole.workflows.actions.designWorkflow", "Design Workflow")]
206
+ })
171
207
  })
172
208
  })]
173
209
  })
174
210
  })]
175
211
  }),
176
- /* @__PURE__ */ D("div", {
212
+ /* @__PURE__ */ M("div", {
177
213
  style: { padding: "var(--space-pagePadding)" },
178
214
  children: [
179
- /* @__PURE__ */ E(w, {
215
+ /* @__PURE__ */ j(k, {
180
216
  className: "mb-[var(--space-sectionGap)]",
181
- children: "Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems, transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep dashboards fed with fresh, shaped data without writing glue code."
217
+ children: N("bigconsole.workflows.list.purpose", "Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems, transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep dashboards fed with fresh, shaped data without writing glue code.")
182
218
  }),
183
- /* @__PURE__ */ E("div", {
219
+ /* @__PURE__ */ j("div", {
184
220
  style: { marginBottom: "var(--space-formGap)" },
185
- children: /* @__PURE__ */ E("div", {
221
+ children: /* @__PURE__ */ j("div", {
186
222
  style: {
187
223
  display: "flex",
188
224
  alignItems: "center",
@@ -192,34 +228,9 @@ var O = c(function() {
192
228
  borderRadius: "var(--radius-card)",
193
229
  width: "fit-content"
194
230
  },
195
- children: [
196
- {
197
- value: "all",
198
- label: "All"
199
- },
200
- {
201
- value: "draft",
202
- label: "Draft"
203
- },
204
- {
205
- value: "active",
206
- label: "Active"
207
- },
208
- {
209
- value: "paused",
210
- label: "Paused"
211
- },
212
- {
213
- value: "error",
214
- label: "Error"
215
- },
216
- {
217
- value: "archived",
218
- label: "Archived"
219
- }
220
- ].map((e) => /* @__PURE__ */ E("button", {
231
+ children: ie.map((e) => /* @__PURE__ */ j("button", {
221
232
  type: "button",
222
- onClick: () => k(e.value),
233
+ onClick: () => B(e.value),
223
234
  style: {
224
235
  padding: "var(--space-controlGap) var(--space-formGap)",
225
236
  fontSize: "var(--font-size-body-sm)",
@@ -228,22 +239,22 @@ var O = c(function() {
228
239
  border: "none",
229
240
  cursor: "pointer",
230
241
  transition: "all 0.2s ease",
231
- backgroundColor: O === e.value ? "var(--color-bg-surface)" : "transparent",
232
- color: O === e.value ? "var(--color-text-primary)" : "var(--color-text-secondary)",
233
- boxShadow: O === e.value ? "0 1px 2px rgba(0,0,0,0.05)" : "none"
242
+ backgroundColor: z === e.value ? "var(--color-bg-surface)" : "transparent",
243
+ color: z === e.value ? "var(--color-text-primary)" : "var(--color-text-secondary)",
244
+ boxShadow: z === e.value ? "0 1px 2px rgba(0,0,0,0.05)" : "none"
234
245
  },
235
246
  children: e.label
236
247
  }, e.value))
237
248
  })
238
249
  }),
239
- /* @__PURE__ */ E("div", {
250
+ /* @__PURE__ */ j("div", {
240
251
  style: { marginBottom: "var(--space-sectionGap)" },
241
- children: /* @__PURE__ */ D("div", {
252
+ children: /* @__PURE__ */ M("div", {
242
253
  style: {
243
254
  position: "relative",
244
255
  maxWidth: "400px"
245
256
  },
246
- children: [/* @__PURE__ */ E(m, { style: {
257
+ children: [/* @__PURE__ */ j(v, { style: {
247
258
  position: "absolute",
248
259
  left: "var(--space-controlGap)",
249
260
  top: "50%",
@@ -251,11 +262,11 @@ var O = c(function() {
251
262
  height: "var(--size-icon-sm)",
252
263
  width: "var(--size-icon-sm)",
253
264
  color: "var(--color-text-muted)"
254
- } }), /* @__PURE__ */ E(C, {
265
+ } }), /* @__PURE__ */ j(O, {
255
266
  type: "text",
256
- placeholder: "Search workflows...",
257
- value: A,
258
- onChange: (e) => j(e.target.value),
267
+ placeholder: N("bigconsole.workflows.filters.searchPlaceholder", "Search workflows..."),
268
+ value: V,
269
+ onChange: (e) => H(e.target.value),
259
270
  style: {
260
271
  paddingLeft: "var(--size-controlHeight-md)",
261
272
  height: "var(--size-controlHeight-md)"
@@ -263,79 +274,83 @@ var O = c(function() {
263
274
  })]
264
275
  })
265
276
  }),
266
- I && R.length === 0 && /* @__PURE__ */ E("div", {
277
+ q && Y.length === 0 && /* @__PURE__ */ j("div", {
267
278
  style: {
268
279
  display: "flex",
269
280
  alignItems: "center",
270
281
  justifyContent: "center",
271
282
  padding: "80px 0"
272
283
  },
273
- children: /* @__PURE__ */ D("div", {
284
+ children: /* @__PURE__ */ M("div", {
274
285
  style: { textAlign: "center" },
275
- children: [/* @__PURE__ */ E(T, { style: {
286
+ children: [/* @__PURE__ */ j(A, { style: {
276
287
  height: "var(--size-icon-xl)",
277
288
  width: "var(--size-icon-xl)",
278
289
  margin: "0 auto var(--space-formGap)"
279
- } }), /* @__PURE__ */ E("p", {
290
+ } }), /* @__PURE__ */ j("p", {
280
291
  style: {
281
292
  fontSize: "var(--font-size-body-sm)",
282
293
  color: "var(--color-text-muted)"
283
294
  },
284
- children: "Loading workflows..."
295
+ children: N("bigconsole.workflows.list.loading", "Loading workflows...")
285
296
  })]
286
297
  })
287
298
  }),
288
- !I && R.length === 0 && /* @__PURE__ */ E(b, {
299
+ !q && Y.length === 0 && /* @__PURE__ */ j(T, {
289
300
  treatment: "insight",
290
301
  className: "border-border-seam",
291
- children: /* @__PURE__ */ E(S, {
302
+ children: /* @__PURE__ */ j(D, {
292
303
  illustration: "empty-data",
293
- title: "No Workflows yet",
294
- description: "Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks.",
295
- action: /* @__PURE__ */ D(_, {
296
- onClick: H,
297
- children: [/* @__PURE__ */ E(p, { style: {
298
- marginRight: "var(--space-iconGap)",
299
- height: "var(--size-icon-sm)",
300
- width: "var(--size-icon-sm)"
301
- } }), "Design Workflow"]
304
+ title: N("bigconsole.workflows.list.emptyTitle", "No Workflows yet"),
305
+ description: N("bigconsole.workflows.list.emptyDescription", "Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks."),
306
+ action: /* @__PURE__ */ j(m, {
307
+ permission: i.WORKFLOW_CREATE,
308
+ deniedBehavior: "disable",
309
+ children: /* @__PURE__ */ M(S, {
310
+ onClick: $,
311
+ children: [/* @__PURE__ */ j(_, { style: {
312
+ marginRight: "var(--space-iconGap)",
313
+ height: "var(--size-icon-sm)",
314
+ width: "var(--size-icon-sm)"
315
+ } }), N("bigconsole.workflows.actions.designWorkflow", "Design Workflow")]
316
+ })
302
317
  })
303
318
  })
304
319
  }),
305
- !I && V.length === 0 && R.length > 0 && /* @__PURE__ */ E(b, {
320
+ !q && Q.length === 0 && Y.length > 0 && /* @__PURE__ */ j(T, {
306
321
  treatment: "insight",
307
322
  className: "border-border-seam",
308
- children: /* @__PURE__ */ E(S, {
323
+ children: /* @__PURE__ */ j(D, {
309
324
  illustration: "empty-search",
310
- title: "No matching workflows",
311
- description: "No workflows match your filters"
325
+ title: N("bigconsole.workflows.list.noResultsTitle", "No matching workflows"),
326
+ description: N("bigconsole.workflows.list.noResultsDescription", "No workflows match your filters")
312
327
  })
313
328
  }),
314
- V.length > 0 && /* @__PURE__ */ E("div", {
329
+ Q.length > 0 && /* @__PURE__ */ j("div", {
315
330
  style: {
316
331
  display: "grid",
317
332
  gridTemplateColumns: "repeat(auto-fill, minmax(320px, 1fr))",
318
333
  gap: "var(--space-formGap)"
319
334
  },
320
- children: V.map((e) => /* @__PURE__ */ E(s, {
335
+ children: Q.map((e) => /* @__PURE__ */ j(c, {
321
336
  workflow: e,
322
- onView: U,
323
- onEdit: W,
324
- onDelete: G
337
+ onView: ee,
338
+ onEdit: L ? te : void 0,
339
+ onDelete: R ? ne : void 0
325
340
  }, e.id))
326
341
  })
327
342
  ]
328
343
  }),
329
- N && /* @__PURE__ */ E(o, {
330
- workflow: N,
331
- isOpen: M,
332
- onClose: F,
333
- onConfirm: K
344
+ W && /* @__PURE__ */ j(s, {
345
+ workflow: W,
346
+ isOpen: U,
347
+ onClose: K,
348
+ onConfirm: re
334
349
  })
335
350
  ]
336
351
  });
337
352
  });
338
353
  //#endregion
339
- export { O as WorkflowsPage };
354
+ export { N as WorkflowsPage };
340
355
 
341
356
  //# sourceMappingURL=WorkflowsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkflowsPage.js","names":[],"sources":["../../../src/bigconsole/pages/WorkflowsPage.tsx"],"sourcesContent":["/**\n * Workflows Page\n *\n * List and manage FluidGrids Workflows.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { newWorkflowPath } from '../BigConsoleRoutes';\nimport { useWorkflowOperations } from '../hooks/useWorkflowOperations';\nimport { useWorkflowStore } from '../store/workflowStore';\nimport { WorkflowCard } from '../components/workflow/WorkflowCard';\nimport { WorkflowDeleteDialog } from '../components/workflow/WorkflowDeleteDialog';\nimport type { FluidGridsWorkflowStatus } from '../types';\n\n// fe-libs UI components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { AuroraBackground, GradientText, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport { Plus, Search, Workflow, AlertCircle } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ntype StatusFilter = 'all' | FluidGridsWorkflowStatus;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowsPage = memo(function WorkflowsPage() {\n const navigate = useAppNavigate();\n\n // Local state\n const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');\n\n // Store state\n const searchQuery = useWorkflowStore((state) => state.searchQuery);\n const setSearchQuery = useWorkflowStore((state) => state.setSearchQuery);\n const deleteDialogOpen = useWorkflowStore((state) => state.deleteDialogOpen);\n const currentWorkflow = useWorkflowStore((state) => state.currentWorkflow);\n const openDeleteDialog = useWorkflowStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = useWorkflowStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, workflows, deleteWorkflow, refetch } = useWorkflowOperations();\n\n // Filter workflows\n const filteredWorkflows = useMemo(() => {\n let filtered = [...workflows];\n\n // Apply status filter\n if (statusFilter !== 'all') {\n filtered = filtered.filter((wf) => wf.status === statusFilter);\n }\n\n // Apply search filter\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (wf) =>\n wf.name.toLowerCase().includes(query) ||\n wf.key.toLowerCase().includes(query) ||\n wf.description?.toLowerCase().includes(query)\n );\n }\n\n // Sort by updatedAt descending\n return filtered.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n }, [workflows, statusFilter, searchQuery]);\n\n // Handlers\n const handleCreateWorkflow = useCallback(() => {\n navigate(newWorkflowPath());\n }, [navigate]);\n\n const handleViewWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}`);\n },\n [navigate]\n );\n\n const handleEditWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}/edit`);\n },\n [navigate]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const workflow = workflows.find((wf) => wf.id === id);\n if (workflow) {\n openDeleteDialog(workflow);\n }\n },\n [workflows, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentWorkflow) {\n try {\n await deleteWorkflow(currentWorkflow.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentWorkflow, deleteWorkflow, closeDeleteDialog]);\n\n // Status filter options\n const statusOptions: { value: StatusFilter; label: string }[] = [\n { value: 'all', label: 'All' },\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'paused', label: 'Paused' },\n { value: 'error', label: 'Error' },\n { value: 'archived', label: 'Archived' },\n ];\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>\n <div\n style={{\n padding: 'var(--space-controlGap)',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <AlertCircle\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-status-error-text)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Failed to load Workflows\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()}>\n Try Again\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div className=\"relative overflow-hidden border-b border-border-seam bg-gloss-card\">\n <AuroraBackground intensity=\"subtle\" />\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <Workflow\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n <GradientText>Workflows</GradientText>\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n Design ETL workflows with FluidGrids and link them to DataSinks\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Design Workflow\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <PagePurpose className=\"mb-[var(--space-sectionGap)]\">\n Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems,\n transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep\n dashboards fed with fresh, shaped data without writing glue code.\n </PagePurpose>\n\n {/* Status Filter Tabs */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '2px',\n padding: '4px',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-card)',\n width: 'fit-content',\n }}\n >\n {statusOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => setStatusFilter(option.value)}\n style={{\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n backgroundColor: statusFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color: statusFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: statusFilter === option.value ? '0 1px 2px rgba(0,0,0,0.05)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Search Bar */}\n <div style={{ marginBottom: 'var(--space-sectionGap)' }}>\n <div style={{ position: 'relative', maxWidth: '400px' }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder=\"Search workflows...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n\n {/* Loading state */}\n {loading && workflows.length === 0 && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n Loading workflows...\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && workflows.length === 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No Workflows yet\"\n description=\"Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks.\"\n action={\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Design Workflow\n </Button>\n }\n />\n </GlassCard>\n )}\n\n {/* No results state */}\n {!loading && filteredWorkflows.length === 0 && workflows.length > 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching workflows\"\n description=\"No workflows match your filters\"\n />\n </GlassCard>\n )}\n\n {/* Workflow Grid */}\n {filteredWorkflows.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredWorkflows.map((workflow) => (\n <WorkflowCard\n key={workflow.id}\n workflow={workflow}\n onView={handleViewWorkflow}\n onEdit={handleEditWorkflow}\n onDelete={handleDeleteClick}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Delete Dialog */}\n {currentWorkflow && (\n <WorkflowDeleteDialog\n workflow={currentWorkflow}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default WorkflowsPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"WorkflowsPage.js","names":[],"sources":["../../../src/bigconsole/pages/WorkflowsPage.tsx"],"sourcesContent":["/**\n * Workflows Page\n *\n * List and manage FluidGrids Workflows.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { newWorkflowPath } from '../BigConsoleRoutes';\nimport { useWorkflowOperations } from '../hooks/useWorkflowOperations';\nimport { useWorkflowStore } from '../store/workflowStore';\nimport { WorkflowCard } from '../components/workflow/WorkflowCard';\nimport { WorkflowDeleteDialog } from '../components/workflow/WorkflowDeleteDialog';\nimport type { FluidGridsWorkflowStatus } from '../types';\n\n// fe-libs UI components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { AuroraBackground, GradientText, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport { Plus, Search, Workflow, AlertCircle } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ntype StatusFilter = 'all' | FluidGridsWorkflowStatus;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowsPage = memo(function WorkflowsPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n\n // RBAC permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_READ);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_DELETE);\n\n // Local state\n const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');\n\n // Store state\n const searchQuery = useWorkflowStore((state) => state.searchQuery);\n const setSearchQuery = useWorkflowStore((state) => state.setSearchQuery);\n const deleteDialogOpen = useWorkflowStore((state) => state.deleteDialogOpen);\n const currentWorkflow = useWorkflowStore((state) => state.currentWorkflow);\n const openDeleteDialog = useWorkflowStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = useWorkflowStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, workflows, deleteWorkflow, refetch } = useWorkflowOperations();\n\n // Filter workflows\n const filteredWorkflows = useMemo(() => {\n let filtered = [...workflows];\n\n // Apply status filter\n if (statusFilter !== 'all') {\n filtered = filtered.filter((wf) => wf.status === statusFilter);\n }\n\n // Apply search filter\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (wf) =>\n wf.name.toLowerCase().includes(query) ||\n wf.key.toLowerCase().includes(query) ||\n wf.description?.toLowerCase().includes(query)\n );\n }\n\n // Sort by updatedAt descending\n return filtered.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n }, [workflows, statusFilter, searchQuery]);\n\n // Handlers\n const handleCreateWorkflow = useCallback(() => {\n navigate(newWorkflowPath());\n }, [navigate]);\n\n const handleViewWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}`);\n },\n [navigate]\n );\n\n const handleEditWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}/edit`);\n },\n [navigate]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const workflow = workflows.find((wf) => wf.id === id);\n if (workflow) {\n openDeleteDialog(workflow);\n }\n },\n [workflows, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentWorkflow) {\n try {\n await deleteWorkflow(currentWorkflow.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentWorkflow, deleteWorkflow, closeDeleteDialog]);\n\n // Status filter options\n const statusOptions: { value: StatusFilter; label: string }[] = [\n { value: 'all', label: t('bigconsole.workflows.filters.all', 'All') },\n { value: 'draft', label: t('bigconsole.workflows.status.draft', 'Draft') },\n { value: 'active', label: t('bigconsole.workflows.status.active', 'Active') },\n { value: 'paused', label: t('bigconsole.workflows.status.paused', 'Paused') },\n { value: 'error', label: t('bigconsole.workflows.status.error', 'Error') },\n { value: 'archived', label: t('bigconsole.workflows.status.archived', 'Archived') },\n ];\n\n // Page-level read gate — only after permissions have finished loading so we\n // don't flash Access Denied while the permission set is still being fetched.\n if (!permissionsLoading && !canRead) {\n return (\n <AccessDenied\n title={t('bigconsole.workflows.errors.accessDeniedTitle', 'Access Denied')}\n description={t(\n 'bigconsole.workflows.errors.accessDeniedListDescription',\n \"You don't have permission to view workflows.\"\n )}\n />\n );\n }\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>\n <div\n style={{\n padding: 'var(--space-controlGap)',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <AlertCircle\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-status-error-text)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.workflows.errors.loadFailedTitle', 'Failed to load Workflows')}\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()}>\n {t('bigconsole.workflows.actions.tryAgain', 'Try Again')}\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div className=\"relative overflow-hidden border-b border-border-seam bg-gloss-card\">\n <AuroraBackground intensity=\"subtle\" />\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <Workflow\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n <GradientText>{t('bigconsole.workflows.list.title', 'Workflows')}</GradientText>\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n {t(\n 'bigconsole.workflows.list.subtitle',\n 'Design ETL workflows with FluidGrids and link them to DataSinks'\n )}\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {t('bigconsole.workflows.actions.designWorkflow', 'Design Workflow')}\n </Button>\n </PermissionButton>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <PagePurpose className=\"mb-[var(--space-sectionGap)]\">\n {t(\n 'bigconsole.workflows.list.purpose',\n 'Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems, transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep dashboards fed with fresh, shaped data without writing glue code.'\n )}\n </PagePurpose>\n\n {/* Status Filter Tabs */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '2px',\n padding: '4px',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-card)',\n width: 'fit-content',\n }}\n >\n {statusOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => setStatusFilter(option.value)}\n style={{\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n backgroundColor: statusFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color: statusFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: statusFilter === option.value ? '0 1px 2px rgba(0,0,0,0.05)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Search Bar */}\n <div style={{ marginBottom: 'var(--space-sectionGap)' }}>\n <div style={{ position: 'relative', maxWidth: '400px' }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder={t('bigconsole.workflows.filters.searchPlaceholder', 'Search workflows...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n\n {/* Loading state */}\n {loading && workflows.length === 0 && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n {t('bigconsole.workflows.list.loading', 'Loading workflows...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && workflows.length === 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('bigconsole.workflows.list.emptyTitle', 'No Workflows yet')}\n description={t(\n 'bigconsole.workflows.list.emptyDescription',\n 'Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks.'\n )}\n action={\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {t('bigconsole.workflows.actions.designWorkflow', 'Design Workflow')}\n </Button>\n </PermissionButton>\n }\n />\n </GlassCard>\n )}\n\n {/* No results state */}\n {!loading && filteredWorkflows.length === 0 && workflows.length > 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title={t('bigconsole.workflows.list.noResultsTitle', 'No matching workflows')}\n description={t('bigconsole.workflows.list.noResultsDescription', 'No workflows match your filters')}\n />\n </GlassCard>\n )}\n\n {/* Workflow Grid */}\n {filteredWorkflows.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredWorkflows.map((workflow) => (\n <WorkflowCard\n key={workflow.id}\n workflow={workflow}\n onView={handleViewWorkflow}\n onEdit={canUpdate ? handleEditWorkflow : undefined}\n onDelete={canDelete ? handleDeleteClick : undefined}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Delete Dialog */}\n {currentWorkflow && (\n <WorkflowDeleteDialog\n workflow={currentWorkflow}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default WorkflowsPage;\n"],"mappings":"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"}