@burdenoff/microfe-bigconsole 2026.624.2 → 2026.626.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 (72) hide show
  1. package/dist/bigconsole/BigConsoleRoutes.js +175 -118
  2. package/dist/bigconsole/BigConsoleRoutes.js.map +1 -1
  3. package/dist/bigconsole/assistant/assistantApi.js +215 -0
  4. package/dist/bigconsole/assistant/assistantApi.js.map +1 -0
  5. package/dist/bigconsole/assistant/createSandboxAssistantTransport.js +119 -0
  6. package/dist/bigconsole/assistant/createSandboxAssistantTransport.js.map +1 -0
  7. package/dist/bigconsole/assistant/index.js +2 -0
  8. package/dist/bigconsole/assistant/pageContext.js +51 -0
  9. package/dist/bigconsole/assistant/pageContext.js.map +1 -0
  10. package/dist/bigconsole/components/dashboard/CreateDashboardDialog.js +48 -48
  11. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +52 -52
  12. package/dist/bigconsole/components/dashboard/DrilldownBreadcrumb.js.map +1 -1
  13. package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +33 -33
  14. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +179 -179
  15. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  16. package/dist/bigconsole/components/dashboard/WidgetPalette.js +38 -38
  17. package/dist/bigconsole/components/datasink/DataSinkTableViewer.js +32 -32
  18. package/dist/bigconsole/components/datasink/ExportDataSinkDialog.js +31 -31
  19. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +98 -98
  20. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  21. package/dist/bigconsole/components/parser/ExportParserDialog.js +31 -31
  22. package/dist/bigconsole/components/parser/ImportParserDialog.js +162 -162
  23. package/dist/bigconsole/components/parser/ImportParserDialog.js.map +1 -1
  24. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +79 -79
  25. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  26. package/dist/bigconsole/components/widgets/DrilldownConfigPanel.js.map +1 -1
  27. package/dist/bigconsole/components/widgets/PropertiesPanel.js +307 -307
  28. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  29. package/dist/bigconsole/components/widgets/WidgetConfigDialog.js +222 -222
  30. package/dist/bigconsole/components/widgets/WidgetConfigDialog.js.map +1 -1
  31. package/dist/bigconsole/components/widgets/WidgetTypeSelector.js +23 -23
  32. package/dist/bigconsole/index.js +3 -0
  33. package/dist/bigconsole/pages/DashboardBuilderPage.js +74 -74
  34. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  35. package/dist/bigconsole/pages/DashboardViewPage.js +168 -189
  36. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  37. package/dist/bigconsole/pages/DashboardsPage.js +266 -310
  38. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  39. package/dist/bigconsole/pages/DataParsersPage.js +148 -194
  40. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  41. package/dist/bigconsole/pages/DataSinkBuilderPage.js +252 -246
  42. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  43. package/dist/bigconsole/pages/DataSinkViewPage.js +256 -231
  44. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  45. package/dist/bigconsole/pages/DataSinksPage.js +173 -219
  46. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  47. package/dist/bigconsole/pages/HomePage.js +125 -141
  48. package/dist/bigconsole/pages/HomePage.js.map +1 -1
  49. package/dist/bigconsole/pages/InsightsPage.js +159 -184
  50. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  51. package/dist/bigconsole/pages/ParserBuilderPage.js +401 -393
  52. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  53. package/dist/bigconsole/pages/ParserViewPage.js +220 -201
  54. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  55. package/dist/bigconsole/pages/PipelineBuilderPage.js +212 -206
  56. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  57. package/dist/bigconsole/pages/PipelineViewPage.js +204 -181
  58. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  59. package/dist/bigconsole/pages/PipelinesPage.js +107 -150
  60. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  61. package/dist/bigconsole/pages/SettingsPage.js +184 -171
  62. package/dist/bigconsole/pages/SettingsPage.js.map +1 -1
  63. package/dist/bigconsole/pages/WidgetDemoPage.js +69 -81
  64. package/dist/bigconsole/pages/WidgetDemoPage.js.map +1 -1
  65. package/dist/bigconsole/pages/WorkflowViewPage.js +230 -216
  66. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  67. package/dist/bigconsole/pages/WorkflowsPage.js +106 -149
  68. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  69. package/dist/generated/wspace-operations.js +87 -36
  70. package/dist/generated/wspace-operations.js.map +1 -1
  71. package/dist/index.js +3 -1
  72. package/package.json +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"DataParsersPage.js","names":[],"sources":["../../../src/bigconsole/pages/DataParsersPage.tsx"],"sourcesContent":["/**\n * Data Parsers Page\n *\n * Page for listing and managing parsers with filtering and search.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeConfirm, nativeImpact, nativeNotify } from '../../utils/nativeBridge';\nimport { useParserStore } from '../store/parserStore';\nimport { useParserOperations } from '../hooks/useParserOperations';\nimport { useExportParser } from '../hooks/useExportParser';\nimport { ParserCard } from '../components/parser/ParserCard';\nimport { ImportParserDialog } from '../components/parser/ImportParserDialog';\nimport type { Parser, ParserType, ParserStatus } from '../types';\n\n// fe-libs UI 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';\n\n// Lucide icons\nimport { Plus, Search, AlertCircle, FileCode2, FolderOpen, X, Upload, Download } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserFilterOption<T> {\n value: T | 'all';\n label: string;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst TYPE_OPTIONS: ParserFilterOption<ParserType>[] = [\n { value: 'all', label: 'All Types' },\n { value: 'jq', label: 'JQ' },\n { value: 'jsonata', label: 'JSONata' },\n];\n\nconst STATUS_OPTIONS: ParserFilterOption<ParserStatus>[] = [\n { value: 'all', label: 'All Status' },\n { value: 'active', label: 'Active' },\n { value: 'inactive', label: 'Inactive' },\n];\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\n// Default console ID for standalone parser listing\nconst DEFAULT_CONSOLE_ID = 'default';\n\nexport const DataParsersPage = memo(function DataParsersPage() {\n const navigate = useAppNavigate();\n const { consoleId: urlConsoleId } = useParams<{ consoleId?: string }>();\n\n // Use URL consoleId or fall back to default\n const consoleId = urlConsoleId || DEFAULT_CONSOLE_ID;\n\n // Store state\n const typeFilter = useParserStore((state) => state.typeFilter);\n const statusFilter = useParserStore((state) => state.statusFilter);\n const searchQuery = useParserStore((state) => state.searchQuery);\n const setTypeFilter = useParserStore((state) => state.setTypeFilter);\n const setStatusFilter = useParserStore((state) => state.setStatusFilter);\n const setSearchQuery = useParserStore((state) => state.setSearchQuery);\n\n // Local state\n const [isDeleting, setIsDeleting] = useState(false);\n const [deleteTargetId, setDeleteTargetId] = useState<string | null>(null);\n const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);\n\n // Operations - use consoleId from URL or default\n const { loading, error, parsers, deleteParser, refetch } = useParserOperations({\n consoleId,\n skipFetch: false,\n });\n\n // Export hook\n const { downloadParser, loading: exportLoading } = useExportParser();\n\n // Filter parsers\n const filteredParsers = useMemo(() => {\n if (!parsers) return [];\n\n return parsers.filter((parser: Parser) => {\n if (typeFilter && parser.type !== typeFilter) {\n return false;\n }\n if (statusFilter && parser.status !== statusFilter) {\n return false;\n }\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n const nameMatch = parser.name?.toLowerCase().includes(query);\n const descMatch = parser.description?.toLowerCase().includes(query);\n const inputKeyMatch = parser.inputSinkKey?.toLowerCase().includes(query);\n const outputKeyMatch = parser.outputKey?.toLowerCase().includes(query);\n if (!nameMatch && !descMatch && !inputKeyMatch && !outputKeyMatch) {\n return false;\n }\n }\n return true;\n });\n }, [parsers, typeFilter, statusFilter, searchQuery]);\n\n // Handlers\n const handleTypeFilterChange = useCallback(\n (value: string) => {\n setTypeFilter(value === 'all' ? null : (value as ParserType));\n },\n [setTypeFilter]\n );\n\n const handleStatusFilterChange = useCallback(\n (value: string) => {\n setStatusFilter(value === 'all' ? null : (value as ParserStatus));\n },\n [setStatusFilter]\n );\n\n const handleSearchChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchQuery(e.target.value);\n },\n [setSearchQuery]\n );\n\n const handleCreateParser = useCallback(() => {\n // Navigate to dashboard-scoped parser creation if consoleId is provided\n if (urlConsoleId) {\n navigate(`/dashboards/${urlConsoleId}/parsers/new`);\n } else {\n navigate('/parsers/new');\n }\n }, [navigate, urlConsoleId]);\n\n const handleViewParser = useCallback(\n (id: string) => {\n // Navigate to dashboard-scoped parser view if consoleId is provided\n if (urlConsoleId) {\n navigate(`/dashboards/${urlConsoleId}/parsers/${id}`);\n } else {\n navigate(`/parsers/${id}`);\n }\n },\n [navigate, urlConsoleId]\n );\n\n const handleEditParser = useCallback(\n (id: string) => {\n // Navigate to dashboard-scoped parser edit if consoleId is provided\n if (urlConsoleId) {\n navigate(`/dashboards/${urlConsoleId}/parsers/${id}/edit`);\n } else {\n navigate(`/parsers/${id}/edit`);\n }\n },\n [navigate, urlConsoleId]\n );\n\n const handleDeleteParser = useCallback(\n async (id: string) => {\n const native = await nativeConfirm({\n title: 'Delete parser?',\n message: 'Are you sure you want to delete this parser?',\n okButtonTitle: 'Delete',\n cancelButtonTitle: 'Cancel',\n });\n const ok = native === null ? window.confirm('Are you sure you want to delete this parser?') : native;\n if (!ok) return;\n nativeImpact('medium');\n setIsDeleting(true);\n setDeleteTargetId(id);\n try {\n await deleteParser(id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n } finally {\n setIsDeleting(false);\n setDeleteTargetId(null);\n }\n },\n [deleteParser]\n );\n\n const handleClearFilters = useCallback(() => {\n setTypeFilter(null);\n setStatusFilter(null);\n setSearchQuery('');\n }, [setTypeFilter, setStatusFilter, setSearchQuery]);\n\n const handleExportParser = useCallback(\n async (id: string) => {\n const parser = parsers.find((p: Parser) => p.id === id);\n if (parser) {\n await downloadParser(id, parser.name);\n }\n },\n [parsers, downloadParser]\n );\n\n const handleImportParser = useCallback(() => {\n setIsImportDialogOpen(true);\n }, []);\n\n const handleImportSuccess = useCallback(\n (_parserId: string, _parserName: string, _wasUpdate: boolean) => {\n // Refetch parsers to show the newly imported one\n refetch();\n },\n [refetch]\n );\n\n const hasActiveFilters = typeFilter !== null || statusFilter !== null || (searchQuery?.length ?? 0) > 0;\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>\n <div\n style={{\n padding: 'var(--space-controlGap)',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <AlertCircle\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-status-error-text)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Failed to load Parsers\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()}>\n Try Again\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div style={{ borderBottom: '1px solid var(--color-border)', backgroundColor: 'var(--color-bg-surface)' }}>\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <FileCode2\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n Data Parsers\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n Transform and process data with JQ or JSONata expressions\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', gap: 'var(--space-controlGap)' }}>\n <Button variant=\"outline\" onClick={handleImportParser}>\n <Upload\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Import\n </Button>\n <Button onClick={handleCreateParser}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Create Parser\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\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', flex: 1 }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder=\"Search parsers...\"\n value={searchQuery || ''}\n onChange={handleSearchChange}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n\n {/* Type Filter */}\n <Select value={typeFilter || 'all'} onValueChange={handleTypeFilterChange}>\n <SelectTrigger style={{ width: '150px' }}>\n <SelectValue placeholder=\"All Types\" />\n </SelectTrigger>\n <SelectContent>\n {TYPE_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {/* Status Filter */}\n <Select value={statusFilter || 'all'} onValueChange={handleStatusFilterChange}>\n <SelectTrigger style={{ width: '150px' }}>\n <SelectValue placeholder=\"All Status\" />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\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 Clear Filters\n </Button>\n )}\n\n {/* Results Count */}\n <Badge variant=\"secondary\" style={{ marginLeft: 'auto' }}>\n {filteredParsers.length} {filteredParsers.length === 1 ? 'Parser' : 'Parsers'}\n </Badge>\n </div>\n\n {/* Loading state */}\n {loading && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n Loading parsers...\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && filteredParsers.length === 0 && !hasActiveFilters && (\n <Card className=\"border-dashed\">\n <CardContent\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px var(--space-pagePadding)',\n }}\n >\n <div\n style={{\n display: 'flex',\n height: '80px',\n width: '80px',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '50%',\n backgroundColor: 'var(--color-bg-sunken)',\n marginBottom: 'var(--space-sectionGap)',\n }}\n >\n <FolderOpen\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-text-muted)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-semibold)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n No Parsers yet\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginBottom: 'var(--space-sectionGap)',\n textAlign: 'center',\n maxWidth: '400px',\n }}\n >\n Create your first parser to start transforming data with JQ or JSONata.\n </p>\n <Button onClick={handleCreateParser}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Create Parser\n </Button>\n </CardContent>\n </Card>\n )}\n\n {/* No results state */}\n {!loading && filteredParsers.length === 0 && hasActiveFilters && (\n <div style={{ padding: '64px 0', textAlign: 'center' }}>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n No parsers match your filters\n </p>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClearFilters}\n style={{ marginTop: 'var(--space-formGap)' }}\n >\n Clear Filters\n </Button>\n </div>\n )}\n\n {/* Parser Grid */}\n {!loading && filteredParsers.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredParsers.map((parser: Parser) => (\n <ParserCard\n key={parser.id}\n parser={parser}\n onView={handleViewParser}\n onEdit={handleEditParser}\n onExport={handleExportParser}\n onDelete={handleDeleteParser}\n isDeleting={isDeleting && deleteTargetId === parser.id}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Import Parser Dialog */}\n <ImportParserDialog\n isOpen={isImportDialogOpen}\n onClose={() => setIsImportDialogOpen(false)}\n consoleId={consoleId}\n onSuccess={handleImportSuccess}\n />\n </div>\n );\n});\n\nexport default DataParsersPage;\n"],"mappings":"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"}
