@burdenoff/microfe-bigconsole 2026.805.2 → 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.
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +109 -113
- package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -1
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +115 -113
- package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +71 -62
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +90 -89
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js +56 -54
- package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js +126 -125
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterChip.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js +151 -150
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterEditor.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js +77 -76
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/FilterPresetSelector.js.map +1 -1
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js +97 -96
- package/dist/bigconsole/components/dashboard/GlobalFiltersBar/GlobalFiltersBar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +172 -191
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +75 -83
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +151 -154
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +181 -190
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
- package/dist/bigconsole/components/dashboard/TemplatePicker/TemplatePicker.js +1 -0
- package/dist/bigconsole/components/dashboard/WidgetPalette.js +110 -108
- package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js +102 -103
- package/dist/bigconsole/components/datasink/CacheTTLSelector.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js +36 -41
- package/dist/bigconsole/components/datasink/DataSinkDeleteDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js +38 -37
- package/dist/bigconsole/components/datasink/DataSinkRefreshDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +113 -117
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +182 -197
- package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js +166 -168
- package/dist/bigconsole/components/datasink/RefreshTypeSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/DataSinkSelector.js +87 -86
- package/dist/bigconsole/components/parser/DataSinkSelector.js.map +1 -1
- package/dist/bigconsole/components/parser/ImportParserDialog.js +196 -211
- package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
- package/dist/bigconsole/components/parser/ParserSelector.js +130 -128
- package/dist/bigconsole/components/parser/ParserSelector.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +66 -63
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +95 -91
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +222 -215
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js +149 -145
- package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/PropertiesPanel.js +504 -470
- package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js +44 -47
- package/dist/bigconsole/components/widgets/calendar/CalendarWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js +143 -142
- package/dist/bigconsole/components/widgets/chart/ChartConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js +101 -88
- package/dist/bigconsole/components/widgets/comments/WidgetComments.js.map +1 -1
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +135 -134
- package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
- package/dist/bigconsole/components/widgets/form/FormWidget.js +167 -159
- package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js +69 -68
- package/dist/bigconsole/components/widgets/gauge/GaugeConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js +64 -72
- package/dist/bigconsole/components/widgets/heatmap/HeatmapConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +60 -59
- package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/list/ListConfig.js +57 -56
- package/dist/bigconsole/components/widgets/list/ListConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js +70 -69
- package/dist/bigconsole/components/widgets/metric-card/MetricCardConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js +35 -34
- package/dist/bigconsole/components/widgets/metric-card/SparklineChart.js.map +1 -1
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js +20 -19
- package/dist/bigconsole/components/widgets/metric-card/TrendIndicator.js.map +1 -1
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js +178 -177
- package/dist/bigconsole/components/widgets/pivot-table/PivotTableWidget.js.map +1 -1
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js +76 -75
- package/dist/bigconsole/components/widgets/progress/ProgressConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableConfig.js +183 -168
- package/dist/bigconsole/components/widgets/table/TableConfig.js.map +1 -1
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +187 -180
- package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js +40 -38
- package/dist/bigconsole/customWidget/CustomWidgetBuilderSheet.js.map +1 -1
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js +150 -148
- package/dist/bigconsole/customWidget/CustomWidgetProposalPanel.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +181 -176
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +196 -192
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +223 -219
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +167 -170
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +204 -189
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +175 -169
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSourcesPage.js +8 -7
- package/dist/bigconsole/pages/DataSourcesPage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +238 -208
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +464 -412
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +92 -90
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +221 -194
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +181 -184
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +128 -127
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/SettingsPage.js +177 -172
- package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
- package/dist/bigconsole/pages/WidgetDemoPage.js +121 -83
- package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +199 -193
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +129 -128
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js +111 -109
- package/dist/bigconsole/renderers/adapters/AdaptiveCardRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js +127 -126
- package/dist/bigconsole/renderers/adapters/BlockKitRenderer.js.map +1 -1
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js +103 -103
- package/dist/bigconsole/renderers/adapters/CustomRenderer.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetPalette.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/WidgetPalette.tsx"],"sourcesContent":["/**\n * WidgetPalette Component\n *\n * Sidebar panel with draggable widget types for the dashboard builder.\n * Uses semantic tokens for consistent theming.\n * Features categorized widgets, search, and drag-and-drop support.\n */\n\nimport { type FC, memo, useState, useCallback, useMemo } from 'react';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport {\n Search,\n ChevronDown,\n ChevronRight,\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n GripVertical,\n X,\n Layers,\n Store,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n getWidgetCategories,\n getWidgetKey,\n WIDGET_CATEGORY_LABELS,\n type WidgetDefinition,\n} from '../widgets/WidgetRegistry';\nimport type { WidgetType, WidgetCategory } from '../../types';\n\n// ============================================================================\n// Icon Mapping\n// ============================================================================\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n};\n\nfunction getIconComponent(iconName: string): LucideIcon {\n return ICON_MAP[iconName] || Puzzle;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetPaletteProps {\n /** Whether the palette is open */\n isOpen: boolean;\n /** Callback to close the palette */\n onClose: () => void;\n /** Callback when a widget is selected (for quick add without drag) */\n onWidgetSelect?: (type: WidgetType, definition?: WidgetDefinition) => void;\n /** Callback when drag starts */\n onDragStart?: (type: WidgetType, definition: WidgetDefinition) => void;\n /** Callback when drag ends */\n onDragEnd?: () => void;\n /** Installed widgets from the store (fetched by parent) */\n installedWidgets?: WidgetDefinition[];\n /** Whether installed widgets are still loading */\n installedWidgetsLoading?: boolean;\n /**\n * Built-in widget catalog (from the backend `getWidgetTypes`, fetched by the\n * parent via useWidgetCatalog). When omitted, falls back to the bundled\n * static registry.\n */\n definitions?: WidgetDefinition[];\n}\n\n// ============================================================================\n// Styles using semantic tokens\n// ============================================================================\n\nconst styles = {\n container: {\n width: '300px',\n height: '100%',\n backgroundColor: 'var(--color-bg-surface)',\n borderRight: '1px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column' as const,\n flexShrink: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n header: {\n padding: 'var(--space-formGap)',\n borderBottom: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n headerTop: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 'var(--space-controlGap)',\n },\n headerTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n },\n headerIcon: {\n width: '32px',\n height: '32px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-action-primary-bg)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n title: {\n fontSize: 'var(--font-size-body-md)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-primary)',\n margin: 0,\n },\n subtitle: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: '2px 0 0 0',\n },\n closeButton: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n border: 'none',\n background: 'transparent',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n color: 'var(--color-text-secondary)',\n transition: 'background-color 0.15s',\n },\n searchContainer: {\n position: 'relative' as const,\n },\n searchIcon: {\n position: 'absolute' as const,\n left: '10px',\n top: '50%',\n transform: 'translateY(-50%)',\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n pointerEvents: 'none' as const,\n },\n searchInput: {\n width: '100%',\n paddingLeft: '36px',\n height: 'var(--size-controlHeight-sm)',\n fontSize: 'var(--font-size-body-sm)',\n },\n content: {\n flex: '1 1 0',\n minHeight: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n scrollArea: {\n position: 'absolute' as const,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n overflowY: 'auto' as const,\n overflowX: 'hidden' as const,\n padding: 'var(--space-controlGap)',\n },\n categoryContainer: {\n marginBottom: 'var(--space-controlGap)',\n },\n categoryHeader: {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-iconGap)',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: 'var(--radius-button)',\n transition: 'background-color 0.15s',\n },\n categoryChevron: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n flexShrink: 0,\n },\n categoryLabel: {\n flex: 1,\n textAlign: 'left' as const,\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-secondary)',\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n },\n categoryCount: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n backgroundColor: 'var(--color-bg-sunken)',\n padding: '2px 8px',\n borderRadius: 'var(--radius-full)',\n },\n widgetList: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '4px',\n marginTop: 'var(--space-controlGap)',\n paddingLeft: '4px',\n },\n widgetCard: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-card)',\n cursor: 'grab',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border)',\n transition: 'all 0.15s ease',\n },\n widgetCardHover: {\n backgroundColor: 'var(--color-bg-hover)',\n borderColor: 'var(--color-action-primary-border)',\n boxShadow: 'var(--shadow-elevation-1)',\n },\n dragHandle: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n opacity: 0.5,\n flexShrink: 0,\n },\n widgetIcon: {\n width: '36px',\n height: '36px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n widgetIconInner: {\n width: '18px',\n height: '18px',\n color: 'var(--color-action-primary-bg)',\n },\n widgetText: {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n },\n widgetName: {\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-text-primary)',\n whiteSpace: 'nowrap' as const,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n marginBottom: '2px',\n },\n widgetDescription: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n lineHeight: 1.3,\n overflow: 'hidden',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical' as const,\n },\n emptyState: {\n textAlign: 'center' as const,\n padding: 'var(--space-pagePadding)',\n },\n emptyIcon: {\n width: '48px',\n height: '48px',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: '0 auto var(--space-formGap)',\n },\n emptyText: {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n margin: 0,\n },\n clearButton: {\n marginTop: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-action-primary-text)',\n backgroundColor: 'var(--color-action-primary-bg)',\n border: 'none',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n },\n footer: {\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n footerText: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: 0,\n textAlign: 'center' as const,\n },\n browseStoreButton: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-iconGap)',\n width: '100%',\n padding: 'var(--space-controlGap)',\n marginBottom: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-button)',\n border: '1px dashed var(--color-border)',\n backgroundColor: 'transparent',\n color: 'var(--color-text-secondary)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n cursor: 'pointer',\n transition: 'border-color 0.15s, color 0.15s',\n },\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WidgetPalette: FC<WidgetPaletteProps> = memo(function WidgetPalette({\n isOpen,\n onClose,\n onWidgetSelect,\n onDragStart,\n onDragEnd,\n installedWidgets = [],\n installedWidgetsLoading = false,\n definitions,\n}) {\n const [searchQuery, setSearchQuery] = useState('');\n const [expandedCategories, setExpandedCategories] = useState<Set<WidgetCategory>>(\n new Set(['KPI', 'Visualization', 'Data', 'Content', 'Temporal', 'Custom', 'Installed'])\n );\n const [hoveredWidget, setHoveredWidget] = useState<string | null>(null);\n\n // Get categorized widgets, merging in installed widgets. When the parent\n // supplies a backend-sourced catalog (`definitions`), group that by category;\n // otherwise fall back to the bundled static registry.\n const categories = useMemo(() => {\n const baseCategories = definitions\n ? (Object.keys(WIDGET_CATEGORY_LABELS) as WidgetCategory[]).map((category) => ({\n category,\n label: WIDGET_CATEGORY_LABELS[category],\n widgets: definitions.filter((def) => def.category === category),\n }))\n : getWidgetCategories();\n\n return baseCategories\n .map((cat) => {\n if (cat.category === 'Installed') {\n // Two sources feed \"Installed from Store\": the registry-driven backend\n // catalog (getWidgetTypes store types — rich metadata, install-gated,\n // BOFF-2858) which arrives via `definitions` under this category, and\n // the legacy workspaceInstalledApps listing passed as `installedWidgets`.\n // Merge both, deduping by name (the catalog entry wins) so a widget\n // present in both sources shows once with the richer definition, while\n // legacy installs not yet in the registry are still preserved.\n const byName = new Map<string, WidgetDefinition>();\n for (const w of installedWidgets) byName.set(w.name.toLowerCase(), w);\n for (const w of cat.widgets) {\n const key = w.name.toLowerCase();\n const legacy = byName.get(key);\n // Catalog wins for metadata but MERGE defaultConfig so the legacy\n // workspaceInstalledApps fields survive — notably `componentId`, which the\n // current render path needs and the catalog store entry lacks until\n // widgetTypeKey rendering is wired. Keeps overlapping store widgets renderable.\n byName.set(key, legacy ? { ...w, defaultConfig: { ...legacy.defaultConfig, ...w.defaultConfig } } : w);\n }\n return { ...cat, widgets: Array.from(byName.values()) };\n }\n return cat;\n })\n .filter((cat) => cat.category !== 'Installed' || cat.widgets.length > 0);\n }, [installedWidgets, definitions]);\n\n // Filter widgets by search query\n const filteredCategories = useMemo(() => {\n if (!searchQuery.trim()) {\n return categories;\n }\n\n const query = searchQuery.toLowerCase();\n return categories\n .map((cat) => ({\n ...cat,\n widgets: cat.widgets.filter(\n (w) =>\n w.name.toLowerCase().includes(query) ||\n w.description.toLowerCase().includes(query) ||\n w.tags.some((tag) => tag.includes(query))\n ),\n }))\n .filter((cat) => cat.widgets.length > 0);\n }, [categories, searchQuery]);\n\n // Toggle category expansion\n const toggleCategory = useCallback((category: WidgetCategory) => {\n setExpandedCategories((prev) => {\n const next = new Set(prev);\n if (next.has(category)) {\n next.delete(category);\n } else {\n next.add(category);\n }\n return next;\n });\n }, []);\n\n // Handle drag start\n const handleDragStart = useCallback(\n (e: React.DragEvent, widget: WidgetDefinition) => {\n e.dataTransfer.setData(\n 'application/json',\n JSON.stringify({\n type: widget.type,\n name: widget.name,\n defaultSize: widget.defaultSize,\n defaultConfig: widget.defaultConfig,\n category: widget.category,\n })\n );\n e.dataTransfer.effectAllowed = 'copy';\n\n // Create custom drag image\n const dragImage = document.createElement('div');\n dragImage.style.cssText = `\n position: absolute;\n top: -1000px;\n left: -1000px;\n padding: 8px 12px;\n background: var(--color-bg-surface);\n border: 2px solid var(--color-action-primary-bg);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--color-text-primary);\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n `;\n dragImage.textContent = widget.name;\n document.body.appendChild(dragImage);\n e.dataTransfer.setDragImage(dragImage, 0, 0);\n\n setTimeout(() => {\n document.body.removeChild(dragImage);\n }, 0);\n\n onDragStart?.(widget.type, widget);\n },\n [onDragStart]\n );\n\n // Handle drag end\n const handleDragEnd = useCallback(() => {\n onDragEnd?.();\n }, [onDragEnd]);\n\n // Handle click to quick-add\n const handleWidgetClick = useCallback(\n (widget: WidgetDefinition) => {\n onWidgetSelect?.(widget.type, widget);\n },\n [onWidgetSelect]\n );\n\n // Open the widget store in a new tab so the builder (and any unsaved edits)\n // stays intact. Preserves the current org/workspace/project query params.\n const handleBrowseStore = useCallback(() => {\n if (typeof window === 'undefined') return;\n const url = `${window.location.origin}/bigconsole/store${window.location.search}`;\n window.open(url, '_blank', 'noopener,noreferrer');\n }, []);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div style={styles.container}>\n {/* Header */}\n <div style={styles.header}>\n <div style={styles.headerTop}>\n <div style={styles.headerTitle}>\n <div style={styles.headerIcon}>\n <Layers style={{ width: '18px', height: '18px', color: 'var(--color-action-primary-text)' }} />\n </div>\n <div>\n <h3 style={styles.title}>Widgets</h3>\n <p style={styles.subtitle}>Drag or click to add</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n style={styles.closeButton}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n <X style={{ width: '16px', height: '16px' }} />\n </button>\n </div>\n\n {/* Search */}\n <div style={styles.searchContainer}>\n <Search style={styles.searchIcon} />\n <Input\n type=\"text\"\n placeholder=\"Search widgets...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={styles.searchInput}\n />\n </div>\n </div>\n\n {/* Widget Categories */}\n <div style={styles.content}>\n <div style={styles.scrollArea}>\n {filteredCategories.map((category) => (\n <div key={category.category} style={styles.categoryContainer}>\n {/* Category Header */}\n <button\n type=\"button\"\n onClick={() => toggleCategory(category.category)}\n style={styles.categoryHeader}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n {expandedCategories.has(category.category) ? (\n <ChevronDown style={styles.categoryChevron} />\n ) : (\n <ChevronRight style={styles.categoryChevron} />\n )}\n <span style={styles.categoryLabel}>{category.label}</span>\n <span style={styles.categoryCount}>{category.widgets.length}</span>\n </button>\n\n {/* Widget Items */}\n {expandedCategories.has(category.category) && (\n <div style={styles.widgetList}>\n {installedWidgetsLoading && category.category === 'Installed' && (\n <div\n style={{\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n padding: 'var(--space-controlGap)',\n }}\n >\n Loading...\n </div>\n )}\n {category.widgets.map((widget) => {\n const IconComponent = getIconComponent(widget.icon);\n const widgetKey = getWidgetKey(widget);\n const isHovered = hoveredWidget === widgetKey;\n\n return (\n <div\n key={widgetKey}\n draggable\n onDragStart={(e) => handleDragStart(e, widget)}\n onDragEnd={handleDragEnd}\n onClick={() => handleWidgetClick(widget)}\n onMouseEnter={() => setHoveredWidget(widgetKey)}\n onMouseLeave={() => setHoveredWidget(null)}\n style={{\n ...styles.widgetCard,\n ...(isHovered ? styles.widgetCardHover : {}),\n }}\n >\n {/* Drag Handle */}\n <GripVertical style={styles.dragHandle} />\n\n {/* Icon */}\n <div style={styles.widgetIcon}>\n <IconComponent style={styles.widgetIconInner} />\n </div>\n\n {/* Text */}\n <div style={styles.widgetText}>\n <div style={styles.widgetName}>{widget.name}</div>\n <div style={styles.widgetDescription}>{widget.description}</div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n ))}\n\n {filteredCategories.length === 0 && (\n <div style={styles.emptyState}>\n <div style={styles.emptyIcon}>\n <Search style={{ width: '24px', height: '24px', color: 'var(--color-text-muted)' }} />\n </div>\n <p style={styles.emptyText}>\n No widgets found for \"<strong>{searchQuery}</strong>\"\n </p>\n <button type=\"button\" onClick={() => setSearchQuery('')} style={styles.clearButton}>\n Clear search\n </button>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <div style={styles.footer}>\n <button\n type=\"button\"\n onClick={handleBrowseStore}\n style={styles.browseStoreButton}\n onMouseOver={(e) => {\n e.currentTarget.style.borderColor = 'var(--color-action-primary-bg)';\n e.currentTarget.style.color = 'var(--color-action-primary-text)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.borderColor = 'var(--color-border)';\n e.currentTarget.style.color = 'var(--color-text-secondary)';\n }}\n >\n <Store style={{ width: '15px', height: '15px' }} />\n Browse widget store\n <ExternalLink style={{ width: '13px', height: '13px', opacity: 0.7 }} />\n </button>\n <p style={styles.footerText}>Drag widgets to position them on the canvas</p>\n </div>\n </div>\n );\n});\n\nexport default WidgetPalette;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetPalette.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/WidgetPalette.tsx"],"sourcesContent":["/**\n * WidgetPalette Component\n *\n * Sidebar panel with draggable widget types for the dashboard builder.\n * Uses semantic tokens for consistent theming.\n * Features categorized widgets, search, and drag-and-drop support.\n */\n\nimport { type FC, memo, useState, useCallback, useMemo } from 'react';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Search,\n ChevronDown,\n ChevronRight,\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n GripVertical,\n X,\n Layers,\n Store,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n getWidgetCategories,\n getWidgetKey,\n WIDGET_CATEGORY_LABELS,\n type WidgetDefinition,\n} from '../widgets/WidgetRegistry';\nimport type { WidgetType, WidgetCategory } from '../../types';\n\n// ============================================================================\n// Icon Mapping\n// ============================================================================\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n};\n\nfunction getIconComponent(iconName: string): LucideIcon {\n return ICON_MAP[iconName] || Puzzle;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetPaletteProps {\n /** Whether the palette is open */\n isOpen: boolean;\n /** Callback to close the palette */\n onClose: () => void;\n /** Callback when a widget is selected (for quick add without drag) */\n onWidgetSelect?: (type: WidgetType, definition?: WidgetDefinition) => void;\n /** Callback when drag starts */\n onDragStart?: (type: WidgetType, definition: WidgetDefinition) => void;\n /** Callback when drag ends */\n onDragEnd?: () => void;\n /** Installed widgets from the store (fetched by parent) */\n installedWidgets?: WidgetDefinition[];\n /** Whether installed widgets are still loading */\n installedWidgetsLoading?: boolean;\n /**\n * Built-in widget catalog (from the backend `getWidgetTypes`, fetched by the\n * parent via useWidgetCatalog). When omitted, falls back to the bundled\n * static registry.\n */\n definitions?: WidgetDefinition[];\n}\n\n// ============================================================================\n// Styles using semantic tokens\n// ============================================================================\n\nconst styles = {\n container: {\n width: '300px',\n height: '100%',\n backgroundColor: 'var(--color-bg-surface)',\n borderRight: '1px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column' as const,\n flexShrink: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n header: {\n padding: 'var(--space-formGap)',\n borderBottom: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n headerTop: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 'var(--space-controlGap)',\n },\n headerTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n },\n headerIcon: {\n width: '32px',\n height: '32px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-action-primary-bg)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n title: {\n fontSize: 'var(--font-size-body-md)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-primary)',\n margin: 0,\n },\n subtitle: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: '2px 0 0 0',\n },\n closeButton: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n border: 'none',\n background: 'transparent',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n color: 'var(--color-text-secondary)',\n transition: 'background-color 0.15s',\n },\n searchContainer: {\n position: 'relative' as const,\n },\n searchIcon: {\n position: 'absolute' as const,\n left: '10px',\n top: '50%',\n transform: 'translateY(-50%)',\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n pointerEvents: 'none' as const,\n },\n searchInput: {\n width: '100%',\n paddingLeft: '36px',\n height: 'var(--size-controlHeight-sm)',\n fontSize: 'var(--font-size-body-sm)',\n },\n content: {\n flex: '1 1 0',\n minHeight: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n scrollArea: {\n position: 'absolute' as const,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n overflowY: 'auto' as const,\n overflowX: 'hidden' as const,\n padding: 'var(--space-controlGap)',\n },\n categoryContainer: {\n marginBottom: 'var(--space-controlGap)',\n },\n categoryHeader: {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-iconGap)',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: 'var(--radius-button)',\n transition: 'background-color 0.15s',\n },\n categoryChevron: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n flexShrink: 0,\n },\n categoryLabel: {\n flex: 1,\n textAlign: 'left' as const,\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-secondary)',\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n },\n categoryCount: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n backgroundColor: 'var(--color-bg-sunken)',\n padding: '2px 8px',\n borderRadius: 'var(--radius-full)',\n },\n widgetList: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '4px',\n marginTop: 'var(--space-controlGap)',\n paddingLeft: '4px',\n },\n widgetCard: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-card)',\n cursor: 'grab',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border)',\n transition: 'all 0.15s ease',\n },\n widgetCardHover: {\n backgroundColor: 'var(--color-bg-hover)',\n borderColor: 'var(--color-action-primary-border)',\n boxShadow: 'var(--shadow-elevation-1)',\n },\n dragHandle: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n opacity: 0.5,\n flexShrink: 0,\n },\n widgetIcon: {\n width: '36px',\n height: '36px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n widgetIconInner: {\n width: '18px',\n height: '18px',\n color: 'var(--color-action-primary-bg)',\n },\n widgetText: {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n },\n widgetName: {\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-text-primary)',\n whiteSpace: 'nowrap' as const,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n marginBottom: '2px',\n },\n widgetDescription: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n lineHeight: 1.3,\n overflow: 'hidden',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical' as const,\n },\n emptyState: {\n textAlign: 'center' as const,\n padding: 'var(--space-pagePadding)',\n },\n emptyIcon: {\n width: '48px',\n height: '48px',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: '0 auto var(--space-formGap)',\n },\n emptyText: {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n margin: 0,\n },\n clearButton: {\n marginTop: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-action-primary-text)',\n backgroundColor: 'var(--color-action-primary-bg)',\n border: 'none',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n },\n footer: {\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n footerText: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: 0,\n textAlign: 'center' as const,\n },\n browseStoreButton: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-iconGap)',\n width: '100%',\n padding: 'var(--space-controlGap)',\n marginBottom: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-button)',\n border: '1px dashed var(--color-border)',\n backgroundColor: 'transparent',\n color: 'var(--color-text-secondary)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n cursor: 'pointer',\n transition: 'border-color 0.15s, color 0.15s',\n },\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WidgetPalette: FC<WidgetPaletteProps> = memo(function WidgetPalette({\n isOpen,\n onClose,\n onWidgetSelect,\n onDragStart,\n onDragEnd,\n installedWidgets = [],\n installedWidgetsLoading = false,\n definitions,\n}) {\n const { t } = useI18n();\n const [searchQuery, setSearchQuery] = useState('');\n const [expandedCategories, setExpandedCategories] = useState<Set<WidgetCategory>>(\n new Set(['KPI', 'Visualization', 'Data', 'Content', 'Temporal', 'Custom', 'Installed'])\n );\n const [hoveredWidget, setHoveredWidget] = useState<string | null>(null);\n\n // Get categorized widgets, merging in installed widgets. When the parent\n // supplies a backend-sourced catalog (`definitions`), group that by category;\n // otherwise fall back to the bundled static registry.\n const categories = useMemo(() => {\n const baseCategories = definitions\n ? (Object.keys(WIDGET_CATEGORY_LABELS) as WidgetCategory[]).map((category) => ({\n category,\n label: WIDGET_CATEGORY_LABELS[category],\n widgets: definitions.filter((def) => def.category === category),\n }))\n : getWidgetCategories();\n\n return baseCategories\n .map((cat) => {\n if (cat.category === 'Installed') {\n // Two sources feed \"Installed from Store\": the registry-driven backend\n // catalog (getWidgetTypes store types — rich metadata, install-gated,\n // BOFF-2858) which arrives via `definitions` under this category, and\n // the legacy workspaceInstalledApps listing passed as `installedWidgets`.\n // Merge both, deduping by name (the catalog entry wins) so a widget\n // present in both sources shows once with the richer definition, while\n // legacy installs not yet in the registry are still preserved.\n const byName = new Map<string, WidgetDefinition>();\n for (const w of installedWidgets) byName.set(w.name.toLowerCase(), w);\n for (const w of cat.widgets) {\n const key = w.name.toLowerCase();\n const legacy = byName.get(key);\n // Catalog wins for metadata but MERGE defaultConfig so the legacy\n // workspaceInstalledApps fields survive — notably `componentId`, which the\n // current render path needs and the catalog store entry lacks until\n // widgetTypeKey rendering is wired. Keeps overlapping store widgets renderable.\n byName.set(key, legacy ? { ...w, defaultConfig: { ...legacy.defaultConfig, ...w.defaultConfig } } : w);\n }\n return { ...cat, widgets: Array.from(byName.values()) };\n }\n return cat;\n })\n .filter((cat) => cat.category !== 'Installed' || cat.widgets.length > 0);\n }, [installedWidgets, definitions]);\n\n // Filter widgets by search query\n const filteredCategories = useMemo(() => {\n if (!searchQuery.trim()) {\n return categories;\n }\n\n const query = searchQuery.toLowerCase();\n return categories\n .map((cat) => ({\n ...cat,\n widgets: cat.widgets.filter(\n (w) =>\n w.name.toLowerCase().includes(query) ||\n w.description.toLowerCase().includes(query) ||\n w.tags.some((tag) => tag.includes(query))\n ),\n }))\n .filter((cat) => cat.widgets.length > 0);\n }, [categories, searchQuery]);\n\n // Toggle category expansion\n const toggleCategory = useCallback((category: WidgetCategory) => {\n setExpandedCategories((prev) => {\n const next = new Set(prev);\n if (next.has(category)) {\n next.delete(category);\n } else {\n next.add(category);\n }\n return next;\n });\n }, []);\n\n // Handle drag start\n const handleDragStart = useCallback(\n (e: React.DragEvent, widget: WidgetDefinition) => {\n e.dataTransfer.setData(\n 'application/json',\n JSON.stringify({\n type: widget.type,\n name: widget.name,\n defaultSize: widget.defaultSize,\n defaultConfig: widget.defaultConfig,\n category: widget.category,\n })\n );\n e.dataTransfer.effectAllowed = 'copy';\n\n // Create custom drag image\n const dragImage = document.createElement('div');\n dragImage.style.cssText = `\n position: absolute;\n top: -1000px;\n left: -1000px;\n padding: 8px 12px;\n background: var(--color-bg-surface);\n border: 2px solid var(--color-action-primary-bg);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--color-text-primary);\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n `;\n dragImage.textContent = widget.name;\n document.body.appendChild(dragImage);\n e.dataTransfer.setDragImage(dragImage, 0, 0);\n\n setTimeout(() => {\n document.body.removeChild(dragImage);\n }, 0);\n\n onDragStart?.(widget.type, widget);\n },\n [onDragStart]\n );\n\n // Handle drag end\n const handleDragEnd = useCallback(() => {\n onDragEnd?.();\n }, [onDragEnd]);\n\n // Handle click to quick-add\n const handleWidgetClick = useCallback(\n (widget: WidgetDefinition) => {\n onWidgetSelect?.(widget.type, widget);\n },\n [onWidgetSelect]\n );\n\n // Open the widget store in a new tab so the builder (and any unsaved edits)\n // stays intact. Preserves the current org/workspace/project query params.\n const handleBrowseStore = useCallback(() => {\n if (typeof window === 'undefined') return;\n const url = `${window.location.origin}/bigconsole/store${window.location.search}`;\n window.open(url, '_blank', 'noopener,noreferrer');\n }, []);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div style={styles.container}>\n {/* Header */}\n <div style={styles.header}>\n <div style={styles.headerTop}>\n <div style={styles.headerTitle}>\n <div style={styles.headerIcon}>\n <Layers style={{ width: '18px', height: '18px', color: 'var(--color-action-primary-text)' }} />\n </div>\n <div>\n <h3 style={styles.title}>{t('bigconsole.dashboards.widgetPalette.title', 'Widgets')}</h3>\n <p style={styles.subtitle}>{t('bigconsole.dashboards.widgetPalette.subtitle', 'Drag or click to add')}</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n style={styles.closeButton}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n <X style={{ width: '16px', height: '16px' }} />\n </button>\n </div>\n\n {/* Search */}\n <div style={styles.searchContainer}>\n <Search style={styles.searchIcon} />\n <Input\n type=\"text\"\n placeholder={t('bigconsole.dashboards.widgetPalette.searchPlaceholder', 'Search widgets...')}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={styles.searchInput}\n />\n </div>\n </div>\n\n {/* Widget Categories */}\n <div style={styles.content}>\n <div style={styles.scrollArea}>\n {filteredCategories.map((category) => (\n <div key={category.category} style={styles.categoryContainer}>\n {/* Category Header */}\n <button\n type=\"button\"\n onClick={() => toggleCategory(category.category)}\n style={styles.categoryHeader}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n {expandedCategories.has(category.category) ? (\n <ChevronDown style={styles.categoryChevron} />\n ) : (\n <ChevronRight style={styles.categoryChevron} />\n )}\n <span style={styles.categoryLabel}>{category.label}</span>\n <span style={styles.categoryCount}>{category.widgets.length}</span>\n </button>\n\n {/* Widget Items */}\n {expandedCategories.has(category.category) && (\n <div style={styles.widgetList}>\n {installedWidgetsLoading && category.category === 'Installed' && (\n <div\n style={{\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n padding: 'var(--space-controlGap)',\n }}\n >\n {t('bigconsole.dashboards.widgetPalette.loading', 'Loading...')}\n </div>\n )}\n {category.widgets.map((widget) => {\n const IconComponent = getIconComponent(widget.icon);\n const widgetKey = getWidgetKey(widget);\n const isHovered = hoveredWidget === widgetKey;\n\n return (\n <div\n key={widgetKey}\n draggable\n onDragStart={(e) => handleDragStart(e, widget)}\n onDragEnd={handleDragEnd}\n onClick={() => handleWidgetClick(widget)}\n onMouseEnter={() => setHoveredWidget(widgetKey)}\n onMouseLeave={() => setHoveredWidget(null)}\n style={{\n ...styles.widgetCard,\n ...(isHovered ? styles.widgetCardHover : {}),\n }}\n >\n {/* Drag Handle */}\n <GripVertical style={styles.dragHandle} />\n\n {/* Icon */}\n <div style={styles.widgetIcon}>\n <IconComponent style={styles.widgetIconInner} />\n </div>\n\n {/* Text */}\n <div style={styles.widgetText}>\n <div style={styles.widgetName}>{widget.name}</div>\n <div style={styles.widgetDescription}>{widget.description}</div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n ))}\n\n {filteredCategories.length === 0 && (\n <div style={styles.emptyState}>\n <div style={styles.emptyIcon}>\n <Search style={{ width: '24px', height: '24px', color: 'var(--color-text-muted)' }} />\n </div>\n <p style={styles.emptyText}>\n {t('bigconsole.dashboards.widgetPalette.noResultsBefore', 'No widgets found for')} \"\n <strong>{searchQuery}</strong>\"\n </p>\n <button type=\"button\" onClick={() => setSearchQuery('')} style={styles.clearButton}>\n {t('bigconsole.dashboards.widgetPalette.clearSearch', 'Clear search')}\n </button>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <div style={styles.footer}>\n <button\n type=\"button\"\n onClick={handleBrowseStore}\n style={styles.browseStoreButton}\n onMouseOver={(e) => {\n e.currentTarget.style.borderColor = 'var(--color-action-primary-bg)';\n e.currentTarget.style.color = 'var(--color-action-primary-text)';\n }}\n onMouseOut={(e) => {\n e.currentTarget.style.borderColor = 'var(--color-border)';\n e.currentTarget.style.color = 'var(--color-text-secondary)';\n }}\n >\n <Store style={{ width: '15px', height: '15px' }} />\n {t('bigconsole.dashboards.widgetPalette.browseStore', 'Browse widget store')}\n <ExternalLink style={{ width: '13px', height: '13px', opacity: 0.7 }} />\n </button>\n <p style={styles.footerText}>\n {t('bigconsole.dashboards.widgetPalette.footerHint', 'Drag widgets to position them on the canvas')}\n </p>\n </div>\n </div>\n );\n});\n\nexport default WidgetPalette;\n"],"mappings":"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"}
|
|
@@ -1,87 +1,90 @@
|
|
|
1
|
-
import { memo as e, useCallback as t, useEffect as n,
|
|
2
|
-
import {
|
|
1
|
+
import { memo as e, useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
|
|
2
|
+
import { useI18n as o } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
3
|
+
import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
3
4
|
//#region src/bigconsole/components/datasink/CacheTTLSelector.tsx
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
value: 900,
|
|
12
|
-
label: "15 minutes",
|
|
13
|
-
description: "Balanced performance",
|
|
14
|
-
recommended: !0
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
value: 3600,
|
|
18
|
-
label: "1 hour",
|
|
19
|
-
description: "For data that changes hourly"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
value: 86400,
|
|
23
|
-
label: "24 hours",
|
|
24
|
-
description: "For daily reports"
|
|
25
|
-
}
|
|
5
|
+
var u = [
|
|
6
|
+
300,
|
|
7
|
+
900,
|
|
8
|
+
3600,
|
|
9
|
+
86400
|
|
26
10
|
];
|
|
27
|
-
function
|
|
28
|
-
return e === null ? !1 :
|
|
11
|
+
function d(e) {
|
|
12
|
+
return e === null ? !1 : u.includes(e);
|
|
29
13
|
}
|
|
30
|
-
function u
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
14
|
+
var f = e(function({ value: e, onChange: u, disabled: f = !1, error: p, hideLabel: m = !1 }) {
|
|
15
|
+
let { t: h } = o(), g = r(() => [
|
|
16
|
+
{
|
|
17
|
+
value: 300,
|
|
18
|
+
label: h("bigconsole.dataSinks.cacheTtl.preset5MinutesLabel", "5 minutes"),
|
|
19
|
+
description: h("bigconsole.dataSinks.cacheTtl.preset5MinutesDescription", "Best for real-time dashboards")
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
value: 900,
|
|
23
|
+
label: h("bigconsole.dataSinks.cacheTtl.preset15MinutesLabel", "15 minutes"),
|
|
24
|
+
description: h("bigconsole.dataSinks.cacheTtl.preset15MinutesDescription", "Balanced performance"),
|
|
25
|
+
recommended: !0
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: 3600,
|
|
29
|
+
label: h("bigconsole.dataSinks.cacheTtl.preset1HourLabel", "1 hour"),
|
|
30
|
+
description: h("bigconsole.dataSinks.cacheTtl.preset1HourDescription", "For data that changes hourly")
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
value: 86400,
|
|
34
|
+
label: h("bigconsole.dataSinks.cacheTtl.preset24HoursLabel", "24 hours"),
|
|
35
|
+
description: h("bigconsole.dataSinks.cacheTtl.preset24HoursDescription", "For daily reports")
|
|
36
|
+
}
|
|
37
|
+
], [h]), _ = t((e) => e < 60 ? h("bigconsole.dataSinks.cacheTtl.durationSeconds", "{{count}} seconds", { count: e }) : e < 3600 ? h("bigconsole.dataSinks.cacheTtl.durationMinutes", "{{count}} minutes", { count: Math.floor(e / 60) }) : e < 86400 ? h("bigconsole.dataSinks.cacheTtl.durationHours", "{{count}} hours", { count: Math.floor(e / 3600) }) : h("bigconsole.dataSinks.cacheTtl.durationDays", "{{count}} days", { count: Math.floor(e / 86400) }), [h]), [v, y] = a(!d(e) && e !== null), [b, x] = a(e?.toString() || ""), [S, C] = a(null), w = i(e);
|
|
35
38
|
n(() => {
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
w.current !== e && (w.current = e, e !== null && !d(e) && queueMicrotask(() => {
|
|
40
|
+
x(e.toString()), y(!0);
|
|
38
41
|
}));
|
|
39
42
|
}, [e]);
|
|
40
|
-
let
|
|
41
|
-
f || (
|
|
42
|
-
}, [f,
|
|
43
|
+
let T = t((e) => {
|
|
44
|
+
f || (y(!1), u(e));
|
|
45
|
+
}, [f, u]), E = t(() => {
|
|
43
46
|
if (f) return;
|
|
44
|
-
|
|
45
|
-
let e = parseInt(
|
|
46
|
-
!isNaN(e) && e >= 30 && e <= 86400 &&
|
|
47
|
+
y(!0);
|
|
48
|
+
let e = parseInt(b);
|
|
49
|
+
!isNaN(e) && e >= 30 && e <= 86400 && u(e);
|
|
47
50
|
}, [
|
|
48
51
|
f,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
]),
|
|
52
|
+
b,
|
|
53
|
+
u
|
|
54
|
+
]), D = t((e) => {
|
|
52
55
|
let t = e.target.value;
|
|
53
|
-
if (
|
|
54
|
-
|
|
56
|
+
if (x(t), t === "") {
|
|
57
|
+
C(null);
|
|
55
58
|
return;
|
|
56
59
|
}
|
|
57
60
|
let n = parseInt(t);
|
|
58
61
|
if (isNaN(n)) {
|
|
59
|
-
|
|
62
|
+
C(h("bigconsole.dataSinks.cacheTtl.errorInvalidNumber", "Please enter a valid number"));
|
|
60
63
|
return;
|
|
61
64
|
}
|
|
62
65
|
if (n < 30) {
|
|
63
|
-
|
|
66
|
+
C(h("bigconsole.dataSinks.cacheTtl.errorMinDuration", "Minimum cache duration is 30 seconds"));
|
|
64
67
|
return;
|
|
65
68
|
}
|
|
66
69
|
if (n > 86400) {
|
|
67
|
-
|
|
70
|
+
C(h("bigconsole.dataSinks.cacheTtl.errorMaxDuration", "Maximum cache duration is 86400 seconds (24 hours)"));
|
|
68
71
|
return;
|
|
69
72
|
}
|
|
70
|
-
|
|
71
|
-
}, [
|
|
72
|
-
return /* @__PURE__ */
|
|
73
|
+
C(null), u(n);
|
|
74
|
+
}, [u, h]);
|
|
75
|
+
return /* @__PURE__ */ l("div", {
|
|
73
76
|
className: "space-y-3",
|
|
74
77
|
children: [
|
|
75
|
-
!m && /* @__PURE__ */
|
|
78
|
+
!m && /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("label", {
|
|
76
79
|
className: "block text-sm font-medium text-text-primary mb-1",
|
|
77
|
-
children: "Cache Duration"
|
|
78
|
-
}), /* @__PURE__ */
|
|
80
|
+
children: h("bigconsole.dataSinks.cacheTtl.heading", "Cache Duration")
|
|
81
|
+
}), /* @__PURE__ */ c("p", {
|
|
79
82
|
className: "text-xs text-text-secondary",
|
|
80
|
-
children: "How long should data be cached before refreshing?"
|
|
83
|
+
children: h("bigconsole.dataSinks.cacheTtl.headingDescription", "How long should data be cached before refreshing?")
|
|
81
84
|
})] }),
|
|
82
|
-
/* @__PURE__ */
|
|
85
|
+
/* @__PURE__ */ l("div", {
|
|
83
86
|
className: "space-y-2",
|
|
84
|
-
children: [
|
|
87
|
+
children: [g.map((t) => /* @__PURE__ */ l("label", {
|
|
85
88
|
className: `
|
|
86
89
|
flex items-start gap-3
|
|
87
90
|
p-3
|
|
@@ -89,32 +92,32 @@ var d = e(function({ value: e, onChange: d, disabled: f = !1, error: p, hideLabe
|
|
|
89
92
|
cursor-pointer
|
|
90
93
|
transition-all
|
|
91
94
|
${f ? "opacity-50 cursor-not-allowed" : ""}
|
|
92
|
-
${!
|
|
95
|
+
${!v && e === t.value ? "border-action-primary-bg bg-action-primary-bg/5" : "border-border-default hover:border-border-hover"}
|
|
93
96
|
`,
|
|
94
|
-
children: [/* @__PURE__ */
|
|
97
|
+
children: [/* @__PURE__ */ c("input", {
|
|
95
98
|
type: "radio",
|
|
96
99
|
name: "cache-ttl",
|
|
97
|
-
checked: !
|
|
98
|
-
onChange: () =>
|
|
100
|
+
checked: !v && e === t.value,
|
|
101
|
+
onChange: () => T(t.value),
|
|
99
102
|
disabled: f,
|
|
100
103
|
className: "\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n "
|
|
101
|
-
}), /* @__PURE__ */
|
|
104
|
+
}), /* @__PURE__ */ l("div", {
|
|
102
105
|
className: "flex-1",
|
|
103
|
-
children: [/* @__PURE__ */
|
|
106
|
+
children: [/* @__PURE__ */ l("div", {
|
|
104
107
|
className: "flex items-center gap-2",
|
|
105
|
-
children: [/* @__PURE__ */
|
|
108
|
+
children: [/* @__PURE__ */ c("span", {
|
|
106
109
|
className: "text-sm font-medium text-text-primary",
|
|
107
110
|
children: t.label
|
|
108
|
-
}), t.recommended && /* @__PURE__ */
|
|
111
|
+
}), t.recommended && /* @__PURE__ */ c("span", {
|
|
109
112
|
className: "px-1.5 py-0.5 text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded",
|
|
110
|
-
children: "Recommended"
|
|
113
|
+
children: h("bigconsole.dataSinks.cacheTtl.recommendedBadge", "Recommended")
|
|
111
114
|
})]
|
|
112
|
-
}), /* @__PURE__ */
|
|
115
|
+
}), /* @__PURE__ */ c("p", {
|
|
113
116
|
className: "text-xs text-text-secondary mt-0.5",
|
|
114
117
|
children: t.description
|
|
115
118
|
})]
|
|
116
119
|
})]
|
|
117
|
-
}, t.value)), /* @__PURE__ */
|
|
120
|
+
}, t.value)), /* @__PURE__ */ l("label", {
|
|
118
121
|
className: `
|
|
119
122
|
flex items-start gap-3
|
|
120
123
|
p-3
|
|
@@ -122,33 +125,33 @@ var d = e(function({ value: e, onChange: d, disabled: f = !1, error: p, hideLabe
|
|
|
122
125
|
cursor-pointer
|
|
123
126
|
transition-all
|
|
124
127
|
${f ? "opacity-50 cursor-not-allowed" : ""}
|
|
125
|
-
${
|
|
128
|
+
${v ? "border-action-primary-bg bg-action-primary-bg/5" : "border-border-default hover:border-border-hover"}
|
|
126
129
|
`,
|
|
127
|
-
children: [/* @__PURE__ */
|
|
130
|
+
children: [/* @__PURE__ */ c("input", {
|
|
128
131
|
type: "radio",
|
|
129
132
|
name: "cache-ttl",
|
|
130
|
-
checked:
|
|
131
|
-
onChange:
|
|
133
|
+
checked: v,
|
|
134
|
+
onChange: E,
|
|
132
135
|
disabled: f,
|
|
133
136
|
className: "\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n "
|
|
134
|
-
}), /* @__PURE__ */
|
|
137
|
+
}), /* @__PURE__ */ l("div", {
|
|
135
138
|
className: "flex-1",
|
|
136
139
|
children: [
|
|
137
|
-
/* @__PURE__ */
|
|
140
|
+
/* @__PURE__ */ c("span", {
|
|
138
141
|
className: "text-sm font-medium text-text-primary",
|
|
139
|
-
children: "Custom"
|
|
142
|
+
children: h("bigconsole.dataSinks.cacheTtl.customLabel", "Custom")
|
|
140
143
|
}),
|
|
141
|
-
/* @__PURE__ */
|
|
144
|
+
/* @__PURE__ */ c("p", {
|
|
142
145
|
className: "text-xs text-text-secondary mt-0.5",
|
|
143
|
-
children: "Enter a custom cache duration (30 - 86400 seconds)"
|
|
146
|
+
children: h("bigconsole.dataSinks.cacheTtl.customDescription", "Enter a custom cache duration (30 - 86400 seconds)")
|
|
144
147
|
}),
|
|
145
|
-
|
|
148
|
+
v && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ l("div", {
|
|
146
149
|
className: "mt-3 flex items-center gap-2",
|
|
147
150
|
children: [
|
|
148
|
-
/* @__PURE__ */
|
|
151
|
+
/* @__PURE__ */ c("input", {
|
|
149
152
|
type: "number",
|
|
150
|
-
value:
|
|
151
|
-
onChange:
|
|
153
|
+
value: b,
|
|
154
|
+
onChange: D,
|
|
152
155
|
disabled: f,
|
|
153
156
|
min: 30,
|
|
154
157
|
max: 86400,
|
|
@@ -163,85 +166,81 @@ var d = e(function({ value: e, onChange: d, disabled: f = !1, error: p, hideLabe
|
|
|
163
166
|
focus:border-action-primary-bg
|
|
164
167
|
focus:ring-2
|
|
165
168
|
focus:ring-action-primary-bg/20
|
|
166
|
-
${p ||
|
|
169
|
+
${p || S ? "border-status-error-border" : "border-border-default"}
|
|
167
170
|
`
|
|
168
171
|
}),
|
|
169
|
-
/* @__PURE__ */
|
|
172
|
+
/* @__PURE__ */ c("span", {
|
|
170
173
|
className: "text-sm text-text-secondary",
|
|
171
|
-
children: "seconds"
|
|
174
|
+
children: h("bigconsole.dataSinks.cacheTtl.secondsUnit", "seconds")
|
|
172
175
|
}),
|
|
173
|
-
|
|
176
|
+
b && !isNaN(parseInt(b)) && !S && /* @__PURE__ */ l("span", {
|
|
174
177
|
className: "text-xs text-text-tertiary",
|
|
175
178
|
children: [
|
|
176
179
|
"(",
|
|
177
|
-
|
|
180
|
+
_(parseInt(b)),
|
|
178
181
|
")"
|
|
179
182
|
]
|
|
180
183
|
})
|
|
181
184
|
]
|
|
182
|
-
}),
|
|
185
|
+
}), S && /* @__PURE__ */ l("div", {
|
|
183
186
|
className: "flex items-center gap-1 mt-1",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
187
|
+
children: [/* @__PURE__ */ c("svg", {
|
|
185
188
|
className: "w-3.5 h-3.5 text-status-error-text flex-shrink-0",
|
|
186
189
|
fill: "none",
|
|
187
190
|
stroke: "currentColor",
|
|
188
191
|
viewBox: "0 0 24 24",
|
|
189
|
-
children: /* @__PURE__ */
|
|
192
|
+
children: /* @__PURE__ */ c("path", {
|
|
190
193
|
strokeLinecap: "round",
|
|
191
194
|
strokeLinejoin: "round",
|
|
192
195
|
strokeWidth: 2,
|
|
193
196
|
d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
194
197
|
})
|
|
195
|
-
}), /* @__PURE__ */
|
|
198
|
+
}), /* @__PURE__ */ c("span", {
|
|
196
199
|
className: "text-xs text-status-error-text",
|
|
197
|
-
children:
|
|
200
|
+
children: S
|
|
198
201
|
})]
|
|
199
202
|
})] })
|
|
200
203
|
]
|
|
201
204
|
})]
|
|
202
205
|
})]
|
|
203
206
|
}),
|
|
204
|
-
p && /* @__PURE__ */
|
|
207
|
+
p && /* @__PURE__ */ l("div", {
|
|
205
208
|
className: "flex items-start gap-2",
|
|
206
|
-
children: [/* @__PURE__ */
|
|
209
|
+
children: [/* @__PURE__ */ c("svg", {
|
|
207
210
|
className: "w-4 h-4 text-status-error-text flex-shrink-0 mt-0.5",
|
|
208
211
|
fill: "none",
|
|
209
212
|
stroke: "currentColor",
|
|
210
213
|
viewBox: "0 0 24 24",
|
|
211
|
-
children: /* @__PURE__ */
|
|
214
|
+
children: /* @__PURE__ */ c("path", {
|
|
212
215
|
strokeLinecap: "round",
|
|
213
216
|
strokeLinejoin: "round",
|
|
214
217
|
strokeWidth: 2,
|
|
215
218
|
d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
216
219
|
})
|
|
217
|
-
}), /* @__PURE__ */
|
|
220
|
+
}), /* @__PURE__ */ c("p", {
|
|
218
221
|
className: "text-xs text-status-error-text",
|
|
219
222
|
children: p
|
|
220
223
|
})]
|
|
221
224
|
}),
|
|
222
|
-
e !== null && !p && /* @__PURE__ */
|
|
225
|
+
e !== null && !p && /* @__PURE__ */ l("div", {
|
|
223
226
|
className: "flex items-center gap-2 text-xs text-text-secondary",
|
|
224
|
-
children: [/* @__PURE__ */
|
|
227
|
+
children: [/* @__PURE__ */ c("svg", {
|
|
225
228
|
className: "w-4 h-4",
|
|
226
229
|
fill: "none",
|
|
227
230
|
stroke: "currentColor",
|
|
228
231
|
viewBox: "0 0 24 24",
|
|
229
|
-
children: /* @__PURE__ */
|
|
232
|
+
children: /* @__PURE__ */ c("path", {
|
|
230
233
|
strokeLinecap: "round",
|
|
231
234
|
strokeLinejoin: "round",
|
|
232
235
|
strokeWidth: 2,
|
|
233
236
|
d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
234
237
|
})
|
|
235
|
-
}), /* @__PURE__ */
|
|
236
|
-
"Data will be cached for ",
|
|
237
|
-
u(e),
|
|
238
|
-
" before being refreshed"
|
|
239
|
-
] })]
|
|
238
|
+
}), /* @__PURE__ */ c("span", { children: h("bigconsole.dataSinks.cacheTtl.infoCachedFor", "Data will be cached for {{duration}} before being refreshed", { duration: _(e) }) })]
|
|
240
239
|
})
|
|
241
240
|
]
|
|
242
241
|
});
|
|
243
242
|
});
|
|
244
243
|
//#endregion
|
|
245
|
-
export {
|
|
244
|
+
export { f as default };
|
|
246
245
|
|
|
247
246
|
//# sourceMappingURL=CacheTTLSelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheTTLSelector.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/CacheTTLSelector.tsx"],"sourcesContent":["/**\n * Cache TTL Selector\n *\n * Component for selecting cache duration with preset options and custom input.\n */\n\nimport { memo, useState, useEffect, useCallback, useRef } from 'react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface CacheTTLOption {\n value: number;\n label: string;\n description: string;\n recommended?: boolean;\n}\n\ninterface CacheTTLSelectorProps {\n /** Current TTL value in seconds (null for no cache) */\n value: number | null;\n /** Callback when value changes */\n onChange: (value: number) => void;\n /** Whether selector is disabled */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /**\n * Hide the built-in \"Cache Duration\" heading + description. Use when the\n * surrounding form already renders its own label for this control, to avoid a\n * duplicated heading.\n */\n hideLabel?: boolean;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst PRESET_OPTIONS: CacheTTLOption[] = [\n {\n value: 300, // 5 minutes\n label: '5 minutes',\n description: 'Best for real-time dashboards',\n },\n {\n value: 900, // 15 minutes\n label: '15 minutes',\n description: 'Balanced performance',\n recommended: true,\n },\n {\n value: 3600, // 1 hour\n label: '1 hour',\n description: 'For data that changes hourly',\n },\n {\n value: 86400, // 24 hours\n label: '24 hours',\n description: 'For daily reports',\n },\n];\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Check if value is a preset option\n */\nfunction isPresetValue(value: number | null): boolean {\n if (value === null) return false;\n return PRESET_OPTIONS.some((opt) => opt.value === value);\n}\n\n/**\n * Format seconds to human-readable string\n */\nfunction formatDuration(seconds: number): string {\n if (seconds < 60) {\n return `${seconds} seconds`;\n }\n if (seconds < 3600) {\n return `${Math.floor(seconds / 60)} minutes`;\n }\n if (seconds < 86400) {\n return `${Math.floor(seconds / 3600)} hours`;\n }\n return `${Math.floor(seconds / 86400)} days`;\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const CacheTTLSelector = memo(function CacheTTLSelector({\n value,\n onChange,\n disabled = false,\n error,\n hideLabel = false,\n}: CacheTTLSelectorProps) {\n // Track whether custom mode is active\n const [isCustom, setIsCustom] = useState(!isPresetValue(value) && value !== null);\n const [customValue, setCustomValue] = useState(value?.toString() || '');\n const [validationError, setValidationError] = useState<string | null>(null);\n const prevValueRef = useRef(value);\n\n // Sync custom value when external value changes (using deferred update to avoid cascading renders)\n useEffect(() => {\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (value !== null && !isPresetValue(value)) {\n // Defer state update to avoid synchronous setState in effect\n queueMicrotask(() => {\n setCustomValue(value.toString());\n setIsCustom(true);\n });\n }\n }\n }, [value]);\n\n // Handle preset selection\n const handlePresetChange = useCallback(\n (presetValue: number) => {\n if (disabled) return;\n setIsCustom(false);\n onChange(presetValue);\n },\n [disabled, onChange]\n );\n\n // Handle custom mode activation\n const handleCustomSelect = useCallback(() => {\n if (disabled) return;\n setIsCustom(true);\n const parsed = parseInt(customValue);\n if (!isNaN(parsed) && parsed >= 30 && parsed <= 86400) {\n onChange(parsed);\n }\n }, [disabled, customValue, onChange]);\n\n // Handle custom value change with validation\n const handleCustomChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n setCustomValue(inputValue);\n\n // Validate input\n if (inputValue === '') {\n setValidationError(null);\n return;\n }\n\n const parsed = parseInt(inputValue);\n\n if (isNaN(parsed)) {\n setValidationError('Please enter a valid number');\n return;\n }\n\n if (parsed < 30) {\n setValidationError('Minimum cache duration is 30 seconds');\n return;\n }\n\n if (parsed > 86400) {\n setValidationError('Maximum cache duration is 86400 seconds (24 hours)');\n return;\n }\n\n // Valid value\n setValidationError(null);\n onChange(parsed);\n },\n [onChange]\n );\n\n return (\n <div className=\"space-y-3\">\n {/* Label (optional — hidden when the surrounding form supplies its own) */}\n {!hideLabel && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Cache Duration</label>\n <p className=\"text-xs text-text-secondary\">How long should data be cached before refreshing?</p>\n </div>\n )}\n\n {/* Options */}\n <div className=\"space-y-2\">\n {/* Preset options */}\n {PRESET_OPTIONS.map((option) => (\n <label\n key={option.value}\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n !isCustom && value === option.value\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={!isCustom && value === option.value}\n onChange={() => handlePresetChange(option.value)}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{option.label}</span>\n {option.recommended && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded\">\n Recommended\n </span>\n )}\n </div>\n <p className=\"text-xs text-text-secondary mt-0.5\">{option.description}</p>\n </div>\n </label>\n ))}\n\n {/* Custom option */}\n <label\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n isCustom\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={isCustom}\n onChange={handleCustomSelect}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <span className=\"text-sm font-medium text-text-primary\">Custom</span>\n <p className=\"text-xs text-text-secondary mt-0.5\">Enter a custom cache duration (30 - 86400 seconds)</p>\n {isCustom && (\n <>\n <div className=\"mt-3 flex items-center gap-2\">\n <input\n type=\"number\"\n value={customValue}\n onChange={handleCustomChange}\n disabled={disabled}\n min={30}\n max={86400}\n placeholder=\"300\"\n className={`\n w-32 px-3 py-2\n bg-bg-sunken\n border rounded-md\n text-sm text-text-primary\n placeholder-text-tertiary\n focus:outline-none\n focus:border-action-primary-bg\n focus:ring-2\n focus:ring-action-primary-bg/20\n ${error || validationError ? 'border-status-error-border' : 'border-border-default'}\n `}\n />\n <span className=\"text-sm text-text-secondary\">seconds</span>\n {customValue && !isNaN(parseInt(customValue)) && !validationError && (\n <span className=\"text-xs text-text-tertiary\">({formatDuration(parseInt(customValue))})</span>\n )}\n </div>\n {validationError && (\n <div className=\"flex items-center gap-1 mt-1\">\n <svg\n className=\"w-3.5 h-3.5 text-status-error-text flex-shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span className=\"text-xs text-status-error-text\">{validationError}</span>\n </div>\n )}\n </>\n )}\n </div>\n </label>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-start gap-2\">\n <svg\n className=\"w-4 h-4 text-status-error-text flex-shrink-0 mt-0.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-xs text-status-error-text\">{error}</p>\n </div>\n )}\n\n {/* Info message */}\n {value !== null && !error && (\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span>Data will be cached for {formatDuration(value)} before being refreshed</span>\n </div>\n )}\n </div>\n );\n});\n\nexport default CacheTTLSelector;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CacheTTLSelector.js","names":[],"sources":["../../../../src/bigconsole/components/datasink/CacheTTLSelector.tsx"],"sourcesContent":["/**\n * Cache TTL Selector\n *\n * Component for selecting cache duration with preset options and custom input.\n */\n\nimport { memo, useState, useEffect, useCallback, useMemo, useRef } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface CacheTTLOption {\n value: number;\n label: string;\n description: string;\n recommended?: boolean;\n}\n\ninterface CacheTTLSelectorProps {\n /** Current TTL value in seconds (null for no cache) */\n value: number | null;\n /** Callback when value changes */\n onChange: (value: number) => void;\n /** Whether selector is disabled */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /**\n * Hide the built-in \"Cache Duration\" heading + description. Use when the\n * surrounding form already renders its own label for this control, to avoid a\n * duplicated heading.\n */\n hideLabel?: boolean;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst PRESET_VALUES: number[] = [300, 900, 3600, 86400];\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Check if value is a preset option\n */\nfunction isPresetValue(value: number | null): boolean {\n if (value === null) return false;\n return PRESET_VALUES.includes(value);\n}\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const CacheTTLSelector = memo(function CacheTTLSelector({\n value,\n onChange,\n disabled = false,\n error,\n hideLabel = false,\n}: CacheTTLSelectorProps) {\n const { t } = useI18n();\n\n const PRESET_OPTIONS = useMemo<CacheTTLOption[]>(\n () => [\n {\n value: 300, // 5 minutes\n label: t('bigconsole.dataSinks.cacheTtl.preset5MinutesLabel', '5 minutes'),\n description: t('bigconsole.dataSinks.cacheTtl.preset5MinutesDescription', 'Best for real-time dashboards'),\n },\n {\n value: 900, // 15 minutes\n label: t('bigconsole.dataSinks.cacheTtl.preset15MinutesLabel', '15 minutes'),\n description: t('bigconsole.dataSinks.cacheTtl.preset15MinutesDescription', 'Balanced performance'),\n recommended: true,\n },\n {\n value: 3600, // 1 hour\n label: t('bigconsole.dataSinks.cacheTtl.preset1HourLabel', '1 hour'),\n description: t('bigconsole.dataSinks.cacheTtl.preset1HourDescription', 'For data that changes hourly'),\n },\n {\n value: 86400, // 24 hours\n label: t('bigconsole.dataSinks.cacheTtl.preset24HoursLabel', '24 hours'),\n description: t('bigconsole.dataSinks.cacheTtl.preset24HoursDescription', 'For daily reports'),\n },\n ],\n [t]\n );\n\n // Format seconds to human-readable string\n const formatDuration = useCallback(\n (seconds: number): string => {\n if (seconds < 60) {\n return t('bigconsole.dataSinks.cacheTtl.durationSeconds', '{{count}} seconds', { count: seconds });\n }\n if (seconds < 3600) {\n return t('bigconsole.dataSinks.cacheTtl.durationMinutes', '{{count}} minutes', {\n count: Math.floor(seconds / 60),\n });\n }\n if (seconds < 86400) {\n return t('bigconsole.dataSinks.cacheTtl.durationHours', '{{count}} hours', {\n count: Math.floor(seconds / 3600),\n });\n }\n return t('bigconsole.dataSinks.cacheTtl.durationDays', '{{count}} days', {\n count: Math.floor(seconds / 86400),\n });\n },\n [t]\n );\n\n // Track whether custom mode is active\n const [isCustom, setIsCustom] = useState(!isPresetValue(value) && value !== null);\n const [customValue, setCustomValue] = useState(value?.toString() || '');\n const [validationError, setValidationError] = useState<string | null>(null);\n const prevValueRef = useRef(value);\n\n // Sync custom value when external value changes (using deferred update to avoid cascading renders)\n useEffect(() => {\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (value !== null && !isPresetValue(value)) {\n // Defer state update to avoid synchronous setState in effect\n queueMicrotask(() => {\n setCustomValue(value.toString());\n setIsCustom(true);\n });\n }\n }\n }, [value]);\n\n // Handle preset selection\n const handlePresetChange = useCallback(\n (presetValue: number) => {\n if (disabled) return;\n setIsCustom(false);\n onChange(presetValue);\n },\n [disabled, onChange]\n );\n\n // Handle custom mode activation\n const handleCustomSelect = useCallback(() => {\n if (disabled) return;\n setIsCustom(true);\n const parsed = parseInt(customValue);\n if (!isNaN(parsed) && parsed >= 30 && parsed <= 86400) {\n onChange(parsed);\n }\n }, [disabled, customValue, onChange]);\n\n // Handle custom value change with validation\n const handleCustomChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n setCustomValue(inputValue);\n\n // Validate input\n if (inputValue === '') {\n setValidationError(null);\n return;\n }\n\n const parsed = parseInt(inputValue);\n\n if (isNaN(parsed)) {\n setValidationError(t('bigconsole.dataSinks.cacheTtl.errorInvalidNumber', 'Please enter a valid number'));\n return;\n }\n\n if (parsed < 30) {\n setValidationError(t('bigconsole.dataSinks.cacheTtl.errorMinDuration', 'Minimum cache duration is 30 seconds'));\n return;\n }\n\n if (parsed > 86400) {\n setValidationError(\n t('bigconsole.dataSinks.cacheTtl.errorMaxDuration', 'Maximum cache duration is 86400 seconds (24 hours)')\n );\n return;\n }\n\n // Valid value\n setValidationError(null);\n onChange(parsed);\n },\n [onChange, t]\n );\n\n return (\n <div className=\"space-y-3\">\n {/* Label (optional — hidden when the surrounding form supplies its own) */}\n {!hideLabel && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {t('bigconsole.dataSinks.cacheTtl.heading', 'Cache Duration')}\n </label>\n <p className=\"text-xs text-text-secondary\">\n {t('bigconsole.dataSinks.cacheTtl.headingDescription', 'How long should data be cached before refreshing?')}\n </p>\n </div>\n )}\n\n {/* Options */}\n <div className=\"space-y-2\">\n {/* Preset options */}\n {PRESET_OPTIONS.map((option) => (\n <label\n key={option.value}\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n !isCustom && value === option.value\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={!isCustom && value === option.value}\n onChange={() => handlePresetChange(option.value)}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{option.label}</span>\n {option.recommended && (\n <span className=\"px-1.5 py-0.5 text-xs font-medium bg-action-primary-bg/10 text-action-primary-bg rounded\">\n {t('bigconsole.dataSinks.cacheTtl.recommendedBadge', 'Recommended')}\n </span>\n )}\n </div>\n <p className=\"text-xs text-text-secondary mt-0.5\">{option.description}</p>\n </div>\n </label>\n ))}\n\n {/* Custom option */}\n <label\n className={`\n flex items-start gap-3\n p-3\n border rounded-lg\n cursor-pointer\n transition-all\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n ${\n isCustom\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-default hover:border-border-hover'\n }\n `}\n >\n <input\n type=\"radio\"\n name=\"cache-ttl\"\n checked={isCustom}\n onChange={handleCustomSelect}\n disabled={disabled}\n className={`\n mt-0.5\n w-4 h-4\n text-action-primary-bg\n border-border-default\n focus:ring-action-primary-bg\n focus:ring-offset-0\n `}\n />\n <div className=\"flex-1\">\n <span className=\"text-sm font-medium text-text-primary\">\n {t('bigconsole.dataSinks.cacheTtl.customLabel', 'Custom')}\n </span>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {t(\n 'bigconsole.dataSinks.cacheTtl.customDescription',\n 'Enter a custom cache duration (30 - 86400 seconds)'\n )}\n </p>\n {isCustom && (\n <>\n <div className=\"mt-3 flex items-center gap-2\">\n <input\n type=\"number\"\n value={customValue}\n onChange={handleCustomChange}\n disabled={disabled}\n min={30}\n max={86400}\n placeholder=\"300\"\n className={`\n w-32 px-3 py-2\n bg-bg-sunken\n border rounded-md\n text-sm text-text-primary\n placeholder-text-tertiary\n focus:outline-none\n focus:border-action-primary-bg\n focus:ring-2\n focus:ring-action-primary-bg/20\n ${error || validationError ? 'border-status-error-border' : 'border-border-default'}\n `}\n />\n <span className=\"text-sm text-text-secondary\">\n {t('bigconsole.dataSinks.cacheTtl.secondsUnit', 'seconds')}\n </span>\n {customValue && !isNaN(parseInt(customValue)) && !validationError && (\n <span className=\"text-xs text-text-tertiary\">({formatDuration(parseInt(customValue))})</span>\n )}\n </div>\n {validationError && (\n <div className=\"flex items-center gap-1 mt-1\">\n <svg\n className=\"w-3.5 h-3.5 text-status-error-text flex-shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span className=\"text-xs text-status-error-text\">{validationError}</span>\n </div>\n )}\n </>\n )}\n </div>\n </label>\n </div>\n\n {/* Error message */}\n {error && (\n <div className=\"flex items-start gap-2\">\n <svg\n className=\"w-4 h-4 text-status-error-text flex-shrink-0 mt-0.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-xs text-status-error-text\">{error}</p>\n </div>\n )}\n\n {/* Info message */}\n {value !== null && !error && (\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span>\n {t(\n 'bigconsole.dataSinks.cacheTtl.infoCachedFor',\n 'Data will be cached for {{duration}} before being refreshed',\n {\n duration: formatDuration(value),\n }\n )}\n </span>\n </div>\n )}\n </div>\n );\n});\n\nexport default CacheTTLSelector;\n"],"mappings":"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"}
|