@burdenoff/microfe-bigconsole 2026.805.2 → 2026.812.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.
Files changed (253) hide show
  1. package/dist/bigconsole/components/DrilldownDashboardRenderer.js +118 -106
  2. package/dist/bigconsole/components/DrilldownDashboardRenderer.js.map +1 -1
  3. package/dist/bigconsole/components/DrilldownModal.js +54 -50
  4. package/dist/bigconsole/components/DrilldownModal.js.map +1 -1
  5. package/dist/bigconsole/components/builder/BuilderCanvas.js +2 -2
  6. package/dist/bigconsole/components/builder/BuilderCanvas.js.map +1 -1
  7. package/dist/bigconsole/components/builder/BuilderTopbar.js +3 -3
  8. package/dist/bigconsole/components/builder/BuilderTopbar.js.map +1 -1
  9. package/dist/bigconsole/components/builder/inspector/AdvancedSection.js +24 -25
  10. package/dist/bigconsole/components/builder/inspector/AdvancedSection.js.map +1 -1
  11. package/dist/bigconsole/components/builder/inspector/AppearanceSection.js +40 -29
  12. package/dist/bigconsole/components/builder/inspector/AppearanceSection.js.map +1 -1
  13. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +145 -111
  14. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
  15. package/dist/bigconsole/components/builder/inspector/GeneralSection.js +58 -44
  16. package/dist/bigconsole/components/builder/inspector/GeneralSection.js.map +1 -1
  17. package/dist/bigconsole/components/common/Section.js +70 -0
  18. package/dist/bigconsole/components/common/Section.js.map +1 -0
  19. package/dist/bigconsole/components/common/index.js +2 -0
  20. package/dist/bigconsole/components/common/sectionStyles.js +42 -0
  21. package/dist/bigconsole/components/common/sectionStyles.js.map +1 -0
  22. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +269 -251
  23. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
  24. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +214 -223
  25. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  26. package/dist/bigconsole/components/dashboard/DashboardGrid.js +12 -18
  27. package/dist/bigconsole/components/dashboard/DashboardGrid.js.map +1 -1
  28. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +110 -102
  29. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  30. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +81 -68
  31. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  32. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +125 -159
  33. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js.map +1 -1
  34. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +147 -144
  35. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
  36. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +154 -153
  37. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
  38. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +82 -79
  39. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
  40. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +171 -284
  41. package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
  42. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +250 -273
  43. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  44. package/dist/bigconsole/components/dashboard/LiveBoardBanner.js +45 -53
  45. package/dist/bigconsole/components/dashboard/LiveBoardBanner.js.map +1 -1
  46. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +157 -148
  47. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
  48. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
  49. package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
  50. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +167 -161
  51. package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
  52. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +181 -190
  53. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
  54. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +101 -95
  55. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
  56. package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js +20 -18
  57. package/dist/bigconsole/components/dashboard/StoreTemplatePicker.js.map +1 -1
  58. package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
  59. package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js +26 -58
  60. package/dist/bigconsole/components/dashboard/TemplateSetupBanner.js.map +1 -1
  61. package/dist/bigconsole/components/dashboard/WidgetPalette.js +307 -229
  62. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  63. package/dist/bigconsole/components/datasink/CacheTTLSelector.js +128 -129
  64. package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
  65. package/dist/bigconsole/components/datasink/DataSinkCard.js +78 -79
  66. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  67. package/dist/bigconsole/components/datasink/DataSinkDataViewer.js +33 -34
  68. package/dist/bigconsole/components/datasink/DataSinkDataViewer.js.map +1 -1
  69. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +79 -61
  70. package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
  71. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +75 -64
  72. package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
  73. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js +1 -1
  74. package/dist/bigconsole/components/datasink/DataSinkStatusBadge.js.map +1 -1
  75. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +20 -19
  76. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js.map +1 -1
  77. package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +127 -171
  78. package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js.map +1 -1
  79. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
  80. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
  81. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +312 -307
  82. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  83. package/dist/bigconsole/components/datasink/LinkedParsersPanel.js +65 -66
  84. package/dist/bigconsole/components/datasink/LinkedParsersPanel.js.map +1 -1
  85. package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js +121 -127
  86. package/dist/bigconsole/components/datasink/LinkedWorkflowsPanel.js.map +1 -1
  87. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +194 -189
  88. package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
  89. package/dist/bigconsole/components/datasink/SetupStateBadge.js +3 -3
  90. package/dist/bigconsole/components/datasink/SetupStateBadge.js.map +1 -1
  91. package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js +95 -95
  92. package/dist/bigconsole/components/datasink/WorkflowStatusPanel.js.map +1 -1
  93. package/dist/bigconsole/components/parser/DataSinkSelector.js +163 -131
  94. package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
  95. package/dist/bigconsole/components/parser/ExpressionEditor.js +3 -3
  96. package/dist/bigconsole/components/parser/ExpressionEditor.js.map +1 -1
  97. package/dist/bigconsole/components/parser/ImportParserDialog.js +205 -260
  98. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  99. package/dist/bigconsole/components/parser/ParserCard.js +133 -114
  100. package/dist/bigconsole/components/parser/ParserCard.js.map +1 -1
  101. package/dist/bigconsole/components/parser/ParserSelector.js +193 -174
  102. package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
  103. package/dist/bigconsole/components/parser/ParserStatusBadge.js +2 -2
  104. package/dist/bigconsole/components/parser/ParserStatusBadge.js.map +1 -1
  105. package/dist/bigconsole/components/parser/ParserTypeBadge.js +4 -4
  106. package/dist/bigconsole/components/parser/ParserTypeBadge.js.map +1 -1
  107. package/dist/bigconsole/components/pipeline/PipelineCard.js +134 -89
  108. package/dist/bigconsole/components/pipeline/PipelineCard.js.map +1 -1
  109. package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js +77 -64
  110. package/dist/bigconsole/components/pipeline/PipelineDeleteDialog.js.map +1 -1
  111. package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js +7 -10
  112. package/dist/bigconsole/components/pipeline/PipelineStatusBadge.js.map +1 -1
  113. package/dist/bigconsole/components/preview/AiPreviewContent.js +31 -32
  114. package/dist/bigconsole/components/preview/AiPreviewContent.js.map +1 -1
  115. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +152 -103
  116. package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
  117. package/dist/bigconsole/components/preview/AiPreviewPanel.js +193 -148
  118. package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
  119. package/dist/bigconsole/components/preview/previewShared.js +41 -23
  120. package/dist/bigconsole/components/preview/previewShared.js.map +1 -1
  121. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +405 -364
  122. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  123. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +265 -237
  124. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  125. package/dist/bigconsole/components/widgets/PropertiesPanel.js +764 -821
  126. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  127. package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js +7 -5
  128. package/dist/bigconsole/components/widgets/WidgetErrorBoundary.js.map +1 -1
  129. package/dist/bigconsole/components/widgets/WidgetHeader.js +7 -8
  130. package/dist/bigconsole/components/widgets/WidgetHeader.js.map +1 -1
  131. package/dist/bigconsole/components/widgets/WidgetWrapper.js +8 -7
  132. package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
  133. package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js +1 -1
  134. package/dist/bigconsole/components/widgets/adaptive-card/AdaptiveCardWidget.js.map +1 -1
  135. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +46 -49
  136. package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
  137. package/dist/bigconsole/components/widgets/chart/ChartConfig.js +154 -147
  138. package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
  139. package/dist/bigconsole/components/widgets/comments/WidgetComments.js +118 -101
  140. package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
  141. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +244 -191
  142. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  143. package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
  144. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  145. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +92 -76
  146. package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
  147. package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js +1 -1
  148. package/dist/bigconsole/components/widgets/gauge/GaugeWidget.js.map +1 -1
  149. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +89 -86
  150. package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
  151. package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js +2 -2
  152. package/dist/bigconsole/components/widgets/iframe-widget/IframeWidget.js.map +1 -1
  153. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +64 -63
  154. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  155. package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js +2 -2
  156. package/dist/bigconsole/components/widgets/kpi-comparison/KPIComparisonWidget.js.map +1 -1
  157. package/dist/bigconsole/components/widgets/list/ListConfig.js +65 -58
  158. package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
  159. package/dist/bigconsole/components/widgets/list/ListItem.js +1 -1
  160. package/dist/bigconsole/components/widgets/list/ListItem.js.map +1 -1
  161. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +1 -1
  162. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
  163. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +79 -72
  164. package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
  165. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
  166. package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
  167. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
  168. package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
  169. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +181 -180
  170. package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
  171. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +100 -90
  172. package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
  173. package/dist/bigconsole/components/widgets/retention/RetentionWidget.js +3 -3
  174. package/dist/bigconsole/components/widgets/retention/RetentionWidget.js.map +1 -1
  175. package/dist/bigconsole/components/widgets/states/EmptyState.js +6 -4
  176. package/dist/bigconsole/components/widgets/states/EmptyState.js.map +1 -1
  177. package/dist/bigconsole/components/widgets/states/ErrorState.js +7 -5
  178. package/dist/bigconsole/components/widgets/states/ErrorState.js.map +1 -1
  179. package/dist/bigconsole/components/widgets/states/LoadingState.js +5 -4
  180. package/dist/bigconsole/components/widgets/states/LoadingState.js.map +1 -1
  181. package/dist/bigconsole/components/widgets/table/TableConfig.js +193 -172
  182. package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
  183. package/dist/bigconsole/components/widgets/table/TableHeader.js +1 -1
  184. package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
  185. package/dist/bigconsole/components/widgets/table/TableWidget.js +1 -1
  186. package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
  187. package/dist/bigconsole/components/widgets/text-widget/TextWidget.js +1 -1
  188. package/dist/bigconsole/components/widgets/text-widget/TextWidget.js.map +1 -1
  189. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +3 -3
  190. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
  191. package/dist/bigconsole/components/widgets/utils/conditionalFormat.js +2 -2
  192. package/dist/bigconsole/components/widgets/utils/conditionalFormat.js.map +1 -1
  193. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +283 -249
  194. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  195. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +28 -20
  196. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  197. package/dist/bigconsole/components/workflow/WorkflowCard.js +92 -77
  198. package/dist/bigconsole/components/workflow/WorkflowCard.js.map +1 -1
  199. package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js +70 -51
  200. package/dist/bigconsole/components/workflow/WorkflowDeleteDialog.js.map +1 -1
  201. package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js +16 -17
  202. package/dist/bigconsole/components/workflow/WorkflowStatusBadge.js.map +1 -1
  203. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +46 -42
  204. package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
  205. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +372 -348
  206. package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
  207. package/dist/bigconsole/hooks/useModalFocusTrap.js +53 -0
  208. package/dist/bigconsole/hooks/useModalFocusTrap.js.map +1 -0
  209. package/dist/bigconsole/pages/DashboardBuilderPage.js +153 -142
  210. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  211. package/dist/bigconsole/pages/DashboardViewPage.js +230 -220
  212. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  213. package/dist/bigconsole/pages/DashboardsPage.js +832 -790
  214. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  215. package/dist/bigconsole/pages/DataParsersPage.js +249 -304
  216. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  217. package/dist/bigconsole/pages/DataSinkBuilderPage.js +324 -349
  218. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  219. package/dist/bigconsole/pages/DataSinkViewPage.js +336 -323
  220. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  221. package/dist/bigconsole/pages/DataSinksPage.js +356 -458
  222. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  223. package/dist/bigconsole/pages/DataSourcesPage.js +14 -8
  224. package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
  225. package/dist/bigconsole/pages/HomePage.js +186 -193
  226. package/dist/bigconsole/pages/HomePage.js.map +1 -1
  227. package/dist/bigconsole/pages/InsightsPage.js +901 -724
  228. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  229. package/dist/bigconsole/pages/ParserBuilderPage.js +769 -675
  230. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  231. package/dist/bigconsole/pages/ParserViewPage.js +382 -354
  232. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  233. package/dist/bigconsole/pages/PipelineBuilderPage.js +540 -420
  234. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  235. package/dist/bigconsole/pages/PipelineViewPage.js +416 -384
  236. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  237. package/dist/bigconsole/pages/PipelinesPage.js +260 -309
  238. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  239. package/dist/bigconsole/pages/SettingsPage.js +177 -172
  240. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  241. package/dist/bigconsole/pages/WidgetDemoPage.js +278 -142
  242. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  243. package/dist/bigconsole/pages/WorkflowViewPage.js +382 -366
  244. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  245. package/dist/bigconsole/pages/WorkflowsPage.js +202 -316
  246. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  247. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
  248. package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
  249. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
  250. package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
  251. package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
  252. package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
  253. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DataSinksPage.js","names":[],"sources":["../../../src/bigconsole/pages/DataSinksPage.tsx"],"sourcesContent":["/**\n * DataSinksPage\n *\n * List and manage DataSinks - fetches data from backend.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { type FC, memo, useCallback, useMemo, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { getProfileScopedKey } from '@burdenoff/fe-libs/shared/utils';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { useDataSinkOperations } from '../hooks/useDataSinkOperations';\nimport { useExportDataSink } from '../hooks/useExportDataSink';\nimport { useDataSinkStore } from '../store/dataSinkStore';\nimport type { DataSink, DataSinkSetupState } from '../types';\nimport { DataSinkCard } from '../components/datasink/DataSinkCard';\nimport { DataSinkDeleteDialog } from '../components/datasink/DataSinkDeleteDialog';\nimport { DataSinkRefreshDialog } from '../components/datasink/DataSinkRefreshDialog';\nimport { ImportDataSinkDialog } from '../components/datasink/ImportDataSinkDialog';\n\n// fe-libs components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport {\n AuroraBackground,\n GradientText,\n GlassCard,\n IllustratedEmptyState,\n CTAOverflowMenu,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport {\n Plus,\n Search,\n AlertCircle,\n Container,\n X,\n Upload,\n LayoutGrid,\n Table2,\n Eye,\n Pencil,\n RefreshCw,\n Download,\n Trash2,\n} from 'lucide-react';\nimport { DataSinkStatusBadge } from '../components/datasink/DataSinkStatusBadge';\nimport { SetupStateBadge } from '../components/datasink/SetupStateBadge';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype SetupStateFilter = 'all' | 'in_progress' | 'completed';\ntype ListViewMode = 'grid' | 'table';\n\nconst VIEW_MODE_KEY = 'bigconsole-datasinks-view-mode';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Determine setup state for a DataSink based on its properties.\n */\nconst getSetupState = (dataSink: DataSink): DataSinkSetupState => {\n if (dataSink.setupState === 'completed') {\n return 'completed';\n }\n if (dataSink.ttl !== null && dataSink.ttl !== undefined && dataSink.ttl > 0) {\n return 'completed';\n }\n if (dataSink.fluidGridsWorkflowId && dataSink.data && Object.keys(dataSink.data).length > 0) {\n return 'completed';\n }\n if (dataSink.fluidGridsWorkflowId) {\n return 'workflow_running';\n }\n return 'workflow_pending';\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DataSinksPage: FC = memo(function DataSinksPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string) => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n },\n [t]\n );\n\n // Permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_READ);\n const canCreate = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_CREATE);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_DELETE);\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_EXECUTE);\n\n // Local state\n const [setupStateFilter, setSetupStateFilter] = useState<SetupStateFilter>('all');\n const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);\n const [viewMode, setViewMode] = useState<ListViewMode>(\n () => (localStorage.getItem(getProfileScopedKey(VIEW_MODE_KEY)) as ListViewMode) || 'grid'\n );\n\n const toggleViewMode = useCallback((mode: ListViewMode) => {\n setViewMode(mode);\n localStorage.setItem(getProfileScopedKey(VIEW_MODE_KEY), mode);\n }, []);\n\n // Store state\n const statusFilter = useDataSinkStore((state) => state.statusFilter);\n const activeFilter = useDataSinkStore((state) => state.activeFilter);\n const searchQuery = useDataSinkStore((state) => state.searchQuery);\n const setStatusFilter = useDataSinkStore((state) => state.setStatusFilter);\n const setActiveFilter = useDataSinkStore((state) => state.setActiveFilter);\n const setSearchQuery = useDataSinkStore((state) => state.setSearchQuery);\n const deleteDialogOpen = useDataSinkStore((state) => state.deleteDialogOpen);\n const refreshDialogOpen = useDataSinkStore((state) => state.refreshDialogOpen);\n const currentDataSink = useDataSinkStore((state) => state.currentDataSink);\n const openDeleteDialog = useDataSinkStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = useDataSinkStore((state) => state.closeDeleteDialog);\n const openRefreshDialog = useDataSinkStore((state) => state.openRefreshDialog);\n const closeRefreshDialog = useDataSinkStore((state) => state.closeRefreshDialog);\n\n // Data operations\n const { loading, error, dataSinks, deleteDataSink, refreshDataSink, refetch } = useDataSinkOperations();\n\n // Export hook\n const { downloadDataSink } = useExportDataSink();\n\n // Compute filtered DataSinks with setup states\n const dataSinksWithSetupState = useMemo(() => {\n return dataSinks.map((ds) => ({\n dataSink: ds,\n setupState: getSetupState(ds),\n }));\n }, [dataSinks]);\n\n // Compute filtered DataSinks\n const filteredDataSinks = useMemo(() => {\n let filtered = [...dataSinksWithSetupState];\n\n if (setupStateFilter === 'in_progress') {\n filtered = filtered.filter((item) => item.setupState !== 'completed');\n } else if (setupStateFilter === 'completed') {\n filtered = filtered.filter((item) => item.setupState === 'completed');\n }\n\n if (statusFilter !== null) {\n filtered = filtered.filter((item) => item.dataSink.status === statusFilter);\n }\n\n if (activeFilter !== null) {\n filtered = filtered.filter((item) => item.dataSink.isActive === activeFilter);\n }\n\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (item) =>\n item.dataSink.name?.toLowerCase().includes(query) ||\n item.dataSink.key.toLowerCase().includes(query) ||\n item.dataSink.description?.toLowerCase().includes(query)\n );\n }\n\n return filtered.sort((a, b) => new Date(b.dataSink.updatedAt).getTime() - new Date(a.dataSink.updatedAt).getTime());\n }, [dataSinksWithSetupState, setupStateFilter, statusFilter, activeFilter, searchQuery]);\n\n // Handlers\n const handleCreateDataSink = useCallback(() => {\n navigate('/datasinks/new');\n }, [navigate]);\n\n const handleViewDataSink = useCallback(\n (id: string) => {\n navigate(`/datasinks/${id}`);\n },\n [navigate]\n );\n\n const handleEditDataSink = useCallback(\n (id: string) => {\n navigate(`/datasinks/${id}/edit`);\n },\n [navigate]\n );\n\n const handleRefreshClick = useCallback(\n (id: string) => {\n const dataSink = dataSinks.find((ds) => ds.id === id);\n if (dataSink) {\n openRefreshDialog(dataSink);\n }\n },\n [dataSinks, openRefreshDialog]\n );\n\n const handleRefreshConfirm = useCallback(\n async (forceRefresh: boolean) => {\n if (currentDataSink) {\n await refreshDataSink({\n id: currentDataSink.id,\n forceRefresh,\n });\n closeRefreshDialog();\n }\n },\n [currentDataSink, refreshDataSink, closeRefreshDialog]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const dataSink = dataSinks.find((ds) => ds.id === id);\n if (dataSink) {\n openDeleteDialog(dataSink);\n }\n },\n [dataSinks, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentDataSink) {\n try {\n await deleteDataSink(currentDataSink.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentDataSink, deleteDataSink, closeDeleteDialog]);\n\n const handleExportDataSink = useCallback(\n async (id: string) => {\n const dataSink = dataSinks.find((ds) => ds.id === id);\n if (dataSink) {\n await downloadDataSink(id, dataSink.name || dataSink.key);\n }\n },\n [dataSinks, downloadDataSink]\n );\n\n const handleImportDataSink = useCallback(() => {\n setIsImportDialogOpen(true);\n }, []);\n\n const handleImportSuccess = useCallback(\n (_dataSinkId: string, _dataSinkName: string | null, _wasUpdate: boolean) => {\n // Refetch DataSinks to show the newly imported one\n refetch();\n },\n [refetch]\n );\n\n const hasActiveFilters = useMemo(() => {\n return setupStateFilter !== 'all' || statusFilter !== null || activeFilter !== null || searchQuery.trim() !== '';\n }, [setupStateFilter, statusFilter, activeFilter, searchQuery]);\n\n const handleClearFilters = useCallback(() => {\n setSetupStateFilter('all');\n setStatusFilter(null);\n setActiveFilter(null);\n setSearchQuery('');\n }, [setStatusFilter, setActiveFilter, setSearchQuery]);\n\n // Setup state filter options\n const setupStateOptions: { value: SetupStateFilter; label: string }[] = [\n { value: 'all', label: tr('bigconsole.dataSinks.filters.setupState.all', 'All') },\n { value: 'in_progress', label: tr('bigconsole.dataSinks.filters.setupState.inProgress', 'In Progress') },\n { value: 'completed', label: tr('bigconsole.dataSinks.filters.setupState.completed', 'Completed') },\n ];\n\n // Read gate — once permissions have loaded, block actors without read access.\n if (!permissionsLoading && !canRead) {\n return (\n <AccessDenied\n title={tr('bigconsole.dataSinks.accessDenied.title', 'Access Denied')}\n description={tr(\n 'bigconsole.dataSinks.accessDenied.description',\n \"You don't have permission to view data sinks.\"\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 {tr('bigconsole.dataSinks.error.title', 'Failed to load Data Sinks')}\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 {tr('bigconsole.dataSinks.error.retry', '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\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 'var(--space-formGap)',\n flexWrap: 'wrap',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-formGap)',\n flex: '1 1 280px',\n minWidth: 0,\n }}\n >\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 <Container\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 style={{ minWidth: 0 }}>\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>{tr('bigconsole.dataSinks.title', 'Data Sinks')}</GradientText>\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n {tr('bigconsole.dataSinks.subtitle', 'Manage pre-processed data from FluidGrids workflows')}\n </p>\n </div>\n </div>\n\n {/* Create + Import both require DATASINK_CREATE; omit them entirely when not permitted. */}\n <CTAOverflowMenu\n primary={\n canCreate\n ? {\n label: tr('bigconsole.dataSinks.actions.create', 'Create Data Sink'),\n onSelect: handleCreateDataSink,\n icon: (\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n ),\n }\n : undefined\n }\n actions={\n canCreate\n ? [\n {\n label: tr('bigconsole.dataSinks.actions.import', 'Import'),\n onSelect: handleImportDataSink,\n icon: <Upload style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />,\n },\n ]\n : []\n }\n />\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 Data sinks are the structured destinations that hold your processed data — define a schema once and every\n pipeline, parser, and workflow can write into it. Dashboards then query sinks directly, so a sink is where\n your data lives and where your charts read from.\n </PagePurpose>\n\n {/* Setup State 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 {setupStateOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => setSetupStateFilter(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: setupStateFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color:\n setupStateFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: setupStateFilter === 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 and Filters Row */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginBottom: 'var(--space-sectionGap)',\n flexWrap: 'wrap',\n }}\n >\n {/* Search Bar */}\n <div style={{ position: 'relative', maxWidth: '400px', minWidth: 'min(100%, 240px)', flex: '1 1 240px' }}>\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={tr('bigconsole.dataSinks.search.placeholder', 'Search data sinks...')}\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\n {/* Status Filter */}\n <Select\n value={statusFilter || 'all'}\n onValueChange={(value) =>\n setStatusFilter(value === 'all' ? null : (value as 'ready' | 'error' | 'stale' | 'refreshing'))\n }\n >\n <SelectTrigger style={{ width: 'min(100%, 150px)' }}>\n <SelectValue placeholder={tr('bigconsole.dataSinks.filters.status.placeholder', 'All Statuses')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">{tr('bigconsole.dataSinks.filters.status.all', 'All Statuses')}</SelectItem>\n <SelectItem value=\"ready\">{tr('bigconsole.dataSinks.filters.status.ready', 'Ready')}</SelectItem>\n <SelectItem value=\"error\">{tr('bigconsole.dataSinks.filters.status.error', 'Error')}</SelectItem>\n <SelectItem value=\"stale\">{tr('bigconsole.dataSinks.filters.status.stale', 'Stale')}</SelectItem>\n <SelectItem value=\"refreshing\">\n {tr('bigconsole.dataSinks.filters.status.refreshing', 'Refreshing')}\n </SelectItem>\n </SelectContent>\n </Select>\n\n {/* Active Filter */}\n <Select\n value={activeFilter === null ? 'all' : activeFilter ? 'true' : 'false'}\n onValueChange={(value) => setActiveFilter(value === 'all' ? null : value === 'true')}\n >\n <SelectTrigger style={{ width: 'min(100%, 130px)' }}>\n <SelectValue placeholder={tr('bigconsole.dataSinks.filters.active.placeholder', 'All')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">{tr('bigconsole.dataSinks.filters.active.all', 'All')}</SelectItem>\n <SelectItem value=\"true\">{tr('bigconsole.dataSinks.filters.active.active', 'Active')}</SelectItem>\n <SelectItem value=\"false\">{tr('bigconsole.dataSinks.filters.active.inactive', 'Inactive')}</SelectItem>\n </SelectContent>\n </Select>\n\n {/* Clear Filters */}\n {hasActiveFilters && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handleClearFilters}>\n <X\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dataSinks.filters.clear', 'Clear Filters')}\n </Button>\n )}\n\n {/* Results Count + View Toggle */}\n <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <Badge variant=\"secondary\">\n {filteredDataSinks.length}{' '}\n {filteredDataSinks.length === 1\n ? tr('bigconsole.dataSinks.count.single', 'Data Sink')\n : tr('bigconsole.dataSinks.count.plural', 'Data Sinks')}\n </Badge>\n <div\n style={{\n display: 'flex',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-border)',\n overflow: 'hidden',\n }}\n >\n <button\n type=\"button\"\n onClick={() => toggleViewMode('grid')}\n title={tr('bigconsole.dataSinks.view.grid', 'Grid view')}\n style={{\n padding: '6px 8px',\n border: 'none',\n cursor: 'pointer',\n backgroundColor: viewMode === 'grid' ? 'var(--color-bg-sunken)' : 'transparent',\n color: viewMode === 'grid' ? 'var(--color-text-primary)' : 'var(--color-text-muted)',\n }}\n >\n <LayoutGrid size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => toggleViewMode('table')}\n title={tr('bigconsole.dataSinks.view.table', 'Table view')}\n style={{\n padding: '6px 8px',\n border: 'none',\n borderLeft: '1px solid var(--color-border)',\n cursor: 'pointer',\n backgroundColor: viewMode === 'table' ? 'var(--color-bg-sunken)' : 'transparent',\n color: viewMode === 'table' ? 'var(--color-text-primary)' : 'var(--color-text-muted)',\n }}\n >\n <Table2 size={16} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Loading state */}\n {loading && dataSinks.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 {tr('bigconsole.dataSinks.loading', 'Loading data sinks...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && dataSinks.length === 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tr('bigconsole.dataSinks.empty.title', 'No Data Sinks yet')}\n description={tr(\n 'bigconsole.dataSinks.empty.description',\n 'Data Sinks store pre-processed data from FluidGrids workflows for fast access in widgets.'\n )}\n action={\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.DATASINK_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreateDataSink}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dataSinks.actions.create', 'Create Data Sink')}\n </Button>\n </PermissionButton>\n }\n />\n </GlassCard>\n )}\n\n {/* No results state */}\n {!loading && filteredDataSinks.length === 0 && dataSinks.length > 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title={tr('bigconsole.dataSinks.empty.filteredTitle', 'No matching data sinks')}\n description={tr('bigconsole.dataSinks.empty.filtered', 'No data sinks match your filters')}\n action={\n <Button variant=\"ghost\" size=\"sm\" onClick={handleClearFilters}>\n {tr('bigconsole.dataSinks.filters.clear', 'Clear Filters')}\n </Button>\n }\n />\n </GlassCard>\n )}\n\n {/* DataSink Grid / Table */}\n {filteredDataSinks.length > 0 && viewMode === 'grid' && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, 320px), 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredDataSinks.map((item) => (\n <DataSinkCard\n key={item.dataSink.id}\n dataSink={item.dataSink}\n setupState={item.setupState}\n onView={handleViewDataSink}\n onEdit={handleEditDataSink}\n onRefresh={handleRefreshClick}\n onExport={handleExportDataSink}\n onDelete={handleDeleteClick}\n canEdit={canUpdate}\n canRefresh={canExecute}\n canDelete={canDelete}\n />\n ))}\n </div>\n )}\n\n {/* Table View */}\n {filteredDataSinks.length > 0 && viewMode === 'table' && (\n <div\n style={{\n border: '1px solid var(--color-border)',\n borderRadius: 'var(--radius-card)',\n overflow: 'hidden',\n }}\n >\n <div style={{ overflowX: 'auto' }}>\n <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 'var(--font-size-body-sm)' }}>\n <thead>\n <tr\n style={{\n backgroundColor: 'var(--color-bg-sunken)',\n borderBottom: '1px solid var(--color-border)',\n }}\n >\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.name', 'Name')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.key', 'Key')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.status', 'Status')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.setup', 'Setup')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'center',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.active', 'Active')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.version', 'Version')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.updated', 'Updated')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'right',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {filteredDataSinks.map((item) => {\n const ds = item.dataSink;\n return (\n <tr\n key={ds.id}\n onClick={() => handleViewDataSink(ds.id)}\n style={{\n borderBottom: '1px solid var(--color-border)',\n cursor: 'pointer',\n transition: 'background-color 0.15s',\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--color-bg-sunken)';\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLElement).style.backgroundColor = 'transparent';\n }}\n >\n <td\n style={{\n padding: '10px 12px',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-primary)',\n maxWidth: 200,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {ds.name || ds.key}\n </td>\n <td\n style={{\n padding: '10px 12px',\n color: 'var(--color-text-muted)',\n fontFamily: 'monospace',\n fontSize: '12px',\n maxWidth: 160,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {ds.key}\n </td>\n <td style={{ padding: '10px 12px' }}>\n <DataSinkStatusBadge status={ds.status} />\n </td>\n <td style={{ padding: '10px 12px' }}>\n <SetupStateBadge state={item.setupState} />\n </td>\n <td style={{ padding: '10px 12px', textAlign: 'center' }}>\n <span\n style={{\n display: 'inline-block',\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: ds.isActive ? '#22c55e' : 'var(--color-text-muted)',\n }}\n title={\n ds.isActive\n ? tr('bigconsole.dataSinks.badges.active', 'Active')\n : tr('bigconsole.dataSinks.badges.inactive', 'Inactive')\n }\n />\n </td>\n <td style={{ padding: '10px 12px', color: 'var(--color-text-muted)' }}>v{ds.version ?? 0}</td>\n <td style={{ padding: '10px 12px', color: 'var(--color-text-muted)', whiteSpace: 'nowrap' }}>\n {new Date(ds.updatedAt).toLocaleDateString()}\n </td>\n <td style={{ padding: '10px 12px', textAlign: 'right' }}>\n <div\n style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.view', 'View')}\n onClick={() => handleViewDataSink(ds.id)}\n style={{\n padding: 4,\n border: 'none',\n background: 'none',\n cursor: 'pointer',\n color: 'var(--color-text-muted)',\n borderRadius: 4,\n }}\n >\n <Eye size={14} />\n </button>\n {canUpdate && (\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.edit', 'Edit')}\n onClick={() => handleEditDataSink(ds.id)}\n style={{\n padding: 4,\n border: 'none',\n background: 'none',\n cursor: 'pointer',\n color: 'var(--color-text-muted)',\n borderRadius: 4,\n }}\n >\n <Pencil size={14} />\n </button>\n )}\n {canExecute && (\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.refresh', 'Refresh')}\n onClick={() => handleRefreshClick(ds.id)}\n style={{\n padding: 4,\n border: 'none',\n background: 'none',\n cursor: 'pointer',\n color: 'var(--color-text-muted)',\n borderRadius: 4,\n }}\n >\n <RefreshCw size={14} />\n </button>\n )}\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.export', 'Export')}\n onClick={() => handleExportDataSink(ds.id)}\n style={{\n padding: 4,\n border: 'none',\n background: 'none',\n cursor: 'pointer',\n color: 'var(--color-text-muted)',\n borderRadius: 4,\n }}\n >\n <Download size={14} />\n </button>\n {canDelete && (\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.delete', 'Delete')}\n onClick={() => handleDeleteClick(ds.id)}\n style={{\n padding: 4,\n border: 'none',\n background: 'none',\n cursor: 'pointer',\n color: 'var(--color-text-muted)',\n borderRadius: 4,\n }}\n >\n <Trash2 size={14} />\n </button>\n )}\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </div>\n\n {/* Dialogs */}\n {currentDataSink && (\n <>\n <DataSinkDeleteDialog\n dataSink={currentDataSink}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n\n <DataSinkRefreshDialog\n dataSink={currentDataSink}\n isOpen={refreshDialogOpen}\n onClose={closeRefreshDialog}\n onConfirm={handleRefreshConfirm}\n />\n </>\n )}\n\n {/* Import DataSink Dialog */}\n <ImportDataSinkDialog\n isOpen={isImportDialogOpen}\n onClose={() => setIsImportDialogOpen(false)}\n onSuccess={handleImportSuccess}\n />\n </div>\n );\n});\n\nexport default DataSinksPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"DataSinksPage.js","names":[],"sources":["../../../src/bigconsole/pages/DataSinksPage.tsx"],"sourcesContent":["/**\n * DataSinksPage\n *\n * List and manage DataSinks - fetches data from backend.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { type FC, memo, useCallback, useMemo, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { getProfileScopedKey } from '@burdenoff/fe-libs/shared/utils';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { useDataSinkOperations } from '../hooks/useDataSinkOperations';\nimport { useExportDataSink } from '../hooks/useExportDataSink';\nimport { useDataSinkStore } from '../store/dataSinkStore';\nimport type { DataSink, DataSinkSetupState } from '../types';\nimport { DataSinkCard } from '../components/datasink/DataSinkCard';\nimport { DataSinkDeleteDialog } from '../components/datasink/DataSinkDeleteDialog';\nimport { DataSinkRefreshDialog } from '../components/datasink/DataSinkRefreshDialog';\nimport { ImportDataSinkDialog } from '../components/datasink/ImportDataSinkDialog';\n\n// fe-libs components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@burdenoff/fe-libs/ui';\nimport { Badge } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport {\n AuroraBackground,\n GradientText,\n IllustratedEmptyState,\n CTAOverflowMenu,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\n\n// Section-emphasis primitives (BOFF-5632)\nimport { Section, SectionStack, SECTION_FOCUS_RING } from '../components/common';\n\n// Lucide icons\nimport {\n Plus,\n Search,\n AlertCircle,\n Container,\n X,\n Upload,\n LayoutGrid,\n Table2,\n Eye,\n Pencil,\n RefreshCw,\n Download,\n Trash2,\n} from 'lucide-react';\nimport { DataSinkStatusBadge } from '../components/datasink/DataSinkStatusBadge';\nimport { SetupStateBadge } from '../components/datasink/SetupStateBadge';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype SetupStateFilter = 'all' | 'in_progress' | 'completed';\ntype ListViewMode = 'grid' | 'table';\n\nconst VIEW_MODE_KEY = 'bigconsole-datasinks-view-mode';\n\n/**\n * Row-action buttons in the table view. `--size-controlHeight-md` (40px) replaces the\n * previous `padding: 4` around a 14px icon, which was a ~22px hit target — far\n * under the touch minimum on the one layout that is already a side-scroll.\n */\nconst TABLE_ICON_BUTTON =\n `inline-flex h-control-md w-[var(--size-controlHeight-md)] items-center justify-center rounded-button border-0 bg-transparent text-text-muted hover:bg-bg-surface hover:text-text-primary motion-safe:transition-colors ${SECTION_FOCUS_RING}` as const;\n\n/**\n * Segmented controls clip their children (`overflow: hidden` keeps the group's\n * rounded corners), which would swallow an offset focus ring entirely — leaving\n * the buttons with no visible focus at all, since `SECTION_FOCUS_RING` also\n * suppresses the native outline. Painting the ring inside the button keeps it\n * visible without dropping the group's rounding.\n */\nconst SEGMENT_RING_FIX = 'focus-visible:ring-inset focus-visible:ring-offset-0' as const;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Determine setup state for a DataSink based on its properties.\n */\nconst getSetupState = (dataSink: DataSink): DataSinkSetupState => {\n if (dataSink.setupState === 'completed') {\n return 'completed';\n }\n if (dataSink.ttl !== null && dataSink.ttl !== undefined && dataSink.ttl > 0) {\n return 'completed';\n }\n if (dataSink.fluidGridsWorkflowId && dataSink.data && Object.keys(dataSink.data).length > 0) {\n return 'completed';\n }\n if (dataSink.fluidGridsWorkflowId) {\n return 'workflow_running';\n }\n return 'workflow_pending';\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DataSinksPage: FC = memo(function DataSinksPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string) => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n },\n [t]\n );\n\n // Permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_READ);\n const canCreate = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_CREATE);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_DELETE);\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.DATASINK_EXECUTE);\n\n // Local state\n const [setupStateFilter, setSetupStateFilter] = useState<SetupStateFilter>('all');\n const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);\n const [viewMode, setViewMode] = useState<ListViewMode>(\n () => (localStorage.getItem(getProfileScopedKey(VIEW_MODE_KEY)) as ListViewMode) || 'grid'\n );\n\n const toggleViewMode = useCallback((mode: ListViewMode) => {\n setViewMode(mode);\n localStorage.setItem(getProfileScopedKey(VIEW_MODE_KEY), mode);\n }, []);\n\n // Store state\n const statusFilter = useDataSinkStore((state) => state.statusFilter);\n const activeFilter = useDataSinkStore((state) => state.activeFilter);\n const searchQuery = useDataSinkStore((state) => state.searchQuery);\n const setStatusFilter = useDataSinkStore((state) => state.setStatusFilter);\n const setActiveFilter = useDataSinkStore((state) => state.setActiveFilter);\n const setSearchQuery = useDataSinkStore((state) => state.setSearchQuery);\n const deleteDialogOpen = useDataSinkStore((state) => state.deleteDialogOpen);\n const refreshDialogOpen = useDataSinkStore((state) => state.refreshDialogOpen);\n const currentDataSink = useDataSinkStore((state) => state.currentDataSink);\n const openDeleteDialog = useDataSinkStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = useDataSinkStore((state) => state.closeDeleteDialog);\n const openRefreshDialog = useDataSinkStore((state) => state.openRefreshDialog);\n const closeRefreshDialog = useDataSinkStore((state) => state.closeRefreshDialog);\n\n // Data operations\n const { loading, error, dataSinks, deleteDataSink, refreshDataSink, refetch } = useDataSinkOperations();\n\n // Export hook\n const { downloadDataSink } = useExportDataSink();\n\n // Compute filtered DataSinks with setup states\n const dataSinksWithSetupState = useMemo(() => {\n return dataSinks.map((ds) => ({\n dataSink: ds,\n setupState: getSetupState(ds),\n }));\n }, [dataSinks]);\n\n // Compute filtered DataSinks\n const filteredDataSinks = useMemo(() => {\n let filtered = [...dataSinksWithSetupState];\n\n if (setupStateFilter === 'in_progress') {\n filtered = filtered.filter((item) => item.setupState !== 'completed');\n } else if (setupStateFilter === 'completed') {\n filtered = filtered.filter((item) => item.setupState === 'completed');\n }\n\n if (statusFilter !== null) {\n filtered = filtered.filter((item) => item.dataSink.status === statusFilter);\n }\n\n if (activeFilter !== null) {\n filtered = filtered.filter((item) => item.dataSink.isActive === activeFilter);\n }\n\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (item) =>\n item.dataSink.name?.toLowerCase().includes(query) ||\n item.dataSink.key.toLowerCase().includes(query) ||\n item.dataSink.description?.toLowerCase().includes(query)\n );\n }\n\n return filtered.sort((a, b) => new Date(b.dataSink.updatedAt).getTime() - new Date(a.dataSink.updatedAt).getTime());\n }, [dataSinksWithSetupState, setupStateFilter, statusFilter, activeFilter, searchQuery]);\n\n // Handlers\n const handleCreateDataSink = useCallback(() => {\n navigate('/datasinks/new');\n }, [navigate]);\n\n const handleViewDataSink = useCallback(\n (id: string) => {\n navigate(`/datasinks/${id}`);\n },\n [navigate]\n );\n\n const handleEditDataSink = useCallback(\n (id: string) => {\n navigate(`/datasinks/${id}/edit`);\n },\n [navigate]\n );\n\n const handleRefreshClick = useCallback(\n (id: string) => {\n const dataSink = dataSinks.find((ds) => ds.id === id);\n if (dataSink) {\n openRefreshDialog(dataSink);\n }\n },\n [dataSinks, openRefreshDialog]\n );\n\n const handleRefreshConfirm = useCallback(\n async (forceRefresh: boolean) => {\n if (currentDataSink) {\n await refreshDataSink({\n id: currentDataSink.id,\n forceRefresh,\n });\n closeRefreshDialog();\n }\n },\n [currentDataSink, refreshDataSink, closeRefreshDialog]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const dataSink = dataSinks.find((ds) => ds.id === id);\n if (dataSink) {\n openDeleteDialog(dataSink);\n }\n },\n [dataSinks, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentDataSink) {\n try {\n await deleteDataSink(currentDataSink.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentDataSink, deleteDataSink, closeDeleteDialog]);\n\n const handleExportDataSink = useCallback(\n async (id: string) => {\n const dataSink = dataSinks.find((ds) => ds.id === id);\n if (dataSink) {\n await downloadDataSink(id, dataSink.name || dataSink.key);\n }\n },\n [dataSinks, downloadDataSink]\n );\n\n const handleImportDataSink = useCallback(() => {\n setIsImportDialogOpen(true);\n }, []);\n\n const handleImportSuccess = useCallback(\n (_dataSinkId: string, _dataSinkName: string | null, _wasUpdate: boolean) => {\n // Refetch DataSinks to show the newly imported one\n refetch();\n },\n [refetch]\n );\n\n const hasActiveFilters = useMemo(() => {\n return setupStateFilter !== 'all' || statusFilter !== null || activeFilter !== null || searchQuery.trim() !== '';\n }, [setupStateFilter, statusFilter, activeFilter, searchQuery]);\n\n const handleClearFilters = useCallback(() => {\n setSetupStateFilter('all');\n setStatusFilter(null);\n setActiveFilter(null);\n setSearchQuery('');\n }, [setStatusFilter, setActiveFilter, setSearchQuery]);\n\n // Setup state filter options\n const setupStateOptions: { value: SetupStateFilter; label: string }[] = [\n { value: 'all', label: tr('bigconsole.dataSinks.filters.setupState.all', 'All') },\n { value: 'in_progress', label: tr('bigconsole.dataSinks.filters.setupState.inProgress', 'In Progress') },\n { value: 'completed', label: tr('bigconsole.dataSinks.filters.setupState.completed', 'Completed') },\n ];\n\n // Read gate — once permissions have loaded, block actors without read access.\n if (!permissionsLoading && !canRead) {\n return (\n <AccessDenied\n title={tr('bigconsole.dataSinks.accessDenied.title', 'Access Denied')}\n description={tr(\n 'bigconsole.dataSinks.accessDenied.description',\n \"You don't have permission to view data sinks.\"\n )}\n />\n );\n }\n\n // The fetch-failure state is rendered inline below (inside the page body), so\n // the header band and page purpose survive an error instead of the whole\n // route collapsing into a standalone error card.\n return (\n // No `minHeight: 100vh`: the app shell already pads this content area, so a\n // full-viewport child guaranteed ~16-24px of vertical overflow everywhere.\n <div className=\"min-w-0\" style={{ backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Page header strip. `border-border-seam` / `bg-gloss-card` are not\n registered utilities in this shell — they emitted no CSS at all, so\n this band previously rendered with neither seam nor gloss. */}\n <header className=\"relative overflow-hidden border-b border-[var(--color-border-seam)] bg-[image:var(--gradient-gloss-card)]\">\n <AuroraBackground intensity=\"subtle\" />\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 'var(--space-formGap)',\n flexWrap: 'wrap',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-formGap)',\n flex: '1 1 280px',\n minWidth: 0,\n }}\n >\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 <Container\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 style={{ minWidth: 0 }}>\n {/* text-2xl matches the builder and detail page titles — those\n used `text-heading-h1`, which emits no CSS in this shell. */}\n <h1 className=\"m-0 text-2xl font-bold text-text-primary\">\n <GradientText>{tr('bigconsole.dataSinks.title', 'Data Sinks')}</GradientText>\n </h1>\n <p className=\"m-0 text-sm text-text-secondary\">\n {tr('bigconsole.dataSinks.subtitle', 'Manage pre-processed data from FluidGrids workflows')}\n </p>\n </div>\n </div>\n\n {/* Create + Import both require DATASINK_CREATE; omit them entirely when not permitted. */}\n <CTAOverflowMenu\n primary={\n canCreate\n ? {\n label: tr('bigconsole.dataSinks.actions.create', 'Create Data Sink'),\n onSelect: handleCreateDataSink,\n icon: (\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n ),\n }\n : undefined\n }\n actions={\n canCreate\n ? [\n {\n label: tr('bigconsole.dataSinks.actions.import', 'Import'),\n onSelect: handleImportDataSink,\n icon: <Upload style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />,\n },\n ]\n : []\n }\n />\n </div>\n </div>\n </header>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <PagePurpose className=\"mb-[var(--space-sectionGap)]\">\n Data sinks are the structured destinations that hold your processed data — define a schema once and every\n pipeline, parser, and workflow can write into it. Dashboards then query sinks directly, so a sink is where\n your data lives and where your charts read from.\n </PagePurpose>\n\n <SectionStack>\n {error ? (\n /* The header band and page purpose stay on screen, so a fetch\n failure no longer costs the user all page identity. */\n <Section\n tone=\"danger\"\n headingLevel={2}\n title={tr('bigconsole.dataSinks.error.title', 'Failed to load Data Sinks')}\n description={error.message}\n icon={<AlertCircle className=\"h-icon-sm w-icon-sm\" />}\n actions={\n <Button size=\"sm\" onClick={() => refetch()}>\n {tr('bigconsole.dataSinks.error.retry', 'Try Again')}\n </Button>\n }\n />\n ) : (\n <>\n {/* Both filter affordances now live in one labelled block, so it\n is obvious that the tab strip and the search row compose. */}\n <Section\n headingLevel={2}\n padding=\"compact\"\n title={tr('bigconsole.dataSinks.filters.heading', 'Filters')}\n description={tr(\n 'bigconsole.dataSinks.filters.description',\n 'Narrow the list by setup progress, status, or name.'\n )}\n bodyClassName=\"space-y-form-gap\"\n >\n <>\n {/* Setup State Filter Tabs */}\n <div\n role=\"group\"\n aria-label={tr('bigconsole.dataSinks.filters.setupState.label', 'Setup state')}\n style={{\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: '2px',\n padding: '4px',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-card)',\n maxWidth: '100%',\n width: 'fit-content',\n }}\n >\n {setupStateOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n aria-pressed={setupStateFilter === option.value}\n onClick={() => setSetupStateFilter(option.value)}\n className={SECTION_FOCUS_RING}\n style={{\n minHeight: 'var(--size-controlHeight-md)',\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 backgroundColor:\n setupStateFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color:\n setupStateFilter === option.value\n ? 'var(--color-text-primary)'\n : 'var(--color-text-secondary)',\n // Was a raw `rgba(0,0,0,0.05)` literal.\n boxShadow: setupStateFilter === option.value ? 'var(--shadow-elevation-1)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n\n {/* Search and Filters Row */}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n flexWrap: 'wrap',\n }}\n >\n {/* Search Bar */}\n <div\n style={{\n position: 'relative',\n maxWidth: '400px',\n minWidth: 'min(100%, 240px)',\n flex: '1 1 240px',\n }}\n >\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={tr('bigconsole.dataSinks.search.placeholder', 'Search data sinks...')}\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\n {/* Status Filter */}\n <Select\n value={statusFilter || 'all'}\n onValueChange={(value) =>\n setStatusFilter(value === 'all' ? null : (value as 'ready' | 'error' | 'stale' | 'refreshing'))\n }\n >\n <SelectTrigger style={{ width: 'min(100%, 150px)' }}>\n <SelectValue\n placeholder={tr('bigconsole.dataSinks.filters.status.placeholder', 'All Statuses')}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">\n {tr('bigconsole.dataSinks.filters.status.all', 'All Statuses')}\n </SelectItem>\n <SelectItem value=\"ready\">\n {tr('bigconsole.dataSinks.filters.status.ready', 'Ready')}\n </SelectItem>\n <SelectItem value=\"error\">\n {tr('bigconsole.dataSinks.filters.status.error', 'Error')}\n </SelectItem>\n <SelectItem value=\"stale\">\n {tr('bigconsole.dataSinks.filters.status.stale', 'Stale')}\n </SelectItem>\n <SelectItem value=\"refreshing\">\n {tr('bigconsole.dataSinks.filters.status.refreshing', 'Refreshing')}\n </SelectItem>\n </SelectContent>\n </Select>\n\n {/* Active Filter */}\n <Select\n value={activeFilter === null ? 'all' : activeFilter ? 'true' : 'false'}\n onValueChange={(value) => setActiveFilter(value === 'all' ? null : value === 'true')}\n >\n <SelectTrigger style={{ width: 'min(100%, 130px)' }}>\n <SelectValue placeholder={tr('bigconsole.dataSinks.filters.active.placeholder', 'All')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">{tr('bigconsole.dataSinks.filters.active.all', 'All')}</SelectItem>\n <SelectItem value=\"true\">\n {tr('bigconsole.dataSinks.filters.active.active', 'Active')}\n </SelectItem>\n <SelectItem value=\"false\">\n {tr('bigconsole.dataSinks.filters.active.inactive', 'Inactive')}\n </SelectItem>\n </SelectContent>\n </Select>\n\n {/* Clear Filters */}\n {hasActiveFilters && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handleClearFilters}>\n <X\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dataSinks.filters.clear', 'Clear Filters')}\n </Button>\n )}\n </div>\n </>\n </Section>\n\n {/* The point of this route. The result count and the view toggle\n belong to the results, not to the filters — moving them here\n also removes the `margin-left: auto` that jumped to the left\n edge as soon as the filter row wrapped. */}\n <Section\n emphasis=\"primary\"\n headingLevel={2}\n title={tr('bigconsole.dataSinks.list.heading', 'Data sinks')}\n description={tr(\n 'bigconsole.dataSinks.list.description',\n 'Every sink in this workspace, most recently updated first.'\n )}\n meta={\n <Badge variant=\"secondary\">\n {filteredDataSinks.length}{' '}\n {filteredDataSinks.length === 1\n ? tr('bigconsole.dataSinks.count.single', 'Data Sink')\n : tr('bigconsole.dataSinks.count.plural', 'Data Sinks')}\n </Badge>\n }\n actions={\n <div\n role=\"group\"\n aria-label={tr('bigconsole.dataSinks.view.label', 'List layout')}\n style={{\n display: 'flex',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-border)',\n overflow: 'hidden',\n }}\n >\n <button\n type=\"button\"\n onClick={() => toggleViewMode('grid')}\n aria-pressed={viewMode === 'grid'}\n title={tr('bigconsole.dataSinks.view.grid', 'Grid view')}\n className={`flex h-control-md w-[var(--size-controlHeight-md)] items-center justify-center ${SECTION_FOCUS_RING} ${SEGMENT_RING_FIX}`}\n style={{\n border: 'none',\n cursor: 'pointer',\n backgroundColor: viewMode === 'grid' ? 'var(--color-bg-sunken)' : 'transparent',\n color: viewMode === 'grid' ? 'var(--color-text-primary)' : 'var(--color-text-muted)',\n }}\n >\n <LayoutGrid size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => toggleViewMode('table')}\n aria-pressed={viewMode === 'table'}\n title={tr('bigconsole.dataSinks.view.table', 'Table view')}\n className={`flex h-control-md w-[var(--size-controlHeight-md)] items-center justify-center ${SECTION_FOCUS_RING} ${SEGMENT_RING_FIX}`}\n style={{\n border: 'none',\n borderLeft: '1px solid var(--color-border)',\n cursor: 'pointer',\n backgroundColor: viewMode === 'table' ? 'var(--color-bg-sunken)' : 'transparent',\n color: viewMode === 'table' ? 'var(--color-text-primary)' : 'var(--color-text-muted)',\n }}\n >\n <Table2 size={16} />\n </button>\n </div>\n }\n >\n <>\n {/* Loading state */}\n {loading && dataSinks.length === 0 && (\n <div className=\"flex items-center justify-center py-12\">\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 className=\"text-sm text-text-muted\">\n {tr('bigconsole.dataSinks.loading', 'Loading data sinks...')}\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state — no GlassCard: the zero-data state should not\n be more emphasised than the content it replaces. */}\n {!loading && dataSinks.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tr('bigconsole.dataSinks.empty.title', 'No Data Sinks yet')}\n description={tr(\n 'bigconsole.dataSinks.empty.description',\n 'Data Sinks store pre-processed data from FluidGrids workflows for fast access in widgets.'\n )}\n action={\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.DATASINK_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreateDataSink}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n {tr('bigconsole.dataSinks.actions.create', 'Create Data Sink')}\n </Button>\n </PermissionButton>\n }\n />\n )}\n\n {/* No results state — an info tone, so \"you have none\" and\n \"your filter matched none\" are no longer identical. */}\n {!loading && filteredDataSinks.length === 0 && dataSinks.length > 0 && (\n <Section\n tone=\"info\"\n emphasis=\"muted\"\n padding=\"compact\"\n headingLevel={3}\n title={tr('bigconsole.dataSinks.empty.filteredTitle', 'No matching data sinks')}\n description={tr('bigconsole.dataSinks.empty.filtered', 'No data sinks match your filters')}\n actions={\n <Button variant=\"secondary\" size=\"sm\" onClick={handleClearFilters}>\n {tr('bigconsole.dataSinks.filters.clear', 'Clear Filters')}\n </Button>\n }\n />\n )}\n\n {/* DataSink Grid */}\n {filteredDataSinks.length > 0 && viewMode === 'grid' && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, 320px), 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredDataSinks.map((item) => (\n <DataSinkCard\n key={item.dataSink.id}\n dataSink={item.dataSink}\n setupState={item.setupState}\n onView={handleViewDataSink}\n onEdit={handleEditDataSink}\n onRefresh={handleRefreshClick}\n onExport={handleExportDataSink}\n onDelete={handleDeleteClick}\n canEdit={canUpdate}\n canRefresh={canExecute}\n canDelete={canDelete}\n />\n ))}\n </div>\n )}\n\n {/* Table View. The section already draws the boundary, so the\n table no longer nests a second border inside it. */}\n {filteredDataSinks.length > 0 && viewMode === 'table' && (\n <div className=\"min-w-0\" style={{ overflowX: 'auto' }}>\n <table\n style={{ width: '100%', borderCollapse: 'collapse', fontSize: 'var(--font-size-body-sm)' }}\n >\n <thead>\n <tr\n style={{\n backgroundColor: 'var(--color-bg-sunken)',\n borderBottom: '1px solid var(--color-border)',\n }}\n >\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.name', 'Name')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.key', 'Key')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.status', 'Status')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.setup', 'Setup')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'center',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.active', 'Active')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.version', 'Version')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'left',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.updated', 'Updated')}\n </th>\n <th\n style={{\n padding: '10px 12px',\n textAlign: 'right',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-secondary)',\n whiteSpace: 'nowrap',\n }}\n >\n {tr('bigconsole.dataSinks.table.actions', 'Actions')}\n </th>\n </tr>\n </thead>\n <tbody>\n {filteredDataSinks.map((item) => {\n const ds = item.dataSink;\n return (\n <tr\n key={ds.id}\n onClick={() => handleViewDataSink(ds.id)}\n // Hover was JS-driven, so it ignored theme and the OS\n // reduce-motion setting and stuck after a tap on touch.\n className=\"cursor-pointer hover:bg-bg-sunken motion-safe:transition-colors\"\n style={{ borderBottom: '1px solid var(--color-border)' }}\n >\n <td\n style={{\n padding: '10px 12px',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-text-primary)',\n maxWidth: 200,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {ds.name || ds.key}\n </td>\n <td\n style={{\n padding: '10px 12px',\n color: 'var(--color-text-muted)',\n fontFamily: 'monospace',\n fontSize: '12px',\n maxWidth: 160,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {ds.key}\n </td>\n <td style={{ padding: '10px 12px' }}>\n <DataSinkStatusBadge status={ds.status} />\n </td>\n <td style={{ padding: '10px 12px' }}>\n <SetupStateBadge state={item.setupState} />\n </td>\n <td style={{ padding: '10px 12px', textAlign: 'center' }}>\n <span\n style={{\n display: 'inline-block',\n width: 8,\n height: 8,\n borderRadius: '50%',\n // Was a raw `#22c55e` literal.\n backgroundColor: ds.isActive\n ? 'var(--color-status-success-bg)'\n : 'var(--color-text-muted)',\n }}\n title={\n ds.isActive\n ? tr('bigconsole.dataSinks.badges.active', 'Active')\n : tr('bigconsole.dataSinks.badges.inactive', 'Inactive')\n }\n />\n </td>\n <td style={{ padding: '10px 12px', color: 'var(--color-text-muted)' }}>\n v{ds.version ?? 0}\n </td>\n <td\n style={{\n padding: '10px 12px',\n color: 'var(--color-text-muted)',\n whiteSpace: 'nowrap',\n }}\n >\n {new Date(ds.updatedAt).toLocaleDateString()}\n </td>\n <td style={{ padding: '10px 12px', textAlign: 'right' }}>\n <div\n style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.view', 'View')}\n aria-label={tr('bigconsole.dataSinks.actions.view', 'View')}\n onClick={() => handleViewDataSink(ds.id)}\n className={TABLE_ICON_BUTTON}\n >\n <Eye size={14} />\n </button>\n {canUpdate && (\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.edit', 'Edit')}\n aria-label={tr('bigconsole.dataSinks.actions.edit', 'Edit')}\n onClick={() => handleEditDataSink(ds.id)}\n className={TABLE_ICON_BUTTON}\n >\n <Pencil size={14} />\n </button>\n )}\n {canExecute && (\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.refresh', 'Refresh')}\n aria-label={tr('bigconsole.dataSinks.actions.refresh', 'Refresh')}\n onClick={() => handleRefreshClick(ds.id)}\n className={TABLE_ICON_BUTTON}\n >\n <RefreshCw size={14} />\n </button>\n )}\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.export', 'Export')}\n aria-label={tr('bigconsole.dataSinks.actions.export', 'Export')}\n onClick={() => handleExportDataSink(ds.id)}\n className={TABLE_ICON_BUTTON}\n >\n <Download size={14} />\n </button>\n {canDelete && (\n <button\n type=\"button\"\n title={tr('bigconsole.dataSinks.actions.delete', 'Delete')}\n aria-label={tr('bigconsole.dataSinks.actions.delete', 'Delete')}\n onClick={() => handleDeleteClick(ds.id)}\n className={TABLE_ICON_BUTTON}\n >\n <Trash2 size={14} />\n </button>\n )}\n </div>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n )}\n </>\n </Section>\n </>\n )}\n </SectionStack>\n </div>\n\n {/* Dialogs */}\n {currentDataSink && (\n <>\n <DataSinkDeleteDialog\n dataSink={currentDataSink}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n\n <DataSinkRefreshDialog\n dataSink={currentDataSink}\n isOpen={refreshDialogOpen}\n onClose={closeRefreshDialog}\n onConfirm={handleRefreshConfirm}\n />\n </>\n )}\n\n {/* Import DataSink Dialog */}\n <ImportDataSinkDialog\n isOpen={isImportDialogOpen}\n onClose={() => setIsImportDialogOpen(false)}\n onSuccess={handleImportSuccess}\n />\n </div>\n );\n});\n\nexport default DataSinksPage;\n"],"mappings":"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"}
