@burdenoff/microfe-bigconsole 2026.610.1 → 2026.612.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.
Files changed (31) hide show
  1. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +3 -3
  2. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  3. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +6 -5
  4. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  5. package/dist/bigconsole/components/widgets/WidgetRegistry.js +2 -1
  6. package/dist/bigconsole/components/widgets/WidgetRegistry.js.map +1 -1
  7. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js +4 -4
  8. package/dist/bigconsole/components/widgets/event-logs/EventLogViewer.js.map +1 -1
  9. package/dist/bigconsole/components/widgets/form/FormWidget.js +20 -20
  10. package/dist/bigconsole/components/widgets/form/FormWidget.js.map +1 -1
  11. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js +1 -1
  12. package/dist/bigconsole/components/widgets/kanban/KanbanWidget.js.map +1 -1
  13. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js +2 -2
  14. package/dist/bigconsole/components/widgets/map-widget/MapWidget.js.map +1 -1
  15. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js +2 -2
  16. package/dist/bigconsole/components/widgets/timeline/TimelineWidget.js.map +1 -1
  17. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js +37 -37
  18. package/dist/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.js.map +1 -1
  19. package/dist/bigconsole/hooks/useDashboardOperations.js +92 -70
  20. package/dist/bigconsole/hooks/useDashboardOperations.js.map +1 -1
  21. package/dist/bigconsole/pages/DashboardBuilderPage.js +220 -200
  22. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  23. package/dist/bigconsole/pages/DashboardViewPage.js +11 -9
  24. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  25. package/dist/bigconsole/pages/DashboardsPage.js +501 -164
  26. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  27. package/dist/bigconsole/pages/InsightsPage.js +783 -395
  28. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  29. package/dist/generated/wspace-operations.js +105 -107
  30. package/dist/generated/wspace-operations.js.map +1 -1
  31. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookConfigPanel.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.tsx"],"sourcesContent":["/**\n * WebhookConfigPanel Component (v2.0)\n *\n * Panel for managing event webhook mappings.\n * Allows creating, editing, testing, and deleting webhooks.\n */\n\nimport React, { memo, useState, useCallback } from 'react';\nimport {\n useEventWebhooks,\n type HttpMethod,\n type EventWebhookMapping,\n type CreateEventWebhookMappingInput,\n type UpdateEventWebhookMappingInput,\n type WebhookTestResult,\n} from '../../../hooks/useEventWebhooks';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WebhookConfigPanelProps {\n /** Dashboard ID for webhook scope */\n dashboardId?: string;\n /** Widget ID for webhook scope */\n widgetId?: string;\n /** Callback when webhook is created */\n onWebhookCreated?: (webhook: EventWebhookMapping) => void;\n /** Callback when webhook is deleted */\n onWebhookDeleted?: (id: string) => void;\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\nconst styles = {\n container: {\n padding: '16px',\n backgroundColor: '#ffffff',\n borderRadius: '8px',\n } as React.CSSProperties,\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '16px',\n } as React.CSSProperties,\n title: {\n fontSize: '16px',\n fontWeight: 600,\n color: '#111827',\n margin: 0,\n } as React.CSSProperties,\n addButton: {\n padding: '8px 16px',\n backgroundColor: '#2563eb',\n color: '#ffffff',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n webhookList: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n } as React.CSSProperties,\n webhookCard: {\n padding: '16px',\n backgroundColor: '#f9fafb',\n borderRadius: '8px',\n border: '1px solid #e5e7eb',\n } as React.CSSProperties,\n webhookHeader: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: '8px',\n } as React.CSSProperties,\n webhookTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n } as React.CSSProperties,\n webhookName: {\n fontSize: '14px',\n fontWeight: 600,\n color: '#111827',\n } as React.CSSProperties,\n statusBadge: {\n padding: '2px 8px',\n borderRadius: '12px',\n fontSize: '12px',\n fontWeight: 500,\n } as React.CSSProperties,\n activeBadge: {\n backgroundColor: '#d1fae5',\n color: '#065f46',\n } as React.CSSProperties,\n inactiveBadge: {\n backgroundColor: '#fef3c7',\n color: '#92400e',\n } as React.CSSProperties,\n webhookDetails: {\n fontSize: '13px',\n color: '#6b7280',\n marginBottom: '4px',\n } as React.CSSProperties,\n webhookUrl: {\n fontSize: '12px',\n color: '#9ca3af',\n fontFamily: 'monospace',\n wordBreak: 'break-all',\n } as React.CSSProperties,\n webhookActions: {\n display: 'flex',\n gap: '8px',\n marginTop: '12px',\n } as React.CSSProperties,\n actionButton: {\n padding: '6px 12px',\n fontSize: '12px',\n fontWeight: 500,\n borderRadius: '4px',\n border: 'none',\n cursor: 'pointer',\n } as React.CSSProperties,\n editButton: {\n backgroundColor: '#e5e7eb',\n color: '#374151',\n } as React.CSSProperties,\n testButton: {\n backgroundColor: '#dbeafe',\n color: '#1d4ed8',\n } as React.CSSProperties,\n deleteButton: {\n backgroundColor: '#fee2e2',\n color: '#dc2626',\n } as React.CSSProperties,\n toggleButton: {\n backgroundColor: '#f3f4f6',\n color: '#6b7280',\n } as React.CSSProperties,\n emptyState: {\n textAlign: 'center',\n padding: '32px',\n color: '#9ca3af',\n } as React.CSSProperties,\n form: {\n padding: '16px',\n backgroundColor: '#f9fafb',\n borderRadius: '8px',\n marginBottom: '16px',\n } as React.CSSProperties,\n formGroup: {\n marginBottom: '12px',\n } as React.CSSProperties,\n label: {\n display: 'block',\n fontSize: '13px',\n fontWeight: 500,\n color: '#374151',\n marginBottom: '4px',\n } as React.CSSProperties,\n input: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n boxSizing: 'border-box',\n } as React.CSSProperties,\n select: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n boxSizing: 'border-box',\n backgroundColor: '#ffffff',\n } as React.CSSProperties,\n textarea: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid #d1d5db',\n borderRadius: '6px',\n boxSizing: 'border-box',\n fontFamily: 'monospace',\n minHeight: '80px',\n resize: 'vertical',\n } as React.CSSProperties,\n formActions: {\n display: 'flex',\n gap: '8px',\n justifyContent: 'flex-end',\n marginTop: '16px',\n } as React.CSSProperties,\n cancelButton: {\n padding: '8px 16px',\n backgroundColor: '#f3f4f6',\n color: '#374151',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n cursor: 'pointer',\n } as React.CSSProperties,\n saveButton: {\n padding: '8px 16px',\n backgroundColor: '#2563eb',\n color: '#ffffff',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n testResult: {\n marginTop: '12px',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '13px',\n } as React.CSSProperties,\n testSuccess: {\n backgroundColor: '#d1fae5',\n color: '#065f46',\n } as React.CSSProperties,\n testFailure: {\n backgroundColor: '#fee2e2',\n color: '#991b1b',\n } as React.CSSProperties,\n helpText: {\n fontSize: '12px',\n color: '#9ca3af',\n marginTop: '4px',\n } as React.CSSProperties,\n};\n\n// ============================================================================\n// Webhook Form Component\n// ============================================================================\n\ninterface WebhookFormProps {\n webhook?: EventWebhookMapping;\n dashboardId?: string;\n widgetId?: string;\n onSave: (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => Promise<void>;\n onCancel: () => void;\n loading?: boolean;\n}\n\nconst WebhookForm: React.FC<WebhookFormProps> = memo(function WebhookForm({\n webhook,\n dashboardId,\n widgetId,\n onSave,\n onCancel,\n loading,\n}) {\n const [eventPattern, setEventPattern] = useState(webhook?.eventPattern || 'widget:*:clicked');\n const [webhookUrl, setWebhookUrl] = useState(webhook?.webhookUrl || '');\n const [method, setMethod] = useState(webhook?.method || 'POST');\n const [headers, setHeaders] = useState(webhook?.headers ? JSON.stringify(webhook.headers, null, 2) : '');\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n let parsedHeaders: Record<string, string> | undefined;\n if (headers.trim()) {\n try {\n parsedHeaders = JSON.parse(headers);\n } catch {\n alert('Invalid JSON in headers field');\n return;\n }\n }\n\n if (webhook) {\n // Update\n await onSave({\n id: webhook.id,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders || null,\n });\n } else {\n // Create\n await onSave({\n dashboardId,\n widgetId,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders,\n });\n }\n };\n\n return (\n <form style={styles.form} onSubmit={handleSubmit}>\n <div style={styles.formGroup}>\n <label style={styles.label}>Event Pattern *</label>\n <input\n type=\"text\"\n value={eventPattern}\n onChange={(e) => setEventPattern(e.target.value)}\n placeholder=\"widget:*:clicked\"\n style={styles.input}\n required\n />\n <p style={styles.helpText}>Use * as wildcard. Examples: widget:*:clicked, *:submit, button:save:*</p>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>Webhook URL *</label>\n <input\n type=\"url\"\n value={webhookUrl}\n onChange={(e) => setWebhookUrl(e.target.value)}\n placeholder=\"https://your-api.com/webhooks/bigconsole\"\n style={styles.input}\n required\n />\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>HTTP Method</label>\n <select value={method} onChange={(e) => setMethod(e.target.value as HttpMethod)} style={styles.select}>\n <option value=\"POST\">POST</option>\n <option value=\"PUT\">PUT</option>\n <option value=\"PATCH\">PATCH</option>\n <option value=\"GET\">GET</option>\n <option value=\"DELETE\">DELETE</option>\n </select>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>Custom Headers (JSON)</label>\n <textarea\n value={headers}\n onChange={(e) => setHeaders(e.target.value)}\n placeholder={'{\\n \"Authorization\": \"Bearer your-token\"\\n}'}\n style={styles.textarea as React.CSSProperties}\n />\n </div>\n\n <div style={styles.formActions}>\n <button type=\"button\" onClick={onCancel} style={styles.cancelButton}>\n Cancel\n </button>\n <button type=\"submit\" disabled={loading} style={styles.saveButton}>\n {loading ? 'Saving...' : webhook ? 'Update Webhook' : 'Create Webhook'}\n </button>\n </div>\n </form>\n );\n});\n\n// ============================================================================\n// Webhook Card Component\n// ============================================================================\n\ninterface WebhookCardProps {\n webhook: EventWebhookMapping;\n onEdit: () => void;\n onDelete: () => void;\n onToggle: () => void;\n onTest: () => void;\n testResult?: WebhookTestResult | null;\n testing?: boolean;\n}\n\nconst WebhookCard: React.FC<WebhookCardProps> = memo(function WebhookCard({\n webhook,\n onEdit,\n onDelete,\n onToggle,\n onTest,\n testResult,\n testing,\n}) {\n return (\n <div style={styles.webhookCard}>\n <div style={styles.webhookHeader}>\n <div style={styles.webhookTitle}>\n <span style={{ fontSize: '16px' }}>📡</span>\n <span style={styles.webhookName}>{webhook.eventPattern}</span>\n <span\n style={{\n ...styles.statusBadge,\n ...(webhook.isActive ? styles.activeBadge : styles.inactiveBadge),\n }}\n >\n {webhook.isActive ? 'Active' : 'Inactive'}\n </span>\n </div>\n </div>\n\n <div style={styles.webhookDetails}>\n Method: <strong>{webhook.method}</strong>\n </div>\n <div style={styles.webhookUrl}>{webhook.webhookUrl}</div>\n\n {testResult && (\n <div\n style={{\n ...styles.testResult,\n ...(testResult.success ? styles.testSuccess : styles.testFailure),\n }}\n >\n {testResult.success ? (\n <>\n ✅ Test successful! Status: {testResult.statusCode}, Latency: {testResult.latencyMs}ms\n </>\n ) : (\n <>❌ Test failed: {testResult.errorMessage || 'Unknown error'}</>\n )}\n </div>\n )}\n\n <div style={styles.webhookActions}>\n <button onClick={onEdit} style={{ ...styles.actionButton, ...styles.editButton }}>\n Edit\n </button>\n <button onClick={onTest} disabled={testing} style={{ ...styles.actionButton, ...styles.testButton }}>\n {testing ? 'Testing...' : 'Test'}\n </button>\n <button onClick={onToggle} style={{ ...styles.actionButton, ...styles.toggleButton }}>\n {webhook.isActive ? 'Disable' : 'Enable'}\n </button>\n <button onClick={onDelete} style={{ ...styles.actionButton, ...styles.deleteButton }}>\n Delete\n </button>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WebhookConfigPanel: React.FC<WebhookConfigPanelProps> = memo(function WebhookConfigPanel({\n dashboardId,\n widgetId,\n onWebhookCreated,\n onWebhookDeleted,\n}) {\n const [showForm, setShowForm] = useState(false);\n const [editingWebhook, setEditingWebhook] = useState<EventWebhookMapping | null>(null);\n const [testResults, setTestResults] = useState<Record<string, WebhookTestResult | null>>({});\n const [testingId, setTestingId] = useState<string | null>(null);\n\n const { webhooks, loading, createWebhook, updateWebhook, deleteWebhook, toggleWebhook, testWebhook } =\n useEventWebhooks({ dashboardId, widgetId });\n\n const handleSave = useCallback(\n async (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => {\n if ('id' in data) {\n const result = await updateWebhook(data);\n if (result) {\n setEditingWebhook(null);\n setShowForm(false);\n }\n } else {\n const result = await createWebhook(data);\n if (result) {\n setShowForm(false);\n onWebhookCreated?.(result);\n }\n }\n },\n [createWebhook, updateWebhook, onWebhookCreated]\n );\n\n const handleDelete = useCallback(\n async (id: string) => {\n if (confirm('Are you sure you want to delete this webhook?')) {\n const success = await deleteWebhook(id);\n if (success) {\n onWebhookDeleted?.(id);\n }\n }\n },\n [deleteWebhook, onWebhookDeleted]\n );\n\n const handleToggle = useCallback(\n async (webhook: EventWebhookMapping) => {\n await toggleWebhook(webhook.id, !webhook.isActive);\n },\n [toggleWebhook]\n );\n\n const handleTest = useCallback(\n async (id: string) => {\n setTestingId(id);\n const result = await testWebhook(id);\n setTestResults((prev) => ({ ...prev, [id]: result }));\n setTestingId(null);\n },\n [testWebhook]\n );\n\n const handleEdit = useCallback((webhook: EventWebhookMapping) => {\n setEditingWebhook(webhook);\n setShowForm(true);\n }, []);\n\n const handleCancel = useCallback(() => {\n setShowForm(false);\n setEditingWebhook(null);\n }, []);\n\n return (\n <div style={styles.container}>\n <div style={styles.header}>\n <h3 style={styles.title}>Webhook Configuration</h3>\n {!showForm && (\n <button onClick={() => setShowForm(true)} style={styles.addButton}>\n + Add Webhook\n </button>\n )}\n </div>\n\n {showForm && (\n <WebhookForm\n webhook={editingWebhook || undefined}\n dashboardId={dashboardId}\n widgetId={widgetId}\n onSave={handleSave}\n onCancel={handleCancel}\n loading={loading}\n />\n )}\n\n {loading && webhooks.length === 0 ? (\n <div style={styles.emptyState}>Loading...</div>\n ) : webhooks.length === 0 ? (\n <div style={styles.emptyState}>\n <p>No webhooks configured</p>\n <p style={{ fontSize: '13px', marginTop: '8px' }}>\n Add a webhook to receive events when actions are triggered.\n </p>\n </div>\n ) : (\n <div style={styles.webhookList as React.CSSProperties}>\n {webhooks.map((webhook) => (\n <WebhookCard\n key={webhook.id}\n webhook={webhook}\n onEdit={() => handleEdit(webhook)}\n onDelete={() => handleDelete(webhook.id)}\n onToggle={() => handleToggle(webhook)}\n onTest={() => handleTest(webhook.id)}\n testResult={testResults[webhook.id]}\n testing={testingId === webhook.id}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nexport default WebhookConfigPanel;\n"],"mappings":"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"}
