@burdenoff/microfe-bigconsole 2026.804.2 → 2026.805.2
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/AdminRoot.js +21 -16
- package/dist/bigconsole/AdminRoot.js.map +1 -1
- package/dist/bigconsole/BigConsoleRoot.js +44 -39
- package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +115 -100
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +164 -161
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +216 -49
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +96 -90
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +113 -104
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +208 -199
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +376 -325
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +135 -125
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +182 -172
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +233 -198
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +281 -268
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +238 -223
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +162 -144
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +212 -204
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +191 -183
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +128 -103
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +238 -217
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +116 -102
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/utils/csv.js +91 -0
- package/dist/bigconsole/utils/csv.js.map +1 -0
- package/dist/constants/permissions.js +83 -0
- package/dist/constants/permissions.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkflowsPage.js","names":[],"sources":["../../../src/bigconsole/pages/WorkflowsPage.tsx"],"sourcesContent":["/**\n * Workflows Page\n *\n * List and manage FluidGrids Workflows.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { newWorkflowPath } from '../BigConsoleRoutes';\nimport { useWorkflowOperations } from '../hooks/useWorkflowOperations';\nimport { useWorkflowStore } from '../store/workflowStore';\nimport { WorkflowCard } from '../components/workflow/WorkflowCard';\nimport { WorkflowDeleteDialog } from '../components/workflow/WorkflowDeleteDialog';\nimport type { FluidGridsWorkflowStatus } from '../types';\n\n// fe-libs UI components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { AuroraBackground, GradientText, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport { Plus, Search, Workflow, AlertCircle } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ntype StatusFilter = 'all' | FluidGridsWorkflowStatus;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowsPage = memo(function WorkflowsPage() {\n const navigate = useAppNavigate();\n\n // Local state\n const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');\n\n // Store state\n const searchQuery = useWorkflowStore((state) => state.searchQuery);\n const setSearchQuery = useWorkflowStore((state) => state.setSearchQuery);\n const deleteDialogOpen = useWorkflowStore((state) => state.deleteDialogOpen);\n const currentWorkflow = useWorkflowStore((state) => state.currentWorkflow);\n const openDeleteDialog = useWorkflowStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = useWorkflowStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, workflows, deleteWorkflow, refetch } = useWorkflowOperations();\n\n // Filter workflows\n const filteredWorkflows = useMemo(() => {\n let filtered = [...workflows];\n\n // Apply status filter\n if (statusFilter !== 'all') {\n filtered = filtered.filter((wf) => wf.status === statusFilter);\n }\n\n // Apply search filter\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (wf) =>\n wf.name.toLowerCase().includes(query) ||\n wf.key.toLowerCase().includes(query) ||\n wf.description?.toLowerCase().includes(query)\n );\n }\n\n // Sort by updatedAt descending\n return filtered.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n }, [workflows, statusFilter, searchQuery]);\n\n // Handlers\n const handleCreateWorkflow = useCallback(() => {\n navigate(newWorkflowPath());\n }, [navigate]);\n\n const handleViewWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}`);\n },\n [navigate]\n );\n\n const handleEditWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}/edit`);\n },\n [navigate]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const workflow = workflows.find((wf) => wf.id === id);\n if (workflow) {\n openDeleteDialog(workflow);\n }\n },\n [workflows, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentWorkflow) {\n try {\n await deleteWorkflow(currentWorkflow.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentWorkflow, deleteWorkflow, closeDeleteDialog]);\n\n // Status filter options\n const statusOptions: { value: StatusFilter; label: string }[] = [\n { value: 'all', label: 'All' },\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'paused', label: 'Paused' },\n { value: 'error', label: 'Error' },\n { value: 'archived', label: 'Archived' },\n ];\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>\n <div\n style={{\n padding: 'var(--space-controlGap)',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <AlertCircle\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-status-error-text)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Failed to load Workflows\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()}>\n Try Again\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div className=\"relative overflow-hidden border-b border-border-seam bg-gloss-card\">\n <AuroraBackground intensity=\"subtle\" />\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <Workflow\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n <GradientText>Workflows</GradientText>\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n Design ETL workflows with FluidGrids and link them to DataSinks\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Design Workflow\n </Button>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <PagePurpose className=\"mb-[var(--space-sectionGap)]\">\n Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems,\n transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep\n dashboards fed with fresh, shaped data without writing glue code.\n </PagePurpose>\n\n {/* Status Filter Tabs */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '2px',\n padding: '4px',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-card)',\n width: 'fit-content',\n }}\n >\n {statusOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => setStatusFilter(option.value)}\n style={{\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n backgroundColor: statusFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color: statusFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: statusFilter === option.value ? '0 1px 2px rgba(0,0,0,0.05)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Search Bar */}\n <div style={{ marginBottom: 'var(--space-sectionGap)' }}>\n <div style={{ position: 'relative', maxWidth: '400px' }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder=\"Search workflows...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n\n {/* Loading state */}\n {loading && workflows.length === 0 && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n Loading workflows...\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && workflows.length === 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No Workflows yet\"\n description=\"Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks.\"\n action={\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Design Workflow\n </Button>\n }\n />\n </GlassCard>\n )}\n\n {/* No results state */}\n {!loading && filteredWorkflows.length === 0 && workflows.length > 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching workflows\"\n description=\"No workflows match your filters\"\n />\n </GlassCard>\n )}\n\n {/* Workflow Grid */}\n {filteredWorkflows.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredWorkflows.map((workflow) => (\n <WorkflowCard\n key={workflow.id}\n workflow={workflow}\n onView={handleViewWorkflow}\n onEdit={handleEditWorkflow}\n onDelete={handleDeleteClick}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Delete Dialog */}\n {currentWorkflow && (\n <WorkflowDeleteDialog\n workflow={currentWorkflow}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default WorkflowsPage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkflowsPage.js","names":[],"sources":["../../../src/bigconsole/pages/WorkflowsPage.tsx"],"sourcesContent":["/**\n * Workflows Page\n *\n * List and manage FluidGrids Workflows.\n * Uses fe-libs shared UI components and semantic tokens for consistent styling.\n */\n\nimport { memo, useState, useMemo, useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { AccessDenied, PermissionButton } from '@burdenoff/fe-libs/shared/components';\nimport { BIGCONSOLE_PERMISSIONS } from '../../constants/permissions';\nimport { useAppNavigate } from '../contexts';\nimport { isNative, nativeNotify } from '../../utils/nativeBridge';\nimport { newWorkflowPath } from '../BigConsoleRoutes';\nimport { useWorkflowOperations } from '../hooks/useWorkflowOperations';\nimport { useWorkflowStore } from '../store/workflowStore';\nimport { WorkflowCard } from '../components/workflow/WorkflowCard';\nimport { WorkflowDeleteDialog } from '../components/workflow/WorkflowDeleteDialog';\nimport type { FluidGridsWorkflowStatus } from '../types';\n\n// fe-libs UI components\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { AuroraBackground, GradientText, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\n// Lucide icons\nimport { Plus, Search, Workflow, AlertCircle } from 'lucide-react';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\ntype StatusFilter = 'all' | FluidGridsWorkflowStatus;\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport const WorkflowsPage = memo(function WorkflowsPage() {\n const navigate = useAppNavigate();\n\n // RBAC permissions\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n const canRead = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_READ);\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_UPDATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.WORKFLOW_DELETE);\n\n // Local state\n const [statusFilter, setStatusFilter] = useState<StatusFilter>('all');\n\n // Store state\n const searchQuery = useWorkflowStore((state) => state.searchQuery);\n const setSearchQuery = useWorkflowStore((state) => state.setSearchQuery);\n const deleteDialogOpen = useWorkflowStore((state) => state.deleteDialogOpen);\n const currentWorkflow = useWorkflowStore((state) => state.currentWorkflow);\n const openDeleteDialog = useWorkflowStore((state) => state.openDeleteDialog);\n const closeDeleteDialog = useWorkflowStore((state) => state.closeDeleteDialog);\n\n // Operations\n const { loading, error, workflows, deleteWorkflow, refetch } = useWorkflowOperations();\n\n // Filter workflows\n const filteredWorkflows = useMemo(() => {\n let filtered = [...workflows];\n\n // Apply status filter\n if (statusFilter !== 'all') {\n filtered = filtered.filter((wf) => wf.status === statusFilter);\n }\n\n // Apply search filter\n if (searchQuery.trim()) {\n const query = searchQuery.toLowerCase();\n filtered = filtered.filter(\n (wf) =>\n wf.name.toLowerCase().includes(query) ||\n wf.key.toLowerCase().includes(query) ||\n wf.description?.toLowerCase().includes(query)\n );\n }\n\n // Sort by updatedAt descending\n return filtered.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n }, [workflows, statusFilter, searchQuery]);\n\n // Handlers\n const handleCreateWorkflow = useCallback(() => {\n navigate(newWorkflowPath());\n }, [navigate]);\n\n const handleViewWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}`);\n },\n [navigate]\n );\n\n const handleEditWorkflow = useCallback(\n (id: string) => {\n navigate(`/workflows/${id}/edit`);\n },\n [navigate]\n );\n\n const handleDeleteClick = useCallback(\n (id: string) => {\n const workflow = workflows.find((wf) => wf.id === id);\n if (workflow) {\n openDeleteDialog(workflow);\n }\n },\n [workflows, openDeleteDialog]\n );\n\n const handleDeleteConfirm = useCallback(async () => {\n if (currentWorkflow) {\n try {\n await deleteWorkflow(currentWorkflow.id);\n if (isNative()) void nativeNotify('success');\n } catch (err) {\n if (isNative()) void nativeNotify('error');\n throw err;\n }\n closeDeleteDialog();\n }\n }, [currentWorkflow, deleteWorkflow, closeDeleteDialog]);\n\n // Status filter options\n const statusOptions: { value: StatusFilter; label: string }[] = [\n { value: 'all', label: 'All' },\n { value: 'draft', label: 'Draft' },\n { value: 'active', label: 'Active' },\n { value: 'paused', label: 'Paused' },\n { value: 'error', label: 'Error' },\n { value: 'archived', label: 'Archived' },\n ];\n\n // Page-level read gate — only after permissions have finished loading so we\n // don't flash Access Denied while the permission set is still being fetched.\n if (!permissionsLoading && !canRead) {\n return <AccessDenied title=\"Access Denied\" description=\"You don't have permission to view workflows.\" />;\n }\n\n // Error state\n if (error) {\n return (\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <Card\n style={{\n borderColor: 'var(--color-status-error-border)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n }}\n >\n <CardContent style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center' }}>\n <div\n style={{\n padding: 'var(--space-controlGap)',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n <AlertCircle\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n color: 'var(--color-status-error-text)',\n }}\n />\n </div>\n <h3\n style={{\n fontSize: 'var(--font-size-body-lg)',\n fontWeight: 'var(--font-weight-medium)',\n color: 'var(--color-status-error-text)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Failed to load Workflows\n </h3>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n marginBottom: 'var(--space-formGap)',\n }}\n >\n {error.message}\n </p>\n <Button size=\"sm\" onClick={() => refetch()}>\n Try Again\n </Button>\n </div>\n </CardContent>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{ minHeight: '100vh', backgroundColor: 'var(--color-bg-canvas)' }}>\n {/* Header Section */}\n <div className=\"relative overflow-hidden border-b border-border-seam bg-gloss-card\">\n <AuroraBackground intensity=\"subtle\" />\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n }}\n >\n <Workflow\n style={{\n height: 'var(--size-icon-lg)',\n width: 'var(--size-icon-lg)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div>\n <h1\n style={{\n fontSize: 'var(--font-size-heading-h4)',\n fontWeight: 'var(--font-weight-bold)',\n margin: 0,\n color: 'var(--color-text-primary)',\n }}\n >\n <GradientText>Workflows</GradientText>\n </h1>\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-secondary)', margin: 0 }}>\n Design ETL workflows with FluidGrids and link them to DataSinks\n </p>\n </div>\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Design Workflow\n </Button>\n </PermissionButton>\n </div>\n </div>\n </div>\n </div>\n\n {/* Main Content */}\n <div style={{ padding: 'var(--space-pagePadding)' }}>\n <PagePurpose className=\"mb-[var(--space-sectionGap)]\">\n Workflows are visual ETL jobs built with the FluidGrids builder — they fetch data from external systems,\n transform it, and load it into your BigConsole DataSinks on a schedule or on demand. Use them to keep\n dashboards fed with fresh, shaped data without writing glue code.\n </PagePurpose>\n\n {/* Status Filter Tabs */}\n <div style={{ marginBottom: 'var(--space-formGap)' }}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '2px',\n padding: '4px',\n backgroundColor: 'var(--color-bg-sunken)',\n borderRadius: 'var(--radius-card)',\n width: 'fit-content',\n }}\n >\n {statusOptions.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => setStatusFilter(option.value)}\n style={{\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n borderRadius: 'var(--radius-button)',\n border: 'none',\n cursor: 'pointer',\n transition: 'all 0.2s ease',\n backgroundColor: statusFilter === option.value ? 'var(--color-bg-surface)' : 'transparent',\n color: statusFilter === option.value ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',\n boxShadow: statusFilter === option.value ? '0 1px 2px rgba(0,0,0,0.05)' : 'none',\n }}\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>\n\n {/* Search Bar */}\n <div style={{ marginBottom: 'var(--space-sectionGap)' }}>\n <div style={{ position: 'relative', maxWidth: '400px' }}>\n <Search\n style={{\n position: 'absolute',\n left: 'var(--space-controlGap)',\n top: '50%',\n transform: 'translateY(-50%)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-text-muted)',\n }}\n />\n <Input\n type=\"text\"\n placeholder=\"Search workflows...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={{ paddingLeft: 'var(--size-controlHeight-md)', height: 'var(--size-controlHeight-md)' }}\n />\n </div>\n </div>\n\n {/* Loading state */}\n {loading && workflows.length === 0 && (\n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '80px 0' }}>\n <div style={{ textAlign: 'center' }}>\n <Spinner\n style={{\n height: 'var(--size-icon-xl)',\n width: 'var(--size-icon-xl)',\n margin: '0 auto var(--space-formGap)',\n }}\n />\n <p style={{ fontSize: 'var(--font-size-body-sm)', color: 'var(--color-text-muted)' }}>\n Loading workflows...\n </p>\n </div>\n </div>\n )}\n\n {/* Empty state */}\n {!loading && workflows.length === 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No Workflows yet\"\n description=\"Design ETL workflows with the FluidGrids visual builder to fetch, transform, and deliver data into BigConsole DataSinks.\"\n action={\n <PermissionButton permission={BIGCONSOLE_PERMISSIONS.WORKFLOW_CREATE} deniedBehavior=\"disable\">\n <Button onClick={handleCreateWorkflow}>\n <Plus\n style={{\n marginRight: 'var(--space-iconGap)',\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n }}\n />\n Design Workflow\n </Button>\n </PermissionButton>\n }\n />\n </GlassCard>\n )}\n\n {/* No results state */}\n {!loading && filteredWorkflows.length === 0 && workflows.length > 0 && (\n <GlassCard treatment=\"insight\" className=\"border-border-seam\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No matching workflows\"\n description=\"No workflows match your filters\"\n />\n </GlassCard>\n )}\n\n {/* Workflow Grid */}\n {filteredWorkflows.length > 0 && (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(320px, 1fr))',\n gap: 'var(--space-formGap)',\n }}\n >\n {filteredWorkflows.map((workflow) => (\n <WorkflowCard\n key={workflow.id}\n workflow={workflow}\n onView={handleViewWorkflow}\n onEdit={canUpdate ? handleEditWorkflow : undefined}\n onDelete={canDelete ? handleDeleteClick : undefined}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Delete Dialog */}\n {currentWorkflow && (\n <WorkflowDeleteDialog\n workflow={currentWorkflow}\n isOpen={deleteDialogOpen}\n onClose={closeDeleteDialog}\n onConfirm={handleDeleteConfirm}\n />\n )}\n </div>\n );\n});\n\nexport default WorkflowsPage;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//#region src/bigconsole/utils/csv.ts
|
|
2
|
+
var e = "CSV could not be parsed: an opening quote is never closed.";
|
|
3
|
+
function t(t, n) {
|
|
4
|
+
let r = [], i = "", a = [], o = !1, s = 0, c = t.length, l = () => {
|
|
5
|
+
a.push(i), i = "";
|
|
6
|
+
}, u = () => {
|
|
7
|
+
l(), r.push(a), a = [];
|
|
8
|
+
};
|
|
9
|
+
for (; s < c;) {
|
|
10
|
+
let e = t[s];
|
|
11
|
+
if (o) {
|
|
12
|
+
if (e === "\"") {
|
|
13
|
+
if (t[s + 1] === "\"") {
|
|
14
|
+
i += "\"", s += 2;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
o = !1, s += 1;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
i += e, s += 1;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (e === "\"") {
|
|
24
|
+
i === "" ? o = !0 : i += e, s += 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (e === n) {
|
|
28
|
+
l(), s += 1;
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (e === "\r") {
|
|
32
|
+
t[s + 1] === "\n" && (s += 1), u(), s += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (e === "\n") {
|
|
36
|
+
u(), s += 1;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
i += e, s += 1;
|
|
40
|
+
}
|
|
41
|
+
if (o) throw Error(e);
|
|
42
|
+
return u(), r;
|
|
43
|
+
}
|
|
44
|
+
function n(e) {
|
|
45
|
+
return e.length <= 1 && (e[0] ?? "").trim() === "";
|
|
46
|
+
}
|
|
47
|
+
function r(e) {
|
|
48
|
+
let t = e.trim();
|
|
49
|
+
if (t === "") return null;
|
|
50
|
+
let n = t.toLowerCase();
|
|
51
|
+
if (n === "true") return !0;
|
|
52
|
+
if (n === "false") return !1;
|
|
53
|
+
if (/^-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/.test(t) && !/^-?0\d/.test(t)) {
|
|
54
|
+
let e = Number(t);
|
|
55
|
+
if (Number.isFinite(e)) return Number.isInteger(e) && !Number.isSafeInteger(e) ? t : e;
|
|
56
|
+
}
|
|
57
|
+
return e;
|
|
58
|
+
}
|
|
59
|
+
function i(e) {
|
|
60
|
+
let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Map();
|
|
61
|
+
return e.map((e, r) => {
|
|
62
|
+
let i = e.trim() || `column_${r + 1}`;
|
|
63
|
+
if (!t.has(i)) return t.add(i), i;
|
|
64
|
+
let a = n.get(i) ?? 0, o;
|
|
65
|
+
do
|
|
66
|
+
a += 1, o = `${i}_${a}`;
|
|
67
|
+
while (t.has(o));
|
|
68
|
+
return n.set(i, a), t.add(o), o;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function a(e, a = {}) {
|
|
72
|
+
let o = a.delimiter ?? ",", s = e.charCodeAt(0) === 65279 ? e.slice(1) : e;
|
|
73
|
+
if (s.trim() === "") throw Error("CSV is empty — nothing to import.");
|
|
74
|
+
let c = t(s, o).filter((e) => !n(e));
|
|
75
|
+
if (c.length === 0) throw Error("CSV is empty — nothing to import.");
|
|
76
|
+
let l = i(c[0]), u = c.slice(1);
|
|
77
|
+
if (u.length === 0) throw Error("CSV has a header row but no data rows to import.");
|
|
78
|
+
return {
|
|
79
|
+
columns: l,
|
|
80
|
+
rows: u.map((e) => {
|
|
81
|
+
let t = Object.create(null);
|
|
82
|
+
return l.forEach((n, i) => {
|
|
83
|
+
t[n] = r(e[i] ?? "");
|
|
84
|
+
}), t;
|
|
85
|
+
})
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { a as parseCsv };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv.js","names":[],"sources":["../../../src/bigconsole/utils/csv.ts"],"sourcesContent":["/**\n * Dependency-free CSV parsing for direct DataSink imports.\n *\n * Parses RFC 4180-style CSV text (quoted fields, embedded delimiters/newlines,\n * escaped `\"\"` quotes, CRLF or LF line endings) into an array of row objects\n * keyed by the header row — the shape the DataSink table viewer and parsers\n * expect. Values are lightly type-inferred (numbers, booleans, empty → null).\n */\n\nexport type CsvValue = string | number | boolean | null;\n\nexport interface ParsedCsv {\n /** Column names taken from the header row, in order. */\n columns: string[];\n /** Data rows, each keyed by column name. */\n rows: Record<string, CsvValue>[];\n}\n\nexport interface ParseCsvOptions {\n /** Field delimiter. Defaults to \",\". */\n delimiter?: string;\n}\n\nconst UNTERMINATED_QUOTE_ERROR = 'CSV could not be parsed: an opening quote is never closed.';\n\n/**\n * Tokenize CSV text into a matrix of raw string fields, honoring quotes so that\n * delimiters and line breaks inside quoted fields are preserved.\n */\nfunction tokenize(text: string, delimiter: string): string[][] {\n const rows: string[][] = [];\n let field = '';\n let row: string[] = [];\n let inQuotes = false;\n let i = 0;\n const n = text.length;\n\n const endField = (): void => {\n row.push(field);\n field = '';\n };\n const endRow = (): void => {\n endField();\n rows.push(row);\n row = [];\n };\n\n while (i < n) {\n const char = text[i];\n\n if (inQuotes) {\n if (char === '\"') {\n if (text[i + 1] === '\"') {\n // Escaped quote inside a quoted field.\n field += '\"';\n i += 2;\n continue;\n }\n inQuotes = false;\n i += 1;\n continue;\n }\n field += char;\n i += 1;\n continue;\n }\n\n if (char === '\"') {\n // A quote only opens a quoted field at the very start of a field. A quote\n // in the middle of an unquoted field (e.g. `John \"JD\" Doe`) is treated as\n // a literal character rather than silently toggling quote mode and\n // swallowing surrounding text — a common shape in real-world exports.\n if (field === '') {\n inQuotes = true;\n } else {\n field += char;\n }\n i += 1;\n continue;\n }\n if (char === delimiter) {\n endField();\n i += 1;\n continue;\n }\n if (char === '\\r') {\n // Treat CRLF as a single line break.\n if (text[i + 1] === '\\n') i += 1;\n endRow();\n i += 1;\n continue;\n }\n if (char === '\\n') {\n endRow();\n i += 1;\n continue;\n }\n\n field += char;\n i += 1;\n }\n\n if (inQuotes) {\n throw new Error(UNTERMINATED_QUOTE_ERROR);\n }\n\n // Flush the trailing field/row for files that do not end in a newline.\n endRow();\n\n return rows;\n}\n\n/**\n * True only for a genuinely blank line — one with no delimiters and no content\n * (e.g. a trailing empty line). A row that bears delimiters represents a real\n * record of empty values and is kept.\n */\nfunction isBlankLine(row: string[]): boolean {\n return row.length <= 1 && (row[0] ?? '').trim() === '';\n}\n\n/** Light type inference so numeric/boolean CSV values are usable in widgets. */\nexport function inferCsvValue(raw: string): CsvValue {\n const trimmed = raw.trim();\n if (trimmed === '') return null;\n\n const lower = trimmed.toLowerCase();\n if (lower === 'true') return true;\n if (lower === 'false') return false;\n\n // Only coerce to a number when the whole token is a finite numeric literal.\n // Preserve leading-zero tokens (ZIP codes, SKUs, zero-padded IDs like \"00123\"\n // or \"007\") as strings — coercing them to numbers is lossy and destructive.\n if (/^-?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?$/.test(trimmed) && !/^-?0\\d/.test(trimmed)) {\n const num = Number(trimmed);\n if (Number.isFinite(num)) {\n // Keep integer-valued literals beyond 2^53-1 as strings — coercing long\n // IDs / account numbers (e.g. 9007199254740993, or the same value exported\n // as 9007199254740993.0 / ...e0) would silently round them. Return the\n // trimmed token for consistency with the other coercion paths.\n if (Number.isInteger(num) && !Number.isSafeInteger(num)) return trimmed;\n return num;\n }\n }\n\n // Free-text values return the original cell verbatim (untrimmed): unlike\n // numeric/boolean tokens, surrounding whitespace in a string can be\n // meaningful data and is not ours to strip.\n return raw;\n}\n\n/** Ensure column names are non-empty and unique. */\nfunction normalizeColumns(header: string[]): string[] {\n const used = new Set<string>();\n const counters = new Map<string, number>();\n return header.map((raw, index) => {\n const base = raw.trim() || `column_${index + 1}`;\n if (!used.has(base)) {\n used.add(base);\n return base;\n }\n // Advance the suffix until the generated name is genuinely unique — a bare\n // `${base}_${n}` can collide with a literal header of the same text\n // (e.g. \"name\",\"name\",\"name_1\"), which would silently drop a column.\n let n = counters.get(base) ?? 0;\n let candidate: string;\n do {\n n += 1;\n candidate = `${base}_${n}`;\n } while (used.has(candidate));\n counters.set(base, n);\n used.add(candidate);\n return candidate;\n });\n}\n\n/**\n * Parse CSV text into columns + typed row objects.\n *\n * @throws Error when the input is empty or has a header but no data rows.\n */\nexport function parseCsv(text: string, options: ParseCsvOptions = {}): ParsedCsv {\n const delimiter = options.delimiter ?? ',';\n\n // Strip a UTF-8 BOM if present (common in spreadsheet exports).\n const clean = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n\n if (clean.trim() === '') {\n throw new Error('CSV is empty — nothing to import.');\n }\n\n const matrix = tokenize(clean, delimiter).filter((row) => !isBlankLine(row));\n\n if (matrix.length === 0) {\n throw new Error('CSV is empty — nothing to import.');\n }\n\n const columns = normalizeColumns(matrix[0]);\n const dataRows = matrix.slice(1);\n\n if (dataRows.length === 0) {\n throw new Error('CSV has a header row but no data rows to import.');\n }\n\n const rows = dataRows.map((cells) => {\n // Null-prototype map so user-controlled header keys (e.g. \"__proto__\",\n // \"constructor\") become own properties instead of hitting Object.prototype\n // setters and silently dropping the column.\n const record = Object.create(null) as Record<string, CsvValue>;\n columns.forEach((col, index) => {\n record[col] = inferCsvValue(cells[index] ?? '');\n });\n return record;\n });\n\n return { columns, rows };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/constants/permissions.ts
|
|
2
|
+
var e = {
|
|
3
|
+
DASHBOARD_READ: "bigconsole-dashboard:read",
|
|
4
|
+
DASHBOARD_CREATE: "bigconsole-dashboard:create",
|
|
5
|
+
DASHBOARD_UPDATE: "bigconsole-dashboard:update",
|
|
6
|
+
DASHBOARD_DELETE: "bigconsole-dashboard:delete",
|
|
7
|
+
DASHBOARD_EXPORT: "bigconsole-dashboard:export",
|
|
8
|
+
DASHBOARD_IMPORT: "bigconsole-dashboard:import",
|
|
9
|
+
DASHBOARD_PUBLISH: "bigconsole-dashboard:publish",
|
|
10
|
+
DASHBOARD_SHARE: "bigconsole-dashboard:share",
|
|
11
|
+
DASHBOARD_MANAGE_EMBED: "bigconsole-dashboard:manage_embed",
|
|
12
|
+
DASHBOARD_PAGE_CREATE: "bigconsole-dashboard-page:create",
|
|
13
|
+
DASHBOARD_PAGE_UPDATE: "bigconsole-dashboard-page:update",
|
|
14
|
+
DASHBOARD_PAGE_DELETE: "bigconsole-dashboard-page:delete",
|
|
15
|
+
FILTER_CREATE: "bigconsole-filter:create",
|
|
16
|
+
FILTER_UPDATE: "bigconsole-filter:update",
|
|
17
|
+
FILTER_DELETE: "bigconsole-filter:delete",
|
|
18
|
+
FILTER_PRESET_READ: "bigconsole-filter-preset:read",
|
|
19
|
+
FILTER_PRESET_CREATE: "bigconsole-filter-preset:create",
|
|
20
|
+
FILTER_PRESET_UPDATE: "bigconsole-filter-preset:update",
|
|
21
|
+
FILTER_PRESET_DELETE: "bigconsole-filter-preset:delete",
|
|
22
|
+
RLS_POLICY_READ: "bigconsole-rls-policy:read",
|
|
23
|
+
RLS_POLICY_CREATE: "bigconsole-rls-policy:create",
|
|
24
|
+
RLS_POLICY_UPDATE: "bigconsole-rls-policy:update",
|
|
25
|
+
RLS_POLICY_DELETE: "bigconsole-rls-policy:delete",
|
|
26
|
+
SHARE_READ: "bigconsole-share:read",
|
|
27
|
+
TEMPLATE_READ: "bigconsole-template:read",
|
|
28
|
+
TEMPLATE_CREATE: "bigconsole-template:create",
|
|
29
|
+
TEMPLATE_UPDATE: "bigconsole-template:update",
|
|
30
|
+
TEMPLATE_DELETE: "bigconsole-template:delete",
|
|
31
|
+
TEMPLATE_PUBLISH: "bigconsole-template:publish",
|
|
32
|
+
VIEW_READ: "bigconsole-view:read",
|
|
33
|
+
VIEW_CREATE: "bigconsole-view:create",
|
|
34
|
+
VIEW_UPDATE: "bigconsole-view:update",
|
|
35
|
+
VIEW_DELETE: "bigconsole-view:delete",
|
|
36
|
+
DATASINK_READ: "bigconsole-datasink:read",
|
|
37
|
+
DATASINK_CREATE: "bigconsole-datasink:create",
|
|
38
|
+
DATASINK_UPDATE: "bigconsole-datasink:update",
|
|
39
|
+
DATASINK_DELETE: "bigconsole-datasink:delete",
|
|
40
|
+
DATASINK_EXECUTE: "bigconsole-datasink:execute",
|
|
41
|
+
DATASINK_MANAGE: "bigconsole-datasink:manage",
|
|
42
|
+
PARSER_READ: "bigconsole-parser:read",
|
|
43
|
+
PARSER_CREATE: "bigconsole-parser:create",
|
|
44
|
+
PARSER_UPDATE: "bigconsole-parser:update",
|
|
45
|
+
PARSER_DELETE: "bigconsole-parser:delete",
|
|
46
|
+
PARSER_EXECUTE: "bigconsole-parser:execute",
|
|
47
|
+
PARSER_TEST: "bigconsole-parser:test",
|
|
48
|
+
PIPELINE_READ: "bigconsole-pipeline:read",
|
|
49
|
+
PIPELINE_CREATE: "bigconsole-pipeline:create",
|
|
50
|
+
PIPELINE_UPDATE: "bigconsole-pipeline:update",
|
|
51
|
+
PIPELINE_DELETE: "bigconsole-pipeline:delete",
|
|
52
|
+
PIPELINE_EXECUTE: "bigconsole-pipeline:execute",
|
|
53
|
+
PIPELINE_TEST: "bigconsole-pipeline:test",
|
|
54
|
+
PROMPT_READ: "bigconsole-prompt:read",
|
|
55
|
+
PROMPT_CREATE: "bigconsole-prompt:create",
|
|
56
|
+
PROMPT_UPDATE: "bigconsole-prompt:update",
|
|
57
|
+
PROMPT_DELETE: "bigconsole-prompt:delete",
|
|
58
|
+
WORKFLOW_READ: "bigconsole-workflow:read",
|
|
59
|
+
WORKFLOW_CREATE: "bigconsole-workflow:create",
|
|
60
|
+
WORKFLOW_UPDATE: "bigconsole-workflow:update",
|
|
61
|
+
WORKFLOW_DELETE: "bigconsole-workflow:delete",
|
|
62
|
+
WORKFLOW_EXECUTE: "bigconsole-workflow:execute",
|
|
63
|
+
WIDGET_READ: "bigconsole-widget:read",
|
|
64
|
+
WIDGET_CREATE: "bigconsole-widget:create",
|
|
65
|
+
WIDGET_UPDATE: "bigconsole-widget:update",
|
|
66
|
+
WIDGET_DELETE: "bigconsole-widget:delete",
|
|
67
|
+
WIDGET_ACTION_READ: "bigconsole-widget-action:read",
|
|
68
|
+
WIDGET_ACTION_CREATE: "bigconsole-widget-action:create",
|
|
69
|
+
WIDGET_ACTION_UPDATE: "bigconsole-widget-action:update",
|
|
70
|
+
WIDGET_ACTION_DELETE: "bigconsole-widget-action:delete",
|
|
71
|
+
WIDGET_ACTION_EXECUTE: "bigconsole-widget-action:execute",
|
|
72
|
+
EVENT_LOG_READ: "bigconsole-event-log:read",
|
|
73
|
+
EVENT_LOG_EXECUTE: "bigconsole-event-log:execute",
|
|
74
|
+
WEBHOOK_READ: "bigconsole-webhook:read",
|
|
75
|
+
WEBHOOK_CREATE: "bigconsole-webhook:create",
|
|
76
|
+
WEBHOOK_UPDATE: "bigconsole-webhook:update",
|
|
77
|
+
WEBHOOK_DELETE: "bigconsole-webhook:delete",
|
|
78
|
+
WEBHOOK_TEST: "bigconsole-webhook:test"
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { e as BIGCONSOLE_PERMISSIONS };
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","names":[],"sources":["../../src/constants/permissions.ts"],"sourcesContent":["/**\n * BigConsole Permission Constants\n *\n * All permission strings for BigConsole resources.\n * Use with fe-libs usePermissions hook:\n * hasPermission(BIGCONSOLE_PERMISSIONS.DASHBOARD_CREATE)\n *\n * IMPORTANT — only strings present in the wspace-rbac-svc seed\n * (`prisma/seed-unified-rbac.ts` ACTION_DEFINITIONS, `// BIGCONSOLE MODULE`\n * section) are ever returned by `myPermissions` / `hasPermission`. Gating on a\n * string the seed does NOT define makes `hasPermission` return false for\n * EVERYONE → a full lockout. Every constant below is verified against the seed\n * as of 2026-08-05.\n *\n * NOTE ON `list` — the BigConsole backend has NO `*:list` action. Every list\n * query (`listDashboards`, `listDataSinks`, …) is gated by the resource's\n * `read` action via its `@rbac` directive. Therefore list pages MUST gate on\n * `<resource>:read`, NOT a `:list` string (which is unseeded → lockout).\n *\n * Resource types (17) and their seeded actions:\n * - bigconsole-dashboard: read, create, update, delete, export, import, publish, share, manage_embed\n * - bigconsole-dashboard-page: create, update, delete\n * - bigconsole-filter: create, update, delete\n * - bigconsole-filter-preset: read, create, update, delete\n * - bigconsole-rls-policy: read, create, update, delete\n * - bigconsole-share: read\n * - bigconsole-template: read, create, update, delete, publish\n * - bigconsole-view: read, create, update, delete\n * - bigconsole-datasink: read, create, update, delete, execute, manage\n * - bigconsole-parser: read, create, update, delete, execute, test\n * - bigconsole-pipeline: read, create, update, delete, execute, test\n * - bigconsole-prompt: read, create, update, delete\n * - bigconsole-workflow: read, create, update, delete, execute\n * - bigconsole-widget: read, create, update, delete\n * - bigconsole-widget-action: read, create, update, delete, execute\n * - bigconsole-event-log: read, execute\n * - bigconsole-webhook: read, create, update, delete, test\n */\n\nexport const BIGCONSOLE_PERMISSIONS = {\n // Dashboard resources\n DASHBOARD_READ: 'bigconsole-dashboard:read',\n DASHBOARD_CREATE: 'bigconsole-dashboard:create',\n DASHBOARD_UPDATE: 'bigconsole-dashboard:update',\n DASHBOARD_DELETE: 'bigconsole-dashboard:delete',\n DASHBOARD_EXPORT: 'bigconsole-dashboard:export',\n DASHBOARD_IMPORT: 'bigconsole-dashboard:import',\n DASHBOARD_PUBLISH: 'bigconsole-dashboard:publish',\n DASHBOARD_SHARE: 'bigconsole-dashboard:share',\n // Embed policy CRUD (`manage_embed` on all embed.gql operations)\n DASHBOARD_MANAGE_EMBED: 'bigconsole-dashboard:manage_embed',\n\n // Dashboard page (sub-resource) resources\n DASHBOARD_PAGE_CREATE: 'bigconsole-dashboard-page:create',\n DASHBOARD_PAGE_UPDATE: 'bigconsole-dashboard-page:update',\n DASHBOARD_PAGE_DELETE: 'bigconsole-dashboard-page:delete',\n\n // Global filter resources\n FILTER_CREATE: 'bigconsole-filter:create',\n FILTER_UPDATE: 'bigconsole-filter:update',\n FILTER_DELETE: 'bigconsole-filter:delete',\n\n // Filter preset resources\n FILTER_PRESET_READ: 'bigconsole-filter-preset:read',\n FILTER_PRESET_CREATE: 'bigconsole-filter-preset:create',\n FILTER_PRESET_UPDATE: 'bigconsole-filter-preset:update',\n FILTER_PRESET_DELETE: 'bigconsole-filter-preset:delete',\n\n // Row-level-security policy resources\n RLS_POLICY_READ: 'bigconsole-rls-policy:read',\n RLS_POLICY_CREATE: 'bigconsole-rls-policy:create',\n RLS_POLICY_UPDATE: 'bigconsole-rls-policy:update',\n RLS_POLICY_DELETE: 'bigconsole-rls-policy:delete',\n\n // Dashboard share resources (read-only surface; share mutations enforce\n // `bigconsole-dashboard:share`, see DASHBOARD_SHARE)\n SHARE_READ: 'bigconsole-share:read',\n\n // Template resources\n TEMPLATE_READ: 'bigconsole-template:read',\n TEMPLATE_CREATE: 'bigconsole-template:create',\n TEMPLATE_UPDATE: 'bigconsole-template:update',\n TEMPLATE_DELETE: 'bigconsole-template:delete',\n TEMPLATE_PUBLISH: 'bigconsole-template:publish',\n\n // Dashboard view resources\n VIEW_READ: 'bigconsole-view:read',\n VIEW_CREATE: 'bigconsole-view:create',\n VIEW_UPDATE: 'bigconsole-view:update',\n VIEW_DELETE: 'bigconsole-view:delete',\n\n // DataSink resources\n DATASINK_READ: 'bigconsole-datasink:read',\n DATASINK_CREATE: 'bigconsole-datasink:create',\n DATASINK_UPDATE: 'bigconsole-datasink:update',\n DATASINK_DELETE: 'bigconsole-datasink:delete',\n // `refreshDataSink` enforces `execute`\n DATASINK_EXECUTE: 'bigconsole-datasink:execute',\n // `invalidateDataSinkCache` enforces `manage`\n DATASINK_MANAGE: 'bigconsole-datasink:manage',\n\n // Parser resources\n PARSER_READ: 'bigconsole-parser:read',\n PARSER_CREATE: 'bigconsole-parser:create',\n PARSER_UPDATE: 'bigconsole-parser:update',\n PARSER_DELETE: 'bigconsole-parser:delete',\n // `executeParser` enforces `execute`\n PARSER_EXECUTE: 'bigconsole-parser:execute',\n // `testParserExpression` enforces `test`\n PARSER_TEST: 'bigconsole-parser:test',\n\n // Pipeline resources\n PIPELINE_READ: 'bigconsole-pipeline:read',\n PIPELINE_CREATE: 'bigconsole-pipeline:create',\n PIPELINE_UPDATE: 'bigconsole-pipeline:update',\n PIPELINE_DELETE: 'bigconsole-pipeline:delete',\n // `executePipeline` enforces `execute`\n PIPELINE_EXECUTE: 'bigconsole-pipeline:execute',\n // `testPipeline` enforces `test`\n PIPELINE_TEST: 'bigconsole-pipeline:test',\n\n // Prompt / AI-generation resources\n PROMPT_READ: 'bigconsole-prompt:read',\n PROMPT_CREATE: 'bigconsole-prompt:create',\n PROMPT_UPDATE: 'bigconsole-prompt:update',\n PROMPT_DELETE: 'bigconsole-prompt:delete',\n\n // Workflow resources\n WORKFLOW_READ: 'bigconsole-workflow:read',\n WORKFLOW_CREATE: 'bigconsole-workflow:create',\n WORKFLOW_UPDATE: 'bigconsole-workflow:update',\n WORKFLOW_DELETE: 'bigconsole-workflow:delete',\n // `executeWorkflow` enforces `execute`\n WORKFLOW_EXECUTE: 'bigconsole-workflow:execute',\n\n // Widget resources\n WIDGET_READ: 'bigconsole-widget:read',\n WIDGET_CREATE: 'bigconsole-widget:create',\n WIDGET_UPDATE: 'bigconsole-widget:update',\n WIDGET_DELETE: 'bigconsole-widget:delete',\n\n // Widget action resources (widget event/action bindings)\n WIDGET_ACTION_READ: 'bigconsole-widget-action:read',\n WIDGET_ACTION_CREATE: 'bigconsole-widget-action:create',\n WIDGET_ACTION_UPDATE: 'bigconsole-widget-action:update',\n WIDGET_ACTION_DELETE: 'bigconsole-widget-action:delete',\n // `emitWidgetEvent` enforces `execute`\n WIDGET_ACTION_EXECUTE: 'bigconsole-widget-action:execute',\n\n // Event log resources\n EVENT_LOG_READ: 'bigconsole-event-log:read',\n // `retryEventDelivery` enforces `execute`\n EVENT_LOG_EXECUTE: 'bigconsole-event-log:execute',\n\n // Event webhook mapping resources\n WEBHOOK_READ: 'bigconsole-webhook:read',\n WEBHOOK_CREATE: 'bigconsole-webhook:create',\n WEBHOOK_UPDATE: 'bigconsole-webhook:update',\n WEBHOOK_DELETE: 'bigconsole-webhook:delete',\n // `testWebhookMapping` enforces `test`\n WEBHOOK_TEST: 'bigconsole-webhook:test',\n} as const;\n\nexport type BigConsolePermission = (typeof BIGCONSOLE_PERMISSIONS)[keyof typeof BIGCONSOLE_PERMISSIONS];\n"],"mappings":";AAuCA,IAAa,IAAyB;CAEpC,gBAAgB;CAChB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,kBAAkB;CAClB,mBAAmB;CACnB,iBAAiB;CAEjB,wBAAwB;CAGxB,uBAAuB;CACvB,uBAAuB;CACvB,uBAAuB;CAGvB,eAAe;CACf,eAAe;CACf,eAAe;CAGf,oBAAoB;CACpB,sBAAsB;CACtB,sBAAsB;CACtB,sBAAsB;CAGtB,iBAAiB;CACjB,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CAInB,YAAY;CAGZ,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,kBAAkB;CAGlB,WAAW;CACX,aAAa;CACb,aAAa;CACb,aAAa;CAGb,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CAEjB,kBAAkB;CAElB,iBAAiB;CAGjB,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAEf,gBAAgB;CAEhB,aAAa;CAGb,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CAEjB,kBAAkB;CAElB,eAAe;CAGf,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAGf,eAAe;CACf,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CAEjB,kBAAkB;CAGlB,aAAa;CACb,eAAe;CACf,eAAe;CACf,eAAe;CAGf,oBAAoB;CACpB,sBAAsB;CACtB,sBAAsB;CACtB,sBAAsB;CAEtB,uBAAuB;CAGvB,gBAAgB;CAEhB,mBAAmB;CAGnB,cAAc;CACd,gBAAgB;CAChB,gBAAgB;CAChB,gBAAgB;CAEhB,cAAc;CACf"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/microfe-bigconsole",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.805.2",
|
|
4
4
|
"description": "BigConsole - AI-powered analytics and dashboard platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"vite-plugin-dts": "3.9.1"
|
|
121
121
|
},
|
|
122
122
|
"publishConfig": {
|
|
123
|
-
"access": "
|
|
123
|
+
"access": "public"
|
|
124
124
|
},
|
|
125
125
|
"overrides": {
|
|
126
126
|
"lodash": ">=4.17.21",
|