1
+ {"version":3,"file":"DataParsersPage.js","names":[],"sources":["../../../src/bigconsole/pages/DataParsersPage.tsx"],"sourcesContent":["/**\n * Data Parsers Page\n *\n * Page for listing and managing parsers with filtering and search.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeConfirm, nativeImpact, nativeNotify } from '../../utils/nativeBridge';\nimport { useParserStore } from '../store/parserStore';\nimport { useParserOperations } from '../hooks/useParserOperations';\nimport { useExportParser } from '../hooks/useExportParser';\nimport { ParserCard } from '../components/parser/ParserCard';\nimport { ImportParserDialog } from '../components/parser/ImportParserDialog';\nimport type { Parser, ParserType, ParserStatus } from '../types';\n\n// fe-libs UI 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 { Plus, Search, AlertCircle, FileCode2, X, Upload } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ninterface ParserFilterOption<T> {\n value: T | 'all';\n label: string;\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst TYPE_OPTIONS: ParserFilterOption<ParserType>[] = [\n { value: 'all', label: 'All Types' },\n { value: 'jq', label: 'JQ' },\n { value: 'jsonata', label: 'JSONata' },\n];\n\nconst STATUS_OPTIONS: ParserFilterOption<ParserStatus>[] = [\n { value: 'all', label: 'All Status' },\n { value: 'active', label: 'Active' },\n { value: 'inactive', label: 'Inactive' },\n];\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\n// Default console ID for standalone parser listing\nconst DEFAULT_CONSOLE_ID = 'default';\n\nexport const DataParsersPage = memo(function DataParsersPage() {\n const navigate = useAppNavigate();\n const { consoleId: urlConsoleId } = useParams<{ consoleId?: string }>();\n\n // Use URL consoleId or fall back to default\n const consoleId = urlConsoleId || DEFAULT_CONSOLE_ID;\n\n // Store state\n const typeFilter = useParserStore((state) => state.typeFilter);\n const statusFilter = useParserStore((state) => state.statusFilter);\n const searchQuery = useParserStore((state) => state.searchQuery);\n const setTypeFilter = useParserStore((state) => state.setTypeFilter);\n const setStatusFilter = useParserStore((state) => state.setStatusFilter);\n const setSearchQuery = useParserStore((state) => state.setSearchQuery);\n\n // Local state\n const [isDeleting, setIsDeleting] = useState(false);\n const [deleteTargetId, setDeleteTargetId] = useState<string | null>(null);\n const [isImportDialogOpen, setIsImportDialogOpen] = useState(false);\n\n // Operations - use consoleId from URL or default\n const { loading, error, parsers, deleteParser, refetch } = useParserOperations({\n consoleId,\n skipFetch: false,\n });\n\n // Export hook\n const { downloadParser, loading: exportLoading } = useExportParser();\n\n // Filter parsers\n const filteredParsers = useMemo(() => {\n if (!parsers) return [];\n\n return parsers.filter((parser: Parser) => {\n if (typeFilter && parser.type !== typeFilter) {\n return false;\n }\n if (statusFilter && parser.status !== statusFilter) {\n return false;\n }\n if (searchQuery) {\n const query = searchQuery.toLowerCase();\n const nameMatch = parser.name?.toLowerCase().includes(query);\n const descMatch = parser.description?.toLowerCase().includes(query);\n const inputKeyMatch = parser.inputSinkKey?.toLowerCase().includes(query);\n const outputKeyMatch = parser.outputKey?.toLowerCase().includes(query);\n if (!nameMatch && !descMatch && !inputKeyMatch && !outputKeyMatch) {\n return false;\n }\n }\n return true;\n });\n }, [parsers, typeFilter, statusFilter, searchQuery]);\n\n // Handlers\n const handleTypeFilterChange = useCallback(\n (value: string) => {\n setTypeFilter(value === 'all' ? null : (value as ParserType));\n },\n [setTypeFilter]\n );\n\n const handleStatusFilterChange = useCallback(\n (value: string) => {\n setStatusFilter(value === 'all' ? null : (value as ParserStatus));\n },\n [setStatusFilter]\n );\n\n const handleSearchChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchQuery(e.target.value);\n },\n [setSearchQuery]\n );\n\n const handleCreateParser = useCallback(() => {\n // Navigate to dashboard-scoped parser creation if consoleId is provided\n if (urlConsoleId) {\n navigate(`/dashboards/${urlConsoleId}/parsers/new`);\n } else {\n navigate('/parsers/new');\n }\n }, [navigate, urlConsoleId]);\n\n const handleViewParser = useCallback(\n (id: string) => {\n // Navigate to dashboard-scoped parser view if consoleId is provided\n if (urlConsoleId) {\n navigate(`/dashboards/${urlConsoleId}/parsers/${id}`);\n } else {\n navigate(`/parsers/${id}`);\n }\n },\n [navigate, urlConsoleId]\n );\n\n const handleEditParser = useCallback(\n (id: string) => {\n // Navigate to dashboard-scoped parser edit if consoleId is provided\n if (urlConsoleId) {\n navigate(`/dashboards/${urlConsoleId}/parsers/${id}/edit`);\n } else {\n navigate(`/parsers/${id}/edit`);\n }\n },\n [navigate, urlConsoleId]\n );\n\n const handleDeleteParser = useCallback(\n async (id: string) => {\n const native = await nativeConfirm({\n title: 'Delete parser?',\n message: 'Are you sure you want to delete this parser?',\n okButtonTitle: 'Delete',\n cancelButtonTitle: 'Cancel',\n });\n const ok = native === null ? window.confirm('Are you sure you want to delete this parser?') : native;\n if (!ok) return;\n nativeImpact('medium');\n setIsDeleting(true);\n setDeleteTargetId(id);\n try {\n await deleteParser(id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n } finally {\n setIsDeleting(false);\n setDeleteTargetId(null);\n }\n },\n [deleteParser]\n );\n\n const handleClearFilters = useCallback(() => {\n setTypeFilter(null);\n setStatusFilter(null);\n setSearchQuery('');\n }, [setTypeFilter, setStatusFilter, setSearchQuery]);\n\n const handleExportParser = useCallback(\n async (id: string) => {\n const parser = parsers.find((p: Parser) => p.id === id);\n if (parser) {\n await downloadParser(id, parser.name);\n }\n },\n [parsers, downloadParser]\n );\n\n const handleImportParser = useCallback(() => {\n setIsImportDialogOpen(true);\n }, []);\n\n const handleImportSuccess = useCallback(\n (_parserId: string, _parserName: string, _wasUpdate: boolean) => {\n // Refetch parsers to show the newly imported one\n refetch();\n },\n [refetch]\n );\n\n const hasActiveFilters = typeFilter !== null || statusFilter !== null || (searchQuery?.length ?? 0) > 0;\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>\n <div\n style={{\n padding: 'var(--space-controlGap)',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <AlertCircle\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-status-error-text)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Failed to load Parsers\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()}>\n Try Again\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div className=\"relative overflow-hidden border-b border-border-seam bg-gloss-card\">\n <AuroraBackground intensity=\"subtle\" />\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <FileCode2\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n <GradientText>Data Parsers</GradientText>\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n Transform and process data with JQ or JSONata expressions\n </p>\n </div>\n </div>\n\n <CTAOverflowMenu\n primary={{\n label: 'Create Parser',\n onSelect: handleCreateParser,\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 actions={[\n {\n label: 'Import',\n onSelect: handleImportParser,\n icon: <Upload style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />,\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 Parsers define how raw input — log lines, CSVs, JSON, or arbitrary text — is read and mapped into structured\n fields. Build a parser once, test it against a sample, then reuse it across pipelines so every source lands in\n a consistent, queryable shape.\n </PagePurpose>\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', flex: 1 }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder=\"Search parsers...\"\n value={searchQuery || ''}\n onChange={handleSearchChange}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n\n {/* Type Filter */}\n <Select value={typeFilter || 'all'} onValueChange={handleTypeFilterChange}>\n <SelectTrigger style={{ width: '150px' }}>\n <SelectValue placeholder=\"All Types\" />\n </SelectTrigger>\n <SelectContent>\n {TYPE_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {/* Status Filter */}\n <Select value={statusFilter || 'all'} onValueChange={handleStatusFilterChange}>\n <SelectTrigger style={{ width: '150px' }}>\n <SelectValue placeholder=\"All Status\" />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\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 Clear Filters\n </Button>\n )}\n\n {/* Results Count */}\n <Badge variant=\"secondary\" style={{ marginLeft: 'auto' }}>\n {filteredParsers.length} {filteredParsers.length === 1 ? 'Parser' : 'Parsers'}\n </Badge>\n </div>\n\n {/* Loading state */}\n {loading && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n Loading parsers...\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && filteredParsers.length === 0 && !hasActiveFilters && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No Parsers yet\"\n description=\"Create your first parser to start transforming data with JQ or JSONata.\"\n action={\n <Button onClick={handleCreateParser}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Create Parser\n </Button>\n }\n />\n </GlassCard>\n )}\n\n {/* No results state */}\n {!loading && filteredParsers.length === 0 && hasActiveFilters && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching parsers\"\n description=\"No parsers match your filters\"\n action={\n <Button variant=\"ghost\" size=\"sm\" onClick={handleClearFilters}>\n Clear Filters\n </Button>\n }\n />\n </GlassCard>\n )}\n\n {/* Parser Grid */}\n {!loading && filteredParsers.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredParsers.map((parser: Parser) => (\n <ParserCard\n key={parser.id}\n parser={parser}\n onView={handleViewParser}\n onEdit={handleEditParser}\n onExport={handleExportParser}\n onDelete={handleDeleteParser}\n isDeleting={isDeleting && deleteTargetId === parser.id}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Import Parser Dialog */}\n <ImportParserDialog\n isOpen={isImportDialogOpen}\n onClose={() => setIsImportDialogOpen(false)}\n consoleId={consoleId}\n onSuccess={handleImportSuccess}\n />\n </div>\n );\n});\n\nexport default DataParsersPage;\n"],"mappings":"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"}