1
+ {"version":3,"file":"WebhookConfigPanel.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/webhook-config/WebhookConfigPanel.tsx"],"sourcesContent":["/**\n * WebhookConfigPanel Component (v2.0)\n *\n * Panel for managing event webhook mappings.\n * Allows creating, editing, testing, and deleting webhooks.\n */\n\nimport React, { memo, useState, useCallback } from 'react';\nimport {\n useEventWebhooks,\n type HttpMethod,\n type EventWebhookMapping,\n type CreateEventWebhookMappingInput,\n type UpdateEventWebhookMappingInput,\n type WebhookTestResult,\n} from '../../../hooks/useEventWebhooks';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WebhookConfigPanelProps {\n /** Dashboard ID for webhook scope */\n dashboardId?: string;\n /** Widget ID for webhook scope */\n widgetId?: string;\n /** Callback when webhook is created */\n onWebhookCreated?: (webhook: EventWebhookMapping) => void;\n /** Callback when webhook is deleted */\n onWebhookDeleted?: (id: string) => void;\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\nconst styles = {\n container: {\n padding: '16px',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n } as React.CSSProperties,\n header: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n marginBottom: '16px',\n } as React.CSSProperties,\n title: {\n fontSize: '16px',\n fontWeight: 600,\n color: 'var(--color-text-primary)',\n margin: 0,\n } as React.CSSProperties,\n addButton: {\n padding: '8px 16px',\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-text-inverse)',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n webhookList: {\n display: 'flex',\n flexDirection: 'column',\n gap: '12px',\n } as React.CSSProperties,\n webhookCard: {\n padding: '16px',\n backgroundColor: 'var(--color-bg-subtle)',\n borderRadius: '8px',\n border: '1px solid var(--color-border-subtle)',\n } as React.CSSProperties,\n webhookHeader: {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: '8px',\n } as React.CSSProperties,\n webhookTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n } as React.CSSProperties,\n webhookName: {\n fontSize: '14px',\n fontWeight: 600,\n color: 'var(--color-text-primary)',\n } as React.CSSProperties,\n statusBadge: {\n padding: '2px 8px',\n borderRadius: '12px',\n fontSize: '12px',\n fontWeight: 500,\n } as React.CSSProperties,\n activeBadge: {\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n color: 'var(--color-status-success-text)',\n } as React.CSSProperties,\n inactiveBadge: {\n backgroundColor: 'var(--color-status-warning-bgSubtle)',\n color: 'var(--color-status-warning-text)',\n } as React.CSSProperties,\n webhookDetails: {\n fontSize: '13px',\n color: 'var(--color-text-muted)',\n marginBottom: '4px',\n } as React.CSSProperties,\n webhookUrl: {\n fontSize: '12px',\n color: 'var(--color-text-placeholder)',\n fontFamily: 'monospace',\n wordBreak: 'break-all',\n } as React.CSSProperties,\n webhookActions: {\n display: 'flex',\n gap: '8px',\n marginTop: '12px',\n } as React.CSSProperties,\n actionButton: {\n padding: '6px 12px',\n fontSize: '12px',\n fontWeight: 500,\n borderRadius: '4px',\n border: 'none',\n cursor: 'pointer',\n } as React.CSSProperties,\n editButton: {\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-primary)',\n } as React.CSSProperties,\n testButton: {\n backgroundColor: 'var(--color-status-info-bgSubtle)',\n color: 'var(--color-status-info-text)',\n } as React.CSSProperties,\n deleteButton: {\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n color: 'var(--color-status-error-text)',\n } as React.CSSProperties,\n toggleButton: {\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-muted)',\n } as React.CSSProperties,\n emptyState: {\n textAlign: 'center',\n padding: '32px',\n color: 'var(--color-text-placeholder)',\n } as React.CSSProperties,\n form: {\n padding: '16px',\n backgroundColor: 'var(--color-bg-subtle)',\n borderRadius: '8px',\n marginBottom: '16px',\n } as React.CSSProperties,\n formGroup: {\n marginBottom: '12px',\n } as React.CSSProperties,\n label: {\n display: 'block',\n fontSize: '13px',\n fontWeight: 500,\n color: 'var(--color-text-primary)',\n marginBottom: '4px',\n } as React.CSSProperties,\n input: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n boxSizing: 'border-box',\n } as React.CSSProperties,\n select: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n boxSizing: 'border-box',\n backgroundColor: 'var(--color-bg-surface)',\n } as React.CSSProperties,\n textarea: {\n width: '100%',\n padding: '8px 12px',\n fontSize: '14px',\n border: '1px solid var(--color-border-default)',\n borderRadius: '6px',\n boxSizing: 'border-box',\n fontFamily: 'monospace',\n minHeight: '80px',\n resize: 'vertical',\n } as React.CSSProperties,\n formActions: {\n display: 'flex',\n gap: '8px',\n justifyContent: 'flex-end',\n marginTop: '16px',\n } as React.CSSProperties,\n cancelButton: {\n padding: '8px 16px',\n backgroundColor: 'var(--color-bg-sunken)',\n color: 'var(--color-text-primary)',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n cursor: 'pointer',\n } as React.CSSProperties,\n saveButton: {\n padding: '8px 16px',\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-text-inverse)',\n border: 'none',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: 500,\n cursor: 'pointer',\n } as React.CSSProperties,\n testResult: {\n marginTop: '12px',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '13px',\n } as React.CSSProperties,\n testSuccess: {\n backgroundColor: 'var(--color-status-success-bgSubtle)',\n color: 'var(--color-status-success-text)',\n } as React.CSSProperties,\n testFailure: {\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n color: 'var(--color-status-error-text)',\n } as React.CSSProperties,\n helpText: {\n fontSize: '12px',\n color: 'var(--color-text-placeholder)',\n marginTop: '4px',\n } as React.CSSProperties,\n};\n\n// ============================================================================\n// Webhook Form Component\n// ============================================================================\n\ninterface WebhookFormProps {\n webhook?: EventWebhookMapping;\n dashboardId?: string;\n widgetId?: string;\n onSave: (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => Promise<void>;\n onCancel: () => void;\n loading?: boolean;\n}\n\nconst WebhookForm: React.FC<WebhookFormProps> = memo(function WebhookForm({\n webhook,\n dashboardId,\n widgetId,\n onSave,\n onCancel,\n loading,\n}) {\n const [eventPattern, setEventPattern] = useState(webhook?.eventPattern || 'widget:*:clicked');\n const [webhookUrl, setWebhookUrl] = useState(webhook?.webhookUrl || '');\n const [method, setMethod] = useState(webhook?.method || 'POST');\n const [headers, setHeaders] = useState(webhook?.headers ? JSON.stringify(webhook.headers, null, 2) : '');\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n let parsedHeaders: Record<string, string> | undefined;\n if (headers.trim()) {\n try {\n parsedHeaders = JSON.parse(headers);\n } catch {\n alert('Invalid JSON in headers field');\n return;\n }\n }\n\n if (webhook) {\n // Update\n await onSave({\n id: webhook.id,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders || null,\n });\n } else {\n // Create\n await onSave({\n dashboardId,\n widgetId,\n eventPattern,\n webhookUrl,\n method: method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',\n headers: parsedHeaders,\n });\n }\n };\n\n return (\n <form style={styles.form} onSubmit={handleSubmit}>\n <div style={styles.formGroup}>\n <label style={styles.label}>Event Pattern *</label>\n <input\n type=\"text\"\n value={eventPattern}\n onChange={(e) => setEventPattern(e.target.value)}\n placeholder=\"widget:*:clicked\"\n style={styles.input}\n required\n />\n <p style={styles.helpText}>Use * as wildcard. Examples: widget:*:clicked, *:submit, button:save:*</p>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>Webhook URL *</label>\n <input\n type=\"url\"\n value={webhookUrl}\n onChange={(e) => setWebhookUrl(e.target.value)}\n placeholder=\"https://your-api.com/webhooks/bigconsole\"\n style={styles.input}\n required\n />\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>HTTP Method</label>\n <select value={method} onChange={(e) => setMethod(e.target.value as HttpMethod)} style={styles.select}>\n <option value=\"POST\">POST</option>\n <option value=\"PUT\">PUT</option>\n <option value=\"PATCH\">PATCH</option>\n <option value=\"GET\">GET</option>\n <option value=\"DELETE\">DELETE</option>\n </select>\n </div>\n\n <div style={styles.formGroup}>\n <label style={styles.label}>Custom Headers (JSON)</label>\n <textarea\n value={headers}\n onChange={(e) => setHeaders(e.target.value)}\n placeholder={'{\\n \"Authorization\": \"Bearer your-token\"\\n}'}\n style={styles.textarea as React.CSSProperties}\n />\n </div>\n\n <div style={styles.formActions}>\n <button type=\"button\" onClick={onCancel} style={styles.cancelButton}>\n Cancel\n </button>\n <button type=\"submit\" disabled={loading} style={styles.saveButton}>\n {loading ? 'Saving...' : webhook ? 'Update Webhook' : 'Create Webhook'}\n </button>\n </div>\n </form>\n );\n});\n\n// ============================================================================\n// Webhook Card Component\n// ============================================================================\n\ninterface WebhookCardProps {\n webhook: EventWebhookMapping;\n onEdit: () => void;\n onDelete: () => void;\n onToggle: () => void;\n onTest: () => void;\n testResult?: WebhookTestResult | null;\n testing?: boolean;\n}\n\nconst WebhookCard: React.FC<WebhookCardProps> = memo(function WebhookCard({\n webhook,\n onEdit,\n onDelete,\n onToggle,\n onTest,\n testResult,\n testing,\n}) {\n return (\n <div style={styles.webhookCard}>\n <div style={styles.webhookHeader}>\n <div style={styles.webhookTitle}>\n <span style={{ fontSize: '16px' }}>📡</span>\n <span style={styles.webhookName}>{webhook.eventPattern}</span>\n <span\n style={{\n ...styles.statusBadge,\n ...(webhook.isActive ? styles.activeBadge : styles.inactiveBadge),\n }}\n >\n {webhook.isActive ? 'Active' : 'Inactive'}\n </span>\n </div>\n </div>\n\n <div style={styles.webhookDetails}>\n Method: <strong>{webhook.method}</strong>\n </div>\n <div style={styles.webhookUrl}>{webhook.webhookUrl}</div>\n\n {testResult && (\n <div\n style={{\n ...styles.testResult,\n ...(testResult.success ? styles.testSuccess : styles.testFailure),\n }}\n >\n {testResult.success ? (\n <>\n ✅ Test successful! Status: {testResult.statusCode}, Latency: {testResult.latencyMs}ms\n </>\n ) : (\n <>❌ Test failed: {testResult.errorMessage || 'Unknown error'}</>\n )}\n </div>\n )}\n\n <div style={styles.webhookActions}>\n <button onClick={onEdit} style={{ ...styles.actionButton, ...styles.editButton }}>\n Edit\n </button>\n <button onClick={onTest} disabled={testing} style={{ ...styles.actionButton, ...styles.testButton }}>\n {testing ? 'Testing...' : 'Test'}\n </button>\n <button onClick={onToggle} style={{ ...styles.actionButton, ...styles.toggleButton }}>\n {webhook.isActive ? 'Disable' : 'Enable'}\n </button>\n <button onClick={onDelete} style={{ ...styles.actionButton, ...styles.deleteButton }}>\n Delete\n </button>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WebhookConfigPanel: React.FC<WebhookConfigPanelProps> = memo(function WebhookConfigPanel({\n dashboardId,\n widgetId,\n onWebhookCreated,\n onWebhookDeleted,\n}) {\n const [showForm, setShowForm] = useState(false);\n const [editingWebhook, setEditingWebhook] = useState<EventWebhookMapping | null>(null);\n const [testResults, setTestResults] = useState<Record<string, WebhookTestResult | null>>({});\n const [testingId, setTestingId] = useState<string | null>(null);\n\n const { webhooks, loading, createWebhook, updateWebhook, deleteWebhook, toggleWebhook, testWebhook } =\n useEventWebhooks({ dashboardId, widgetId });\n\n const handleSave = useCallback(\n async (data: CreateEventWebhookMappingInput | UpdateEventWebhookMappingInput) => {\n if ('id' in data) {\n const result = await updateWebhook(data);\n if (result) {\n setEditingWebhook(null);\n setShowForm(false);\n }\n } else {\n const result = await createWebhook(data);\n if (result) {\n setShowForm(false);\n onWebhookCreated?.(result);\n }\n }\n },\n [createWebhook, updateWebhook, onWebhookCreated]\n );\n\n const handleDelete = useCallback(\n async (id: string) => {\n if (confirm('Are you sure you want to delete this webhook?')) {\n const success = await deleteWebhook(id);\n if (success) {\n onWebhookDeleted?.(id);\n }\n }\n },\n [deleteWebhook, onWebhookDeleted]\n );\n\n const handleToggle = useCallback(\n async (webhook: EventWebhookMapping) => {\n await toggleWebhook(webhook.id, !webhook.isActive);\n },\n [toggleWebhook]\n );\n\n const handleTest = useCallback(\n async (id: string) => {\n setTestingId(id);\n const result = await testWebhook(id);\n setTestResults((prev) => ({ ...prev, [id]: result }));\n setTestingId(null);\n },\n [testWebhook]\n );\n\n const handleEdit = useCallback((webhook: EventWebhookMapping) => {\n setEditingWebhook(webhook);\n setShowForm(true);\n }, []);\n\n const handleCancel = useCallback(() => {\n setShowForm(false);\n setEditingWebhook(null);\n }, []);\n\n return (\n <div style={styles.container}>\n <div style={styles.header}>\n <h3 style={styles.title}>Webhook Configuration</h3>\n {!showForm && (\n <button onClick={() => setShowForm(true)} style={styles.addButton}>\n + Add Webhook\n </button>\n )}\n </div>\n\n {showForm && (\n <WebhookForm\n webhook={editingWebhook || undefined}\n dashboardId={dashboardId}\n widgetId={widgetId}\n onSave={handleSave}\n onCancel={handleCancel}\n loading={loading}\n />\n )}\n\n {loading && webhooks.length === 0 ? (\n <div style={styles.emptyState}>Loading...</div>\n ) : webhooks.length === 0 ? (\n <div style={styles.emptyState}>\n <p>No webhooks configured</p>\n <p style={{ fontSize: '13px', marginTop: '8px' }}>\n Add a webhook to receive events when actions are triggered.\n </p>\n </div>\n ) : (\n <div style={styles.webhookList as React.CSSProperties}>\n {webhooks.map((webhook) => (\n <WebhookCard\n key={webhook.id}\n webhook={webhook}\n onEdit={() => handleEdit(webhook)}\n onDelete={() => handleDelete(webhook.id)}\n onToggle={() => handleToggle(webhook)}\n onTest={() => handleTest(webhook.id)}\n testResult={testResults[webhook.id]}\n testing={testingId === webhook.id}\n />\n ))}\n </div>\n )}\n </div>\n );\n});\n\nexport default WebhookConfigPanel;\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { useDashboardStore as e } from "../store/dashboardStore.js";
2
2
  import "../store/index.js";
3
- import { CreateDashboardDocument as t, DeleteDashboardDocument as n, GetDashboardDocument as r, ListDashboardsDocument as i, UpdateDashboardDocument as a } from "../../generated/wspace-operations.js";
4
- import { useCallback as o, useEffect as s, useState as c } from "react";
5
- import { useApolloClient as l } from "@apollo/client/react";
3
+ import { CloneDashboardDocument as t, CreateDashboardDocument as n, DeleteDashboardDocument as r, GetDashboardDocument as i, ListDashboardsDocument as a, UpdateDashboardDocument as o } from "../../generated/wspace-operations.js";
4
+ import { useCallback as s, useEffect as c, useState as l } from "react";
5
+ import { useApolloClient as u } from "@apollo/client/react";
6
6
  //#region src/bigconsole/hooks/useDashboardOperations.ts
7
- function u(e) {
7
+ function d(e) {
8
8
  let t = e.pages?.edges?.map((t) => ({
9
9
  id: t.node.id,
10
10
  dashboardId: t.node.dashboardId || e.id,
@@ -39,7 +39,7 @@ function u(e) {
39
39
  updatedAt: e.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
40
40
  };
41
41
  }
42
- function d(e) {
42
+ function f(e) {
43
43
  let t = e.pages?.edges?.map((t) => ({
44
44
  id: t.node.id,
45
45
  dashboardId: t.node.dashboardId || e.id,
@@ -65,123 +65,145 @@ function d(e) {
65
65
  pages: t
66
66
  };
67
67
  }
68
- function f() {
69
- let [f, p] = c(!1), [m, h] = c(null), [g, _] = c([]), v = l(), y = e((e) => e.currentDashboard), b = e((e) => e.setCurrentDashboard), x = o(async (e) => {
68
+ function p() {
69
+ let [p, m] = l(!1), [h, g] = l(null), [_, v] = l([]), y = u(), b = e((e) => e.currentDashboard), x = e((e) => e.setCurrentDashboard), S = s(async (e) => {
70
70
  try {
71
- p(!0), h(null), _(((await v.query({
72
- query: i,
71
+ m(!0), g(null), v(((await y.query({
72
+ query: a,
73
73
  variables: {
74
74
  first: 50,
75
75
  search: e,
76
76
  includeArchived: !1
77
77
  },
78
78
  fetchPolicy: "network-only"
79
- })).data?.listDashboards?.edges || []).map((e) => d(e.node)));
79
+ })).data?.listDashboards?.edges || []).map((e) => f(e.node)));
80
80
  } catch (e) {
81
- h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch dashboards"));
81
+ g(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch dashboards"));
82
82
  } finally {
83
- p(!1);
83
+ m(!1);
84
84
  }
85
- }, [v]), S = o(async (e) => {
85
+ }, [y]), C = s(async (e) => {
86
86
  try {
87
- p(!0), h(null);
88
- let t = await v.query({
89
- query: r,
87
+ m(!0), g(null);
88
+ let t = await y.query({
89
+ query: i,
90
90
  variables: { id: e },
91
91
  fetchPolicy: "network-only"
92
92
  });
93
93
  if (t.data?.getDashboard) {
94
- let e = u(t.data.getDashboard);
95
- return b(e), e;
94
+ let e = d(t.data.getDashboard);
95
+ return x(e), e;
96
96
  }
97
97
  return null;
98
98
  } catch (e) {
99
- return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch dashboard")), null;
99
+ return g(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch dashboard")), null;
100
100
  } finally {
101
- p(!1);
101
+ m(!1);
102
102
  }
103
- }, [v, b]), C = o(async (e) => {
103
+ }, [y, x]), w = s(async (e) => {
104
104
  try {
105
- p(!0), h(null);
106
- let n = {
105
+ m(!0), g(null);
106
+ let t = {
107
107
  name: e.name,
108
108
  description: e.description,
109
109
  category: e.category || "CUSTOM",
110
110
  layout: e.layoutType || "GRID",
111
111
  createDefaultPage: !0
112
112
  };
113
- e.tags && e.tags.length > 0 && (n.metadata = { tags: e.tags });
114
- let r = await v.mutate({
115
- mutation: t,
116
- variables: { input: n }
113
+ e.tags && e.tags.length > 0 && (t.metadata = { tags: e.tags });
114
+ let r = await y.mutate({
115
+ mutation: n,
116
+ variables: { input: t }
117
117
  });
118
118
  if (r.data?.createBigConsoleDashboard) {
119
- let e = u(r.data.createBigConsoleDashboard);
120
- return await x(), e;
119
+ let e = d(r.data.createBigConsoleDashboard);
120
+ return await S(), e;
121
121
  }
122
122
  return null;
123
123
  } catch (e) {
124
- return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to create dashboard")), null;
124
+ return g(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to create dashboard")), null;
125
125
  } finally {
126
- p(!1);
126
+ m(!1);
127
127
  }
128
- }, [v, x]), w = o(async (e) => {
128
+ }, [y, S]), T = s(async (e) => {
129
129
  try {
130
- p(!0), h(null);
131
- let t = await v.mutate({
132
- mutation: a,
130
+ m(!0), g(null);
131
+ let t = await y.mutate({
132
+ mutation: o,
133
133
  variables: { input: e }
134
134
  });
135
135
  if (t.data?.updateBigConsoleDashboard) {
136
- let n = u(t.data.updateBigConsoleDashboard);
137
- return y?.id === e.id && b(n), await x(), n;
136
+ let n = d(t.data.updateBigConsoleDashboard);
137
+ return b?.id === e.id && x(n), await S(), n;
138
138
  }
139
139
  return null;
140
140
  } catch (e) {
141
- return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update dashboard")), null;
141
+ return g(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update dashboard")), null;
142
142
  } finally {
143
- p(!1);
143
+ m(!1);
144
144
  }
145
145
  }, [
146
- v,
147
- y?.id,
148
- b,
149
- x
150
- ]), T = o(async (e) => {
146
+ y,
147
+ b?.id,
148
+ x,
149
+ S
150
+ ]), E = s(async (e) => {
151
151
  try {
152
- return p(!0), h(null), (await v.mutate({
153
- mutation: n,
152
+ return m(!0), g(null), (await y.mutate({
153
+ mutation: r,
154
154
  variables: { id: e }
155
- })).data?.deleteBigConsoleDashboard ? (y?.id === e && b(null), await x(), !0) : !1;
155
+ })).data?.deleteBigConsoleDashboard ? (b?.id === e && x(null), await S(), !0) : !1;
156
156
  } catch (e) {
157
- return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to delete dashboard")), !1;
157
+ return g(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to delete dashboard")), !1;
158
158
  } finally {
159
- p(!1);
159
+ m(!1);
160
160
  }
161
161
  }, [
162
- v,
163
- y?.id,
164
- b,
165
- x
166
- ]), E = o(async () => {
167
- await x();
168
- }, [x]);
169
- return s(() => {
170
- x();
171
- }, [x]), {
172
- loading: f,
173
- error: m,
174
- dashboards: g,
175
- currentDashboard: y,
176
- fetchDashboards: x,
177
- fetchDashboard: S,
178
- createDashboard: C,
179
- updateDashboard: w,
180
- deleteDashboard: T,
181
- refetch: E
162
+ y,
163
+ b?.id,
164
+ x,
165
+ S
166
+ ]), D = s(async (e, n) => {
167
+ try {
168
+ m(!0), g(null);
169
+ let r = await y.mutate({
170
+ mutation: t,
171
+ variables: { input: {
172
+ sourceDashboardId: e,
173
+ name: n,
174
+ includeWidgets: !0
175
+ } }
176
+ });
177
+ if (r.data?.cloneDashboard) {
178
+ let e = d(r.data.cloneDashboard);
179
+ return await S(), e;
180
+ }
181
+ return null;
182
+ } catch (e) {
183
+ return g(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to clone dashboard")), null;
184
+ } finally {
185
+ m(!1);
186
+ }
187
+ }, [y, S]), O = s(async () => {
188
+ await S();
189
+ }, [S]);
190
+ return c(() => {
191
+ S();
192
+ }, [S]), {
193
+ loading: p,
194
+ error: h,
195
+ dashboards: _,
196
+ currentDashboard: b,
197
+ fetchDashboards: S,
198
+ fetchDashboard: C,
199
+ createDashboard: w,
200
+ updateDashboard: T,
201
+ deleteDashboard: E,
202
+ cloneDashboard: D,
203
+ refetch: O
182
204
  };
183
205
  }
184
206
  //#endregion
185
- export { f as default };
207
+ export { p as default };
186
208
 
187
209
  //# sourceMappingURL=useDashboardOperations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDashboardOperations.js","names":[],"sources":["../../../src/bigconsole/hooks/useDashboardOperations.ts"],"sourcesContent":["/**\n * useDashboardOperations Hook\n *\n * Provides CRUD operations for dashboards using GraphQL.\n */\n\nimport { useCallback, useState, useEffect } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport type { Dashboard, DashboardLayoutConfig, DashboardPage } from '../types';\nimport { useDashboardStore } from '../store';\nimport {\n ListDashboardsDocument,\n GetDashboardDocument,\n CreateDashboardDocument,\n UpdateDashboardDocument,\n DeleteDashboardDocument,\n} from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardListItem {\n id: string;\n name: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n viewCount?: number;\n widgetCount?: number;\n createdAt: string;\n updatedAt: string;\n pages: DashboardPage[];\n}\n\ninterface CreateDashboardInput {\n name: string;\n description?: string;\n category?: string;\n layoutType?: string;\n tags?: string[];\n}\n\ninterface UpdateDashboardInput {\n id: string;\n name?: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n}\n\ninterface DashboardOperationsResult {\n loading: boolean;\n error: Error | null;\n dashboards: DashboardListItem[];\n currentDashboard: Dashboard | null;\n\n // Operations\n fetchDashboards: (search?: string) => Promise<void>;\n fetchDashboard: (id: string) => Promise<Dashboard | null>;\n createDashboard: (input: CreateDashboardInput) => Promise<Dashboard | null>;\n updateDashboard: (input: UpdateDashboardInput) => Promise<Dashboard | null>;\n deleteDashboard: (id: string) => Promise<boolean>;\n refetch: () => Promise<void>;\n}\n\n// ============================================================================\n// Helper: Normalize dashboard from GraphQL response\n// ============================================================================\n\n// Raw GraphQL response shape for dashboard data\ninterface RawDashboardData {\n id: string;\n name?: string;\n description?: string;\n workspaceId?: string;\n isPublic?: boolean;\n isTemplate?: boolean;\n layout?: Record<string, unknown>;\n category?: string;\n viewCount?: number;\n widgetCount?: number;\n createdBy?: string;\n ownerId?: string;\n createdAt?: string;\n updatedAt?: string;\n pages?: {\n edges?: Array<{\n node: {\n id: string;\n dashboardId?: string;\n name?: string;\n order?: number;\n layout?: Record<string, unknown>;\n gridColumns?: number;\n createdAt?: string;\n updatedAt?: string;\n };\n }>;\n };\n}\n\nfunction normalizeDashboard(data: RawDashboardData): Dashboard {\n const pages =\n data.pages?.edges?.map((edge) => ({\n id: edge.node.id,\n dashboardId: edge.node.dashboardId || data.id,\n name: edge.node.name,\n slug: edge.node.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n order: edge.node.order || 0,\n layoutConfig: edge.node.layout || {},\n gridColumns: edge.node.gridColumns || 12,\n widgets: [], // Widgets loaded separately via useWidgetOperations\n createdAt: edge.node.createdAt || new Date().toISOString(),\n updatedAt: edge.node.updatedAt || new Date().toISOString(),\n })) || [];\n\n return {\n id: data.id,\n workspaceId: data.workspaceId || '',\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n slug: data.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n isPublished: data.isPublic || false,\n isTemplate: data.isTemplate || false,\n layoutConfig: (data.layout as unknown as DashboardLayoutConfig) || {\n columns: 12,\n rowHeight: 100,\n gap: 10,\n margin: [10, 10],\n containerPadding: [10, 10],\n },\n pages,\n translations: [],\n createdBy: data.createdBy || data.ownerId || '',\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n };\n}\n\nfunction normalizeDashboardListItem(data: RawDashboardData): DashboardListItem {\n const pages =\n data.pages?.edges?.map((edge) => ({\n id: edge.node.id,\n dashboardId: edge.node.dashboardId || data.id,\n name: edge.node.name,\n slug: edge.node.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n order: edge.node.order || 0,\n layoutConfig: edge.node.layout || {},\n gridColumns: edge.node.gridColumns || 12,\n widgets: [], // Widget count not available in list query\n createdAt: edge.node.createdAt || new Date().toISOString(),\n updatedAt: edge.node.updatedAt || new Date().toISOString(),\n })) || [];\n\n return {\n id: data.id,\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n category: data.category,\n isPublic: data.isPublic,\n viewCount: data.viewCount,\n widgetCount: data.widgetCount,\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n pages,\n };\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboardOperations(): DashboardOperationsResult {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [dashboards, setDashboards] = useState<DashboardListItem[]>([]);\n\n // Get Apollo Client - will throw if not in ApolloProvider context\n const apolloClient = useApolloClient();\n\n // Store actions\n const currentDashboard = useDashboardStore((state) => state.currentDashboard);\n const setCurrentDashboard = useDashboardStore((state) => state.setCurrentDashboard);\n\n // Fetch dashboards list\n const fetchDashboards = useCallback(\n async (search?: string) => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ listDashboards?: { edges?: Array<{ node: RawDashboardData }> } }>({\n query: ListDashboardsDocument,\n variables: {\n first: 50,\n search,\n includeArchived: false,\n },\n fetchPolicy: 'network-only',\n });\n\n const edges = result.data?.listDashboards?.edges || [];\n const dashboardsList = edges.map((edge) => normalizeDashboardListItem(edge.node));\n setDashboards(dashboardsList);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboards');\n setError(error);\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Fetch single dashboard\n const fetchDashboard = useCallback(\n async (id: string): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ getDashboard?: RawDashboardData }>({\n query: GetDashboardDocument,\n variables: { id },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDashboard) {\n const dashboard = normalizeDashboard(result.data.getDashboard);\n setCurrentDashboard(dashboard);\n return dashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, setCurrentDashboard]\n );\n\n // Create dashboard\n const createDashboard = useCallback(\n async (input: CreateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n // Build mutation input\n // Note: Tags require Tag IDs from the Tags service. For now, tags are stored in metadata.\n // Full tag integration would require querying/creating tags via the Tags service first.\n const mutationInput: Record<string, unknown> = {\n name: input.name,\n description: input.description,\n category: input.category || 'CUSTOM',\n layout: input.layoutType || 'GRID',\n createDefaultPage: true,\n };\n\n // Store tags in metadata until full Tags service integration\n if (input.tags && input.tags.length > 0) {\n mutationInput.metadata = {\n tags: input.tags,\n };\n }\n\n const result = await apolloClient.mutate<{ createBigConsoleDashboard?: RawDashboardData }>({\n mutation: CreateDashboardDocument,\n variables: {\n input: mutationInput,\n },\n });\n\n if (result.data?.createBigConsoleDashboard) {\n const newDashboard = normalizeDashboard(result.data.createBigConsoleDashboard);\n await fetchDashboards();\n return newDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Update dashboard\n const updateDashboard = useCallback(\n async (input: UpdateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ updateBigConsoleDashboard?: RawDashboardData }>({\n mutation: UpdateDashboardDocument,\n variables: { input },\n });\n\n if (result.data?.updateBigConsoleDashboard) {\n const updatedDashboard = normalizeDashboard(result.data.updateBigConsoleDashboard);\n if (currentDashboard?.id === input.id) {\n setCurrentDashboard(updatedDashboard);\n }\n await fetchDashboards();\n return updatedDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to update dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Delete dashboard\n const deleteDashboard = useCallback(\n async (id: string): Promise<boolean> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ deleteBigConsoleDashboard?: boolean }>({\n mutation: DeleteDashboardDocument,\n variables: { id },\n });\n\n if (result.data?.deleteBigConsoleDashboard) {\n if (currentDashboard?.id === id) {\n setCurrentDashboard(null);\n }\n await fetchDashboards();\n return true;\n }\n\n return false;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to delete dashboard');\n setError(error);\n return false;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Refetch\n const refetch = useCallback(async () => {\n await fetchDashboards();\n }, [fetchDashboards]);\n\n // Fetch on mount\n useEffect(() => {\n fetchDashboards();\n }, [fetchDashboards]);\n\n return {\n loading,\n error,\n dashboards,\n currentDashboard,\n fetchDashboards,\n fetchDashboard,\n createDashboard,\n updateDashboard,\n deleteDashboard,\n refetch,\n };\n}\n\nexport default useDashboardOperations;\n"],"mappings":"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"}
1
+ {"version":3,"file":"useDashboardOperations.js","names":[],"sources":["../../../src/bigconsole/hooks/useDashboardOperations.ts"],"sourcesContent":["/**\n * useDashboardOperations Hook\n *\n * Provides CRUD operations for dashboards using GraphQL.\n */\n\nimport { useCallback, useState, useEffect } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport type { Dashboard, DashboardLayoutConfig, DashboardPage } from '../types';\nimport { useDashboardStore } from '../store';\nimport {\n ListDashboardsDocument,\n GetDashboardDocument,\n CreateDashboardDocument,\n UpdateDashboardDocument,\n DeleteDashboardDocument,\n CloneDashboardDocument,\n} from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardListItem {\n id: string;\n name: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n viewCount?: number;\n widgetCount?: number;\n createdAt: string;\n updatedAt: string;\n pages: DashboardPage[];\n}\n\ninterface CreateDashboardInput {\n name: string;\n description?: string;\n category?: string;\n layoutType?: string;\n tags?: string[];\n}\n\ninterface UpdateDashboardInput {\n id: string;\n name?: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n}\n\ninterface DashboardOperationsResult {\n loading: boolean;\n error: Error | null;\n dashboards: DashboardListItem[];\n currentDashboard: Dashboard | null;\n\n // Operations\n fetchDashboards: (search?: string) => Promise<void>;\n fetchDashboard: (id: string) => Promise<Dashboard | null>;\n createDashboard: (input: CreateDashboardInput) => Promise<Dashboard | null>;\n updateDashboard: (input: UpdateDashboardInput) => Promise<Dashboard | null>;\n deleteDashboard: (id: string) => Promise<boolean>;\n cloneDashboard: (sourceDashboardId: string, name: string) => Promise<Dashboard | null>;\n refetch: () => Promise<void>;\n}\n\n// ============================================================================\n// Helper: Normalize dashboard from GraphQL response\n// ============================================================================\n\n// Raw GraphQL response shape for dashboard data\ninterface RawDashboardData {\n id: string;\n name?: string;\n description?: string;\n workspaceId?: string;\n isPublic?: boolean;\n isTemplate?: boolean;\n layout?: Record<string, unknown>;\n category?: string;\n viewCount?: number;\n widgetCount?: number;\n createdBy?: string;\n ownerId?: string;\n createdAt?: string;\n updatedAt?: string;\n pages?: {\n edges?: Array<{\n node: {\n id: string;\n dashboardId?: string;\n name?: string;\n order?: number;\n layout?: Record<string, unknown>;\n gridColumns?: number;\n createdAt?: string;\n updatedAt?: string;\n };\n }>;\n };\n}\n\nfunction normalizeDashboard(data: RawDashboardData): Dashboard {\n const pages =\n data.pages?.edges?.map((edge) => ({\n id: edge.node.id,\n dashboardId: edge.node.dashboardId || data.id,\n name: edge.node.name,\n slug: edge.node.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n order: edge.node.order || 0,\n layoutConfig: edge.node.layout || {},\n gridColumns: edge.node.gridColumns || 12,\n widgets: [], // Widgets loaded separately via useWidgetOperations\n createdAt: edge.node.createdAt || new Date().toISOString(),\n updatedAt: edge.node.updatedAt || new Date().toISOString(),\n })) || [];\n\n return {\n id: data.id,\n workspaceId: data.workspaceId || '',\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n slug: data.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n isPublished: data.isPublic || false,\n isTemplate: data.isTemplate || false,\n layoutConfig: (data.layout as unknown as DashboardLayoutConfig) || {\n columns: 12,\n rowHeight: 100,\n gap: 10,\n margin: [10, 10],\n containerPadding: [10, 10],\n },\n pages,\n translations: [],\n createdBy: data.createdBy || data.ownerId || '',\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n };\n}\n\nfunction normalizeDashboardListItem(data: RawDashboardData): DashboardListItem {\n const pages =\n data.pages?.edges?.map((edge) => ({\n id: edge.node.id,\n dashboardId: edge.node.dashboardId || data.id,\n name: edge.node.name,\n slug: edge.node.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n order: edge.node.order || 0,\n layoutConfig: edge.node.layout || {},\n gridColumns: edge.node.gridColumns || 12,\n widgets: [], // Widget count not available in list query\n createdAt: edge.node.createdAt || new Date().toISOString(),\n updatedAt: edge.node.updatedAt || new Date().toISOString(),\n })) || [];\n\n return {\n id: data.id,\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n category: data.category,\n isPublic: data.isPublic,\n viewCount: data.viewCount,\n widgetCount: data.widgetCount,\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n pages,\n };\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboardOperations(): DashboardOperationsResult {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [dashboards, setDashboards] = useState<DashboardListItem[]>([]);\n\n // Get Apollo Client - will throw if not in ApolloProvider context\n const apolloClient = useApolloClient();\n\n // Store actions\n const currentDashboard = useDashboardStore((state) => state.currentDashboard);\n const setCurrentDashboard = useDashboardStore((state) => state.setCurrentDashboard);\n\n // Fetch dashboards list\n const fetchDashboards = useCallback(\n async (search?: string) => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ listDashboards?: { edges?: Array<{ node: RawDashboardData }> } }>({\n query: ListDashboardsDocument,\n variables: {\n first: 50,\n search,\n includeArchived: false,\n },\n fetchPolicy: 'network-only',\n });\n\n const edges = result.data?.listDashboards?.edges || [];\n const dashboardsList = edges.map((edge) => normalizeDashboardListItem(edge.node));\n setDashboards(dashboardsList);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboards');\n setError(error);\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Fetch single dashboard\n const fetchDashboard = useCallback(\n async (id: string): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ getDashboard?: RawDashboardData }>({\n query: GetDashboardDocument,\n variables: { id },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDashboard) {\n const dashboard = normalizeDashboard(result.data.getDashboard);\n setCurrentDashboard(dashboard);\n return dashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, setCurrentDashboard]\n );\n\n // Create dashboard\n const createDashboard = useCallback(\n async (input: CreateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n // Build mutation input\n // Note: Tags require Tag IDs from the Tags service. For now, tags are stored in metadata.\n // Full tag integration would require querying/creating tags via the Tags service first.\n const mutationInput: Record<string, unknown> = {\n name: input.name,\n description: input.description,\n category: input.category || 'CUSTOM',\n layout: input.layoutType || 'GRID',\n createDefaultPage: true,\n };\n\n // Store tags in metadata until full Tags service integration\n if (input.tags && input.tags.length > 0) {\n mutationInput.metadata = {\n tags: input.tags,\n };\n }\n\n const result = await apolloClient.mutate<{ createBigConsoleDashboard?: RawDashboardData }>({\n mutation: CreateDashboardDocument,\n variables: {\n input: mutationInput,\n },\n });\n\n if (result.data?.createBigConsoleDashboard) {\n const newDashboard = normalizeDashboard(result.data.createBigConsoleDashboard);\n await fetchDashboards();\n return newDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Update dashboard\n const updateDashboard = useCallback(\n async (input: UpdateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ updateBigConsoleDashboard?: RawDashboardData }>({\n mutation: UpdateDashboardDocument,\n variables: { input },\n });\n\n if (result.data?.updateBigConsoleDashboard) {\n const updatedDashboard = normalizeDashboard(result.data.updateBigConsoleDashboard);\n if (currentDashboard?.id === input.id) {\n setCurrentDashboard(updatedDashboard);\n }\n await fetchDashboards();\n return updatedDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to update dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Delete dashboard\n const deleteDashboard = useCallback(\n async (id: string): Promise<boolean> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ deleteBigConsoleDashboard?: boolean }>({\n mutation: DeleteDashboardDocument,\n variables: { id },\n });\n\n if (result.data?.deleteBigConsoleDashboard) {\n if (currentDashboard?.id === id) {\n setCurrentDashboard(null);\n }\n await fetchDashboards();\n return true;\n }\n\n return false;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to delete dashboard');\n setError(error);\n return false;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Clone dashboard (duplicate including widgets)\n const cloneDashboard = useCallback(\n async (sourceDashboardId: string, name: string): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ cloneDashboard?: RawDashboardData }>({\n mutation: CloneDashboardDocument,\n variables: {\n input: { sourceDashboardId, name, includeWidgets: true },\n },\n });\n\n if (result.data?.cloneDashboard) {\n const cloned = normalizeDashboard(result.data.cloneDashboard);\n await fetchDashboards();\n return cloned;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to clone dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Refetch\n const refetch = useCallback(async () => {\n await fetchDashboards();\n }, [fetchDashboards]);\n\n // Fetch on mount\n useEffect(() => {\n fetchDashboards();\n }, [fetchDashboards]);\n\n return {\n loading,\n error,\n dashboards,\n currentDashboard,\n fetchDashboards,\n fetchDashboard,\n createDashboard,\n updateDashboard,\n deleteDashboard,\n cloneDashboard,\n refetch,\n };\n}\n\nexport default useDashboardOperations;\n"],"mappings":"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"}