@@ -1,18 +1,24 @@
1
1
  import { useAppNavigate as e } from "../contexts/NavigationContext.js";
2
2
  import "../contexts/index.js";
3
3
  import { useEffect as t } from "react";
4
- import { jsx as n } from "react/jsx-runtime";
4
+ import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
5
+ import { jsx as r } from "react/jsx-runtime";
5
6
  //#region src/bigconsole/pages/DataSourcesPage.tsx
6
- function r() {
7
- let r = e();
7
+ function i() {
8
+ let i = e(), { t: a } = n();
8
9
  return t(() => {
9
- r("/datasinks", { replace: !0 });
10
- }, []), /* @__PURE__ */ n("div", {
11
- className: "p-card-padding text-text-secondary",
12
- children: "Redirecting to DataSinks..."
10
+ i("/datasinks", { replace: !0 });
11
+ }, []), /* @__PURE__ */ r("div", {
12
+ className: "p-card-padding",
13
+ children: /* @__PURE__ */ r("p", {
14
+ role: "status",
15
+ "aria-live": "polite",
16
+ className: "text-sm text-text-secondary",
17
+ children: a("bigconsole.dataSinks.redirecting", "Redirecting to DataSinks...")
18
+ })
13
19
  });
14
20
  }
15
21
  //#endregion
16
- export { r as DataSourcesPage, r as default };
22
+ export { i as DataSourcesPage, i as default };
17
23
 
18
24
  //# sourceMappingURL=DataSourcesPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataSourcesPage.js","names":[],"sources":["../../../src/bigconsole/pages/DataSourcesPage.tsx"],"sourcesContent":["/**\n * DataSourcesPage\n *\n * Data Sources were architecturally replaced by DataSinks in the v2.0\n * pipeline refactor (BOFF-1754). This page redirects users to the\n * DataSinks page which is the primary data connection management UI.\n */\n\nimport { useEffect } from 'react';\nimport { useAppNavigate } from '../contexts';\n\nexport function DataSourcesPage() {\n const navigate = useAppNavigate();\n\n useEffect(() => {\n navigate('/datasinks', { replace: true });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Run once on mount - navigate is stable (memoized)\n\n return <div className=\"p-card-padding text-text-secondary\">Redirecting to DataSinks...</div>;\n}\n\nexport default DataSourcesPage;\n"],"mappings":";;;;;AAWA,SAAgB,IAAkB;CAChC,IAAM,IAAW,GAAgB;AAOjC,QALA,QAAgB;AACd,IAAS,cAAc,EAAE,SAAS,IAAM,CAAC;IAExC,EAAE,CAAC,EAEC,kBAAC,OAAD;EAAK,WAAU;YAAqC;EAAiC,CAAA"}
1
+ {"version":3,"file":"DataSourcesPage.js","names":[],"sources":["../../../src/bigconsole/pages/DataSourcesPage.tsx"],"sourcesContent":["/**\n * DataSourcesPage\n *\n * Data Sources were architecturally replaced by DataSinks in the v2.0\n * pipeline refactor (BOFF-1754). This page redirects users to the\n * DataSinks page which is the primary data connection management UI.\n */\n\nimport { useEffect } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useAppNavigate } from '../contexts';\n\nexport function DataSourcesPage() {\n const navigate = useAppNavigate();\n const { t } = useI18n();\n\n useEffect(() => {\n navigate('/datasinks', { replace: true });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []); // Run once on mount - navigate is stable (memoized)\n\n return (\n <div className=\"p-card-padding\">\n <p role=\"status\" aria-live=\"polite\" className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.redirecting', 'Redirecting to DataSinks...')}\n </p>\n </div>\n );\n}\n\nexport default DataSourcesPage;\n"],"mappings":";;;;;;AAYA,SAAgB,IAAkB;CAChC,IAAM,IAAW,GAAgB,EAC3B,EAAE,SAAM,GAAS;AAOvB,QALA,QAAgB;AACd,IAAS,cAAc,EAAE,SAAS,IAAM,CAAC;IAExC,EAAE,CAAC,EAGJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,KAAD;GAAG,MAAK;GAAS,aAAU;GAAS,WAAU;aAC3C,EAAE,oCAAoC,8BAA8B;GACnE,CAAA;EACA,CAAA"}