@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":"WidgetActions.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/widget-actions/WidgetActions.tsx"],"sourcesContent":["/**\n * Widget Actions Component (v2.0)\n *\n * Renders interactive action buttons for widgets.\n * Supports multiple action types, styles, confirmation dialogs, and icons.\n */\n\nimport React, { memo, useCallback, useState, useMemo, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetActionsProps {\n /** List of actions to render */\n actions: WidgetAction[];\n /** Action context (widget ID, data, etc.) */\n context: ActionContext;\n /** Callback when action is triggered */\n onAction?: (action: WidgetAction, context: ActionContext) => Promise<ActionResult | void>;\n /** Whether actions are disabled */\n disabled?: boolean;\n /** Layout direction */\n layout?: 'horizontal' | 'vertical';\n /** Size of action buttons */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show labels */\n showLabels?: boolean;\n /** Maximum number of visible actions (rest go to overflow menu) */\n maxVisible?: number;\n /** Custom class name */\n className?: string;\n}\n\ninterface ConfirmationDialogProps {\n title: string;\n message: string;\n confirmLabel: string;\n cancelLabel: string;\n style: WidgetAction['style'];\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n// ============================================================================\n// Style Utilities\n// ============================================================================\n\nfunction getButtonClasses(\n style: WidgetAction['style'] | undefined,\n size: 'sm' | 'md' | 'lg',\n disabled: boolean\n): string {\n const baseClasses =\n 'inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';\n\n const sizeClasses = {\n sm: 'px-2.5 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n };\n\n const styleClasses: Record<string, string> = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90 focus:ring-action-primary/50 transition-colors',\n SECONDARY: 'bg-bg-sunken text-primary hover:bg-bg-sunken/80 focus:ring-muted transition-colors',\n DANGER:\n 'bg-status-error-bg text-white hover:bg-status-error-bg/90 focus:ring-status-error-border/50 transition-colors',\n SUCCESS:\n 'bg-status-success-bg text-white hover:bg-status-success-bg/90 focus:ring-status-success-border/50 transition-colors',\n WARNING:\n 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90 focus:ring-status-warning-border/50 transition-colors',\n };\n\n const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';\n\n // Default to SECONDARY if style is undefined\n const effectiveStyle = style || 'SECONDARY';\n const styleClass = styleClasses[effectiveStyle] || styleClasses.SECONDARY;\n\n return `${baseClasses} ${sizeClasses[size]} ${styleClass} ${disabledClasses}`;\n}\n\n// Get inline styles as fallback for button visibility\nfunction getButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: { backgroundColor: 'var(--color-action-primary-bg)', color: 'var(--color-action-primary-text)' },\n SECONDARY: { backgroundColor: 'var(--color-bg-muted)', color: 'var(--color-text-primary)' },\n DANGER: { backgroundColor: 'var(--color-status-error-bg)', color: 'var(--color-action-primary-text)' },\n SUCCESS: { backgroundColor: 'var(--color-status-success-bg)', color: 'var(--color-action-primary-text)' },\n WARNING: { backgroundColor: 'var(--color-status-warning-bg)', color: 'var(--color-action-primary-text)' },\n };\n const effectiveStyle = style || 'SECONDARY';\n return styles[effectiveStyle] || styles.SECONDARY;\n}\n\nfunction getConfirmButtonClasses(style: WidgetAction['style']): string {\n const styleClasses = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90',\n SECONDARY: 'bg-secondary text-white hover:bg-secondary/90',\n DANGER: 'bg-status-error-bg text-white hover:bg-status-error-bg/90',\n SUCCESS: 'bg-status-success-bg text-white hover:bg-status-success-bg/90',\n WARNING: 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90',\n };\n\n const effectiveStyle = style || 'PRIMARY';\n return `px-4 py-2 text-sm font-medium rounded-md transition-colors ${styleClasses[effectiveStyle] || styleClasses.PRIMARY}`;\n}\n\n// Get inline styles for confirm button to ensure visibility\nfunction getConfirmButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SECONDARY: {\n backgroundColor: 'var(--color-text-secondary)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n DANGER: {\n backgroundColor: 'var(--color-status-error-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SUCCESS: {\n backgroundColor: 'var(--color-status-success-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n WARNING: {\n backgroundColor: 'var(--color-status-warning-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n };\n const effectiveStyle = style || 'PRIMARY';\n return styles[effectiveStyle] || styles.PRIMARY;\n}\n\n// ============================================================================\n// Icon Component\n// ============================================================================\n\ninterface ActionIconProps {\n name: string;\n className?: string;\n}\n\nconst ActionIcon: React.FC<ActionIconProps> = memo(function ActionIcon({ name, className = 'w-4 h-4' }) {\n // Common icons used in actions\n const icons: Record<string, React.ReactNode> = {\n 'external-link': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n ),\n save: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n ),\n trash: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n edit: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n refresh: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n download: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n ),\n upload: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12\"\n />\n </svg>\n ),\n plus: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n ),\n check: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n x: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n 'more-horizontal': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z\"\n />\n </svg>\n ),\n };\n\n return icons[name] || null;\n});\n\n// ============================================================================\n// Confirmation Dialog\n// ============================================================================\n\nconst ConfirmationDialog: React.FC<ConfirmationDialogProps> = memo(function ConfirmationDialog({\n title,\n message,\n confirmLabel,\n cancelLabel,\n style,\n onConfirm,\n onCancel,\n}) {\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50\"\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)' }}\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6 animate-in fade-in zoom-in-95 duration-200\"\n style={{\n position: 'relative',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\n maxWidth: '28rem',\n width: '100%',\n margin: '0 16px',\n padding: '24px',\n zIndex: 10000,\n }}\n >\n <h3\n className=\"text-lg font-semibold text-primary\"\n style={{ fontSize: '18px', fontWeight: 600, color: 'var(--color-text-primary)', margin: 0 }}\n >\n {title}\n </h3>\n <p\n className=\"mt-2 text-sm text-secondary\"\n style={{ marginTop: '8px', fontSize: '14px', color: 'var(--color-text-secondary)' }}\n >\n {message}\n </p>\n <div\n className=\"mt-4 flex justify-end gap-3\"\n style={{ marginTop: '16px', display: 'flex', justifyContent: 'flex-end', gap: '12px' }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-secondary bg-bg-sunken hover:bg-bg-sunken/80 rounded-md transition-colors\"\n style={{\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-bg-muted)',\n borderRadius: '6px',\n border: 'none',\n cursor: 'pointer',\n }}\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={getConfirmButtonClasses(style)}\n style={getConfirmButtonInlineStyles(style)}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Overflow Menu\n// ============================================================================\n\ninterface OverflowMenuProps {\n actions: WidgetAction[];\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n}\n\nconst OverflowMenu: React.FC<OverflowMenuProps> = memo(function OverflowMenu({\n actions,\n context: _context,\n onAction,\n disabled,\n size,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n\n const handleToggle = useCallback(() => {\n if (!disabled) {\n setIsOpen((prev) => !prev);\n }\n }, [disabled]);\n\n const handleAction = useCallback(\n (action: WidgetAction) => {\n setIsOpen(false);\n onAction(action);\n },\n [onAction]\n );\n\n const handleClickOutside = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: rect.right - 192, // 192px = w-48, align right edge\n });\n }\n }, [isOpen]);\n\n if (actions.length === 0) return null;\n\n return (\n <div className=\"relative\">\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n className={getButtonClasses('SECONDARY', size, disabled ?? false)}\n aria-label=\"More actions\"\n >\n <ActionIcon name=\"more-horizontal\" />\n </button>\n\n {isOpen &&\n createPortal(\n <>\n {/* Click-outside handler */}\n <div className=\"fixed inset-0 z-[9998]\" onClick={handleClickOutside} />\n\n {/* Menu - rendered via portal at body level */}\n <div\n className=\"fixed w-48 bg-surface rounded-md shadow-lg ring-1 ring-border z-[9999] animate-in fade-in slide-in-from-top-2 duration-150\"\n style={{\n top: menuPosition.top,\n left: Math.max(8, menuPosition.left), // Ensure at least 8px from left edge\n }}\n >\n <div className=\"py-1\">\n {actions.map((action) => (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => handleAction(action)}\n disabled={action.disabled}\n className=\"w-full text-left px-4 py-2 text-sm text-secondary hover:bg-bg-sunken hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors\"\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4\" />}\n {action.label}\n </button>\n ))}\n </div>\n </div>\n </>,\n document.body\n )}\n </div>\n );\n});\n\n// ============================================================================\n// Action Button\n// ============================================================================\n\ninterface ActionButtonProps {\n action: WidgetAction;\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n showLabel?: boolean;\n}\n\nconst ActionButton: React.FC<ActionButtonProps> = memo(function ActionButton({\n action,\n context: _context,\n onAction,\n disabled,\n size,\n showLabel = true,\n}) {\n const isDisabled = disabled || action.disabled;\n\n const handleClick = useCallback(() => {\n if (!isDisabled) {\n onAction(action);\n }\n }, [action, isDisabled, onAction]);\n\n // Get both classes and inline styles for guaranteed visibility\n const buttonClasses = getButtonClasses(action.style, size, isDisabled);\n const buttonInlineStyles = getButtonInlineStyles(action.style);\n\n // Handle LINK type\n if (action.type === 'LINK' && action.metadata?.url) {\n return (\n <a\n href={action.metadata.url as string}\n target={(action.metadata.target as string) || '_blank'}\n rel=\"noopener noreferrer\"\n className={buttonClasses}\n style={buttonInlineStyles}\n aria-disabled={isDisabled}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n {!action.icon && <ActionIcon name=\"external-link\" className=\"w-4 h-4 ml-1.5\" />}\n </a>\n );\n }\n\n return (\n <button\n type={action.type === 'SUBMIT' ? 'submit' : 'button'}\n onClick={handleClick}\n disabled={isDisabled}\n className={buttonClasses}\n style={buttonInlineStyles}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n </button>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WidgetActions: React.FC<WidgetActionsProps> = memo(function WidgetActions({\n actions,\n context,\n onAction,\n disabled = false,\n layout = 'horizontal',\n size = 'md',\n showLabels = true,\n maxVisible = 3,\n className = '',\n}) {\n const [pendingAction, setPendingAction] = useState<WidgetAction | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Filter visible actions (not hidden)\n const visibleActions = useMemo(() => {\n return actions.filter((a) => !a.hidden).sort((a, b) => a.order - b.order);\n }, [actions]);\n\n // Split into main and overflow actions\n const { mainActions, overflowActions } = useMemo(() => {\n if (visibleActions.length <= maxVisible) {\n return { mainActions: visibleActions, overflowActions: [] };\n }\n return {\n mainActions: visibleActions.slice(0, maxVisible - 1),\n overflowActions: visibleActions.slice(maxVisible - 1),\n };\n }, [visibleActions, maxVisible]);\n\n // Execute action\n const executeAction = useCallback(\n async (action: WidgetAction) => {\n if (!onAction) return;\n\n setIsLoading(true);\n try {\n await onAction(action, context);\n } catch (error) {\n } finally {\n setIsLoading(false);\n }\n },\n [onAction, context]\n );\n\n // Handle action trigger\n const handleTriggerAction = useCallback(\n (action: WidgetAction) => {\n // If action has confirmation, show dialog\n if (action.confirmation) {\n setPendingAction(action);\n return;\n }\n\n // Execute action immediately\n executeAction(action);\n },\n [executeAction]\n );\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n if (pendingAction) {\n executeAction(pendingAction);\n setPendingAction(null);\n }\n }, [pendingAction, executeAction]);\n\n const handleCancel = useCallback(() => {\n setPendingAction(null);\n }, []);\n\n // No actions to render\n if (visibleActions.length === 0) {\n return null;\n }\n\n const layoutClasses = layout === 'horizontal' ? 'flex flex-row flex-wrap gap-2' : 'flex flex-col gap-2';\n\n return (\n <>\n <div className={`${layoutClasses} ${className}`}>\n {mainActions.map((action) => (\n <ActionButton\n key={action.id}\n action={action}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n showLabel={showLabels}\n />\n ))}\n\n {overflowActions.length > 0 && (\n <OverflowMenu\n actions={overflowActions}\n context={context}\n onAction={handleTriggerAction}\n disabled={disabled || isLoading}\n size={size}\n />\n )}\n </div>\n\n {/* Confirmation Dialog */}\n {pendingAction?.confirmation && (\n <ConfirmationDialog\n title={pendingAction.confirmation.title || 'Confirm Action'}\n message={pendingAction.confirmation.message || 'Are you sure you want to proceed?'}\n confirmLabel={pendingAction.confirmation.confirmLabel || 'OK'}\n cancelLabel={pendingAction.confirmation.cancelLabel || 'Cancel'}\n style={pendingAction.style}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n )}\n </>\n );\n});\n\nexport default WidgetActions;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetActions.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/widget-actions/WidgetActions.tsx"],"sourcesContent":["/**\n * Widget Actions Component (v2.0)\n *\n * Renders interactive action buttons for widgets.\n * Supports multiple action types, styles, confirmation dialogs, and icons.\n */\n\nimport React, { memo, useCallback, useState, useMemo, useRef, useEffect } from 'react';\nimport { createPortal } from 'react-dom';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport type { WidgetAction, ActionContext, ActionResult } from '../../../renderers/types/renderer';\nimport { BIGCONSOLE_PERMISSIONS } from '../../../../constants/permissions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetActionsProps {\n /** List of actions to render */\n actions: WidgetAction[];\n /** Action context (widget ID, data, etc.) */\n context: ActionContext;\n /** Callback when action is triggered */\n onAction?: (action: WidgetAction, context: ActionContext) => Promise<ActionResult | void>;\n /** Whether actions are disabled */\n disabled?: boolean;\n /** Layout direction */\n layout?: 'horizontal' | 'vertical';\n /** Size of action buttons */\n size?: 'sm' | 'md' | 'lg';\n /** Whether to show labels */\n showLabels?: boolean;\n /** Maximum number of visible actions (rest go to overflow menu) */\n maxVisible?: number;\n /** Custom class name */\n className?: string;\n}\n\ninterface ConfirmationDialogProps {\n title: string;\n message: string;\n confirmLabel: string;\n cancelLabel: string;\n style: WidgetAction['style'];\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n// ============================================================================\n// Style Utilities\n// ============================================================================\n\nfunction getButtonClasses(\n style: WidgetAction['style'] | undefined,\n size: 'sm' | 'md' | 'lg',\n disabled: boolean\n): string {\n const baseClasses =\n 'inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';\n\n const sizeClasses = {\n sm: 'px-2.5 py-1.5 text-xs',\n md: 'px-4 py-2 text-sm',\n lg: 'px-6 py-3 text-base',\n };\n\n const styleClasses: Record<string, string> = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90 focus:ring-action-primary/50 transition-colors',\n SECONDARY: 'bg-bg-sunken text-primary hover:bg-bg-sunken/80 focus:ring-muted transition-colors',\n DANGER:\n 'bg-status-error-bg text-white hover:bg-status-error-bg/90 focus:ring-status-error-border/50 transition-colors',\n SUCCESS:\n 'bg-status-success-bg text-white hover:bg-status-success-bg/90 focus:ring-status-success-border/50 transition-colors',\n WARNING:\n 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90 focus:ring-status-warning-border/50 transition-colors',\n };\n\n const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer';\n\n // Default to SECONDARY if style is undefined\n const effectiveStyle = style || 'SECONDARY';\n const styleClass = styleClasses[effectiveStyle] || styleClasses.SECONDARY;\n\n return `${baseClasses} ${sizeClasses[size]} ${styleClass} ${disabledClasses}`;\n}\n\n// Get inline styles as fallback for button visibility\nfunction getButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: { backgroundColor: 'var(--color-action-primary-bg)', color: 'var(--color-action-primary-text)' },\n SECONDARY: { backgroundColor: 'var(--color-bg-muted)', color: 'var(--color-text-primary)' },\n DANGER: { backgroundColor: 'var(--color-status-error-bg)', color: 'var(--color-action-primary-text)' },\n SUCCESS: { backgroundColor: 'var(--color-status-success-bg)', color: 'var(--color-action-primary-text)' },\n WARNING: { backgroundColor: 'var(--color-status-warning-bg)', color: 'var(--color-action-primary-text)' },\n };\n const effectiveStyle = style || 'SECONDARY';\n return styles[effectiveStyle] || styles.SECONDARY;\n}\n\nfunction getConfirmButtonClasses(style: WidgetAction['style']): string {\n const styleClasses = {\n PRIMARY: 'bg-action-primary text-white hover:bg-action-primary/90',\n SECONDARY: 'bg-secondary text-white hover:bg-secondary/90',\n DANGER: 'bg-status-error-bg text-white hover:bg-status-error-bg/90',\n SUCCESS: 'bg-status-success-bg text-white hover:bg-status-success-bg/90',\n WARNING: 'bg-status-warning-bg text-white hover:bg-status-warning-bg/90',\n };\n\n const effectiveStyle = style || 'PRIMARY';\n return `px-4 py-2 text-sm font-medium rounded-md transition-colors ${styleClasses[effectiveStyle] || styleClasses.PRIMARY}`;\n}\n\n// Get inline styles for confirm button to ensure visibility\nfunction getConfirmButtonInlineStyles(style: WidgetAction['style'] | undefined): React.CSSProperties {\n const styles: Record<string, React.CSSProperties> = {\n PRIMARY: {\n backgroundColor: 'var(--color-action-primary-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SECONDARY: {\n backgroundColor: 'var(--color-text-secondary)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n DANGER: {\n backgroundColor: 'var(--color-status-error-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n SUCCESS: {\n backgroundColor: 'var(--color-status-success-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n WARNING: {\n backgroundColor: 'var(--color-status-warning-bg)',\n color: 'var(--color-action-primary-text)',\n padding: '8px 16px',\n borderRadius: '6px',\n fontWeight: 500,\n },\n };\n const effectiveStyle = style || 'PRIMARY';\n return styles[effectiveStyle] || styles.PRIMARY;\n}\n\n// ============================================================================\n// Icon Component\n// ============================================================================\n\ninterface ActionIconProps {\n name: string;\n className?: string;\n}\n\nconst ActionIcon: React.FC<ActionIconProps> = memo(function ActionIcon({ name, className = 'w-4 h-4' }) {\n // Common icons used in actions\n const icons: Record<string, React.ReactNode> = {\n 'external-link': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\n />\n </svg>\n ),\n save: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4\"\n />\n </svg>\n ),\n trash: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n edit: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n refresh: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n download: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4\"\n />\n </svg>\n ),\n upload: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12\"\n />\n </svg>\n ),\n plus: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n ),\n check: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n x: (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n 'more-horizontal': (\n <svg className={className} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z\"\n />\n </svg>\n ),\n };\n\n return icons[name] || null;\n});\n\n// ============================================================================\n// Confirmation Dialog\n// ============================================================================\n\nconst ConfirmationDialog: React.FC<ConfirmationDialogProps> = memo(function ConfirmationDialog({\n title,\n message,\n confirmLabel,\n cancelLabel,\n style,\n onConfirm,\n onCancel,\n}) {\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50\"\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.5)' }}\n onClick={onCancel}\n />\n\n {/* Dialog */}\n <div\n className=\"relative bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6 animate-in fade-in zoom-in-95 duration-200\"\n style={{\n position: 'relative',\n backgroundColor: 'var(--color-bg-surface)',\n borderRadius: '8px',\n boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',\n maxWidth: '28rem',\n width: '100%',\n margin: '0 16px',\n padding: '24px',\n zIndex: 10000,\n }}\n >\n <h3\n className=\"text-lg font-semibold text-primary\"\n style={{ fontSize: '18px', fontWeight: 600, color: 'var(--color-text-primary)', margin: 0 }}\n >\n {title}\n </h3>\n <p\n className=\"mt-2 text-sm text-secondary\"\n style={{ marginTop: '8px', fontSize: '14px', color: 'var(--color-text-secondary)' }}\n >\n {message}\n </p>\n <div\n className=\"mt-4 flex justify-end gap-3\"\n style={{ marginTop: '16px', display: 'flex', justifyContent: 'flex-end', gap: '12px' }}\n >\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-secondary bg-bg-sunken hover:bg-bg-sunken/80 rounded-md transition-colors\"\n style={{\n padding: '8px 16px',\n fontSize: '14px',\n fontWeight: 500,\n color: 'var(--color-text-secondary)',\n backgroundColor: 'var(--color-bg-muted)',\n borderRadius: '6px',\n border: 'none',\n cursor: 'pointer',\n }}\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={getConfirmButtonClasses(style)}\n style={getConfirmButtonInlineStyles(style)}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Overflow Menu\n// ============================================================================\n\ninterface OverflowMenuProps {\n actions: WidgetAction[];\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n}\n\nconst OverflowMenu: React.FC<OverflowMenuProps> = memo(function OverflowMenu({\n actions,\n context: _context,\n onAction,\n disabled,\n size,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n\n const handleToggle = useCallback(() => {\n if (!disabled) {\n setIsOpen((prev) => !prev);\n }\n }, [disabled]);\n\n const handleAction = useCallback(\n (action: WidgetAction) => {\n setIsOpen(false);\n onAction(action);\n },\n [onAction]\n );\n\n const handleClickOutside = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: rect.right - 192, // 192px = w-48, align right edge\n });\n }\n }, [isOpen]);\n\n if (actions.length === 0) return null;\n\n return (\n <div className=\"relative\">\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={handleToggle}\n disabled={disabled}\n className={getButtonClasses('SECONDARY', size, disabled ?? false)}\n aria-label=\"More actions\"\n >\n <ActionIcon name=\"more-horizontal\" />\n </button>\n\n {isOpen &&\n createPortal(\n <>\n {/* Click-outside handler */}\n <div className=\"fixed inset-0 z-[9998]\" onClick={handleClickOutside} />\n\n {/* Menu - rendered via portal at body level */}\n <div\n className=\"fixed w-48 bg-surface rounded-md shadow-lg ring-1 ring-border z-[9999] animate-in fade-in slide-in-from-top-2 duration-150\"\n style={{\n top: menuPosition.top,\n left: Math.max(8, menuPosition.left), // Ensure at least 8px from left edge\n }}\n >\n <div className=\"py-1\">\n {actions.map((action) => (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => handleAction(action)}\n disabled={action.disabled}\n className=\"w-full text-left px-4 py-2 text-sm text-secondary hover:bg-bg-sunken hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors\"\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4\" />}\n {action.label}\n </button>\n ))}\n </div>\n </div>\n </>,\n document.body\n )}\n </div>\n );\n});\n\n// ============================================================================\n// Action Button\n// ============================================================================\n\ninterface ActionButtonProps {\n action: WidgetAction;\n context: ActionContext;\n onAction: (action: WidgetAction) => void;\n disabled?: boolean;\n size: 'sm' | 'md' | 'lg';\n showLabel?: boolean;\n}\n\nconst ActionButton: React.FC<ActionButtonProps> = memo(function ActionButton({\n action,\n context: _context,\n onAction,\n disabled,\n size,\n showLabel = true,\n}) {\n const isDisabled = disabled || action.disabled;\n\n const handleClick = useCallback(() => {\n if (!isDisabled) {\n onAction(action);\n }\n }, [action, isDisabled, onAction]);\n\n // Get both classes and inline styles for guaranteed visibility\n const buttonClasses = getButtonClasses(action.style, size, isDisabled);\n const buttonInlineStyles = getButtonInlineStyles(action.style);\n\n // Handle LINK type\n if (action.type === 'LINK' && action.metadata?.url) {\n return (\n <a\n href={action.metadata.url as string}\n target={(action.metadata.target as string) || '_blank'}\n rel=\"noopener noreferrer\"\n className={buttonClasses}\n style={buttonInlineStyles}\n aria-disabled={isDisabled}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n {!action.icon && <ActionIcon name=\"external-link\" className=\"w-4 h-4 ml-1.5\" />}\n </a>\n );\n }\n\n return (\n <button\n type={action.type === 'SUBMIT' ? 'submit' : 'button'}\n onClick={handleClick}\n disabled={isDisabled}\n className={buttonClasses}\n style={buttonInlineStyles}\n >\n {action.icon && <ActionIcon name={action.icon} className=\"w-4 h-4 mr-1.5\" />}\n {showLabel && action.label}\n </button>\n );\n});\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\nexport const WidgetActions: React.FC<WidgetActionsProps> = memo(function WidgetActions({\n actions,\n context,\n onAction,\n disabled = false,\n layout = 'horizontal',\n size = 'md',\n showLabels = true,\n maxVisible = 3,\n className = '',\n}) {\n const [pendingAction, setPendingAction] = useState<WidgetAction | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Triggering a widget action emits `widget:<name>:clicked` (and may fire a bound\n // webhook), which is gateway-enforced by `execute`. Gate the emitting buttons on\n // the same permission. LINK actions are pure client-side navigation (they render\n // an <a> that bypasses onAction), so they stay available regardless.\n const { hasPermission } = usePermissions();\n const canExecute = hasPermission(BIGCONSOLE_PERMISSIONS.WIDGET_ACTION_EXECUTE);\n\n // Filter visible actions (not hidden)\n const visibleActions = useMemo(() => {\n return actions.filter((a) => !a.hidden).sort((a, b) => a.order - b.order);\n }, [actions]);\n\n // Split into main and overflow actions\n const { mainActions, overflowActions } = useMemo(() => {\n if (visibleActions.length <= maxVisible) {\n return { mainActions: visibleActions, overflowActions: [] };\n }\n return {\n mainActions: visibleActions.slice(0, maxVisible - 1),\n overflowActions: visibleActions.slice(maxVisible - 1),\n };\n }, [visibleActions, maxVisible]);\n\n // Execute action\n const executeAction = useCallback(\n async (action: WidgetAction) => {\n if (!onAction) return;\n\n setIsLoading(true);\n try {\n await onAction(action, context);\n } catch (error) {\n } finally {\n setIsLoading(false);\n }\n },\n [onAction, context]\n );\n\n // Handle action trigger\n const handleTriggerAction = useCallback(\n (action: WidgetAction) => {\n // If action has confirmation, show dialog\n if (action.confirmation) {\n setPendingAction(action);\n return;\n }\n\n // Execute action immediately\n executeAction(action);\n },\n [executeAction]\n );\n\n // Handle confirmation\n const handleConfirm = useCallback(() => {\n if (pendingAction) {\n executeAction(pendingAction);\n setPendingAction(null);\n }\n }, [pendingAction, executeAction]);\n\n const handleCancel = useCallback(() => {\n setPendingAction(null);\n }, []);\n\n // No actions to render\n if (visibleActions.length === 0) {\n return null;\n }\n\n const layoutClasses = layout === 'horizontal' ? 'flex flex-row flex-wrap gap-2' : 'flex flex-col gap-2';\n\n return (\n <>\n <div className={`${layoutClasses} ${className}`}>\n {mainActions.map((action) => (\n <ActionButton\n key={action.id}\n action={action}\n context={context}\n onAction={handleTriggerAction}\n // LINK actions only navigate, so they aren't execute-gated; every\n // other action emits an event on click and requires `execute`.\n disabled={disabled || isLoading || (!canExecute && action.type !== 'LINK')}\n size={size}\n showLabel={showLabels}\n />\n ))}\n\n {overflowActions.length > 0 && (\n <OverflowMenu\n actions={overflowActions}\n context={context}\n onAction={handleTriggerAction}\n // Overflow items always route through onAction (never a raw <a>), so\n // the whole menu is disabled when the caller can't execute actions.\n disabled={disabled || isLoading || !canExecute}\n size={size}\n />\n )}\n </div>\n\n {/* Confirmation Dialog */}\n {pendingAction?.confirmation && (\n <ConfirmationDialog\n title={pendingAction.confirmation.title || 'Confirm Action'}\n message={pendingAction.confirmation.message || 'Are you sure you want to proceed?'}\n confirmLabel={pendingAction.confirmation.confirmLabel || 'OK'}\n cancelLabel={pendingAction.confirmation.cancelLabel || 'Cancel'}\n style={pendingAction.style}\n onConfirm={handleConfirm}\n onCancel={handleCancel}\n />\n )}\n </>\n );\n});\n\nexport default WidgetActions;\n"],"mappings":"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"}
|
|
@@ -7,43 +7,46 @@ import r from "../hooks/useWidgetOperations.js";
|
|
|
7
7
|
import i from "../hooks/useDashboardOperations.js";
|
|
8
8
|
import a from "../hooks/usePageOperations.js";
|
|
9
9
|
import "../hooks/index.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { BIGCONSOLE_PERMISSIONS as o } from "../../constants/permissions.js";
|
|
11
|
+
import { BuilderCanvas as s } from "../components/builder/BuilderCanvas.js";
|
|
12
|
+
import { BuilderTopbar as c } from "../components/builder/BuilderTopbar.js";
|
|
13
|
+
import { DashboardEditorShell as ee } from "../components/builder/DashboardEditorShell.js";
|
|
13
14
|
import "../components/builder/index.js";
|
|
14
15
|
import { findNextAvailablePosition as l } from "../utils/widgetPositioning.js";
|
|
15
16
|
import u from "../components/dashboard/DashboardCanvas.js";
|
|
16
|
-
import
|
|
17
|
+
import te from "../components/dashboard/ExportDashboardDialog.js";
|
|
17
18
|
import "../components/dashboard/index.js";
|
|
18
|
-
import
|
|
19
|
+
import ne from "../customWidget/CustomWidgetBuilderSheet.js";
|
|
19
20
|
import "../customWidget/index.js";
|
|
20
|
-
import { memo as
|
|
21
|
-
import { useParams as
|
|
22
|
-
import {
|
|
21
|
+
import { memo as d, useCallback as f, useEffect as p, useState as m } from "react";
|
|
22
|
+
import { useParams as h } from "react-router";
|
|
23
|
+
import { AccessDenied as g } from "@burdenoff/fe-libs/shared/components";
|
|
24
|
+
import { usePermissions as _ } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
25
|
+
import { jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
23
26
|
//#region src/bigconsole/pages/DashboardBuilderPage.tsx
|
|
24
|
-
function
|
|
27
|
+
function b() {
|
|
25
28
|
try {
|
|
26
29
|
return window.__breadcrumbRegistry;
|
|
27
30
|
} catch {
|
|
28
31
|
return;
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
|
-
function
|
|
32
|
-
let n =
|
|
34
|
+
function re(e, t) {
|
|
35
|
+
let n = b();
|
|
33
36
|
n?.register && n.register(e, t);
|
|
34
37
|
}
|
|
35
|
-
function
|
|
36
|
-
let t =
|
|
38
|
+
function ie(e) {
|
|
39
|
+
let t = b();
|
|
37
40
|
t?.unregister && t.unregister(e);
|
|
38
41
|
}
|
|
39
|
-
var
|
|
40
|
-
let { dashboardId:
|
|
41
|
-
|
|
42
|
-
if (!
|
|
43
|
-
|
|
42
|
+
var x = d(function() {
|
|
43
|
+
let { dashboardId: d } = h(), b = n(), { hasPermission: x, isLoading: ae } = _(), oe = x(o.DASHBOARD_READ), se = x(o.DASHBOARD_UPDATE), S = x(o.DASHBOARD_EXPORT), C = x(o.WIDGET_CREATE), [ce, w] = m(!1), [T, E] = m(null), [D, O] = m(!1), [le, k] = m(!1), [A, j] = m(null), { fetchDashboard: M, updateDashboard: N, loading: ue, error: P } = i(), { createWidget: F, updateWidget: I, deleteWidget: L, duplicateWidget: R, batchUpdatePositions: z } = r(void 0, d), { createPage: B, updatePage: V, deletePage: H, reorderPages: U } = a(), W = t((e) => e.setCurrentDashboard), G = t((e) => e.currentDashboard), K = t((e) => e.setViewMode), q = e((e) => e.selectWidget), J = e((e) => e.widgets), Y = e((e) => e.clipboardWidgetId), X = e((e) => e.clipboardAction), Z = e((e) => e.clearClipboard);
|
|
44
|
+
p(() => (K("edit"), () => K("view")), [K]), p(() => {
|
|
45
|
+
if (!d) {
|
|
46
|
+
b("/dashboards");
|
|
44
47
|
return;
|
|
45
48
|
}
|
|
46
|
-
return
|
|
49
|
+
return M(d).then((e) => {
|
|
47
50
|
e ? (W({
|
|
48
51
|
...e,
|
|
49
52
|
title: e.name,
|
|
@@ -55,20 +58,20 @@ var S = p(function() {
|
|
|
55
58
|
index: t,
|
|
56
59
|
layoutConfig: e.layoutConfig ?? {}
|
|
57
60
|
}))
|
|
58
|
-
}), e.pages.length > 0 && !
|
|
61
|
+
}), e.pages.length > 0 && !A && j(e.pages[0].id), e.name && re(d, e.name)) : b("/dashboards");
|
|
59
62
|
}), () => {
|
|
60
|
-
|
|
63
|
+
d && ie(d);
|
|
61
64
|
};
|
|
62
65
|
}, [
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
d,
|
|
67
|
+
b,
|
|
65
68
|
W,
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
M,
|
|
70
|
+
A
|
|
68
71
|
]);
|
|
69
|
-
let Q =
|
|
70
|
-
let e =
|
|
71
|
-
if (!Y || !
|
|
72
|
+
let Q = f(async () => {
|
|
73
|
+
let e = A ?? G?.pages?.[0]?.id;
|
|
74
|
+
if (!Y || !d || !e) return;
|
|
72
75
|
let t = J.get(Y);
|
|
73
76
|
if (!t) {
|
|
74
77
|
Z();
|
|
@@ -85,7 +88,7 @@ var S = p(function() {
|
|
|
85
88
|
}, s = X === "copy" ? `${t.title} (Copy)` : t.title, c = await R(Y, o, s).catch(() => null);
|
|
86
89
|
c ||= await F({
|
|
87
90
|
pageId: e,
|
|
88
|
-
dashboardId:
|
|
91
|
+
dashboardId: d,
|
|
89
92
|
type: t.type,
|
|
90
93
|
title: s,
|
|
91
94
|
description: t.description,
|
|
@@ -101,8 +104,8 @@ var S = p(function() {
|
|
|
101
104
|
}, [
|
|
102
105
|
Y,
|
|
103
106
|
X,
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
d,
|
|
108
|
+
A,
|
|
106
109
|
G,
|
|
107
110
|
J,
|
|
108
111
|
R,
|
|
@@ -111,7 +114,7 @@ var S = p(function() {
|
|
|
111
114
|
q,
|
|
112
115
|
Z
|
|
113
116
|
]);
|
|
114
|
-
|
|
117
|
+
p(() => {
|
|
115
118
|
let n = (n) => {
|
|
116
119
|
if (t.getState().viewMode !== "edit" || n.target?.closest("input, textarea, select, [contenteditable=\"true\"]") || document.querySelector("[data-slot=\"dialog-overlay\"]")) return;
|
|
117
120
|
let r = e.getState(), i = r.selectedWidgetId;
|
|
@@ -127,11 +130,11 @@ var S = p(function() {
|
|
|
127
130
|
};
|
|
128
131
|
return document.addEventListener("keydown", n, !0), () => document.removeEventListener("keydown", n, !0);
|
|
129
132
|
}, [L, Q]);
|
|
130
|
-
let
|
|
131
|
-
|
|
132
|
-
}, [
|
|
133
|
-
if (
|
|
134
|
-
|
|
133
|
+
let $ = f(() => {
|
|
134
|
+
b("/dashboards");
|
|
135
|
+
}, [b]), de = f(async () => {
|
|
136
|
+
if (d) {
|
|
137
|
+
w(!0), E(null);
|
|
135
138
|
try {
|
|
136
139
|
let t = e.getState(), n = Array.from(t.widgets.values()), r = t.dirtyWidgetIds, i = n.filter((e) => r.has(e.id));
|
|
137
140
|
if (i.length > 0) {
|
|
@@ -155,33 +158,33 @@ var S = p(function() {
|
|
|
155
158
|
width: e.positionWidth ?? 4,
|
|
156
159
|
height: e.positionHeight ?? 4
|
|
157
160
|
}
|
|
158
|
-
}))), G && await
|
|
159
|
-
id:
|
|
161
|
+
}))), G && await N({
|
|
162
|
+
id: d,
|
|
160
163
|
name: G.title,
|
|
161
164
|
description: G.description
|
|
162
165
|
});
|
|
163
166
|
} catch (e) {
|
|
164
|
-
|
|
167
|
+
E(e instanceof Error ? e.message : "Failed to save dashboard");
|
|
165
168
|
} finally {
|
|
166
|
-
|
|
169
|
+
w(!1);
|
|
167
170
|
}
|
|
168
171
|
}
|
|
169
172
|
}, [
|
|
170
|
-
|
|
173
|
+
d,
|
|
171
174
|
G,
|
|
172
175
|
I,
|
|
173
176
|
z,
|
|
174
|
-
|
|
175
|
-
]),
|
|
176
|
-
|
|
177
|
-
}, []),
|
|
178
|
-
|
|
179
|
-
}, []),
|
|
180
|
-
|
|
181
|
-
}, []),
|
|
182
|
-
if (!G || !
|
|
177
|
+
N
|
|
178
|
+
]), fe = f(() => {
|
|
179
|
+
O(!0);
|
|
180
|
+
}, []), pe = f(() => {
|
|
181
|
+
O(!1);
|
|
182
|
+
}, []), me = f((e) => {
|
|
183
|
+
j(e);
|
|
184
|
+
}, []), he = f(async () => {
|
|
185
|
+
if (!G || !d) return;
|
|
183
186
|
let e = await B({
|
|
184
|
-
dashboardId:
|
|
187
|
+
dashboardId: d,
|
|
185
188
|
name: `Page ${G.pages.length + 1}`
|
|
186
189
|
});
|
|
187
190
|
e && (W({
|
|
@@ -192,13 +195,13 @@ var S = p(function() {
|
|
|
192
195
|
index: e.order,
|
|
193
196
|
layoutConfig: e.layoutConfig || {}
|
|
194
197
|
}]
|
|
195
|
-
}),
|
|
198
|
+
}), j(e.id));
|
|
196
199
|
}, [
|
|
197
200
|
G,
|
|
198
|
-
|
|
201
|
+
d,
|
|
199
202
|
W,
|
|
200
203
|
B
|
|
201
|
-
]),
|
|
204
|
+
]), ge = f(async (e, t) => {
|
|
202
205
|
G && await V({
|
|
203
206
|
id: e,
|
|
204
207
|
name: t
|
|
@@ -213,12 +216,12 @@ var S = p(function() {
|
|
|
213
216
|
G,
|
|
214
217
|
W,
|
|
215
218
|
V
|
|
216
|
-
]),
|
|
217
|
-
if (!G || !
|
|
219
|
+
]), _e = f(async (e) => {
|
|
220
|
+
if (!G || !d) return;
|
|
218
221
|
let t = G.pages.find((t) => t.id === e);
|
|
219
222
|
if (!t) return;
|
|
220
223
|
let n = await B({
|
|
221
|
-
dashboardId:
|
|
224
|
+
dashboardId: d,
|
|
222
225
|
name: `${t.title} (Copy)`
|
|
223
226
|
});
|
|
224
227
|
n && (W({
|
|
@@ -229,13 +232,13 @@ var S = p(function() {
|
|
|
229
232
|
index: n.order,
|
|
230
233
|
layoutConfig: n.layoutConfig || {}
|
|
231
234
|
}]
|
|
232
|
-
}),
|
|
235
|
+
}), j(n.id));
|
|
233
236
|
}, [
|
|
234
237
|
G,
|
|
235
|
-
|
|
238
|
+
d,
|
|
236
239
|
W,
|
|
237
240
|
B
|
|
238
|
-
]),
|
|
241
|
+
]), ve = f(async (e) => {
|
|
239
242
|
if (!(!G || G.pages.length <= 1) && await H(e)) {
|
|
240
243
|
let t = G.pages.filter((t) => t.id !== e).map((e, t) => ({
|
|
241
244
|
...e,
|
|
@@ -244,109 +247,115 @@ var S = p(function() {
|
|
|
244
247
|
W({
|
|
245
248
|
...G,
|
|
246
249
|
pages: t
|
|
247
|
-
}),
|
|
250
|
+
}), A === e && j(t[0]?.id || null);
|
|
248
251
|
}
|
|
249
252
|
}, [
|
|
250
253
|
G,
|
|
251
254
|
W,
|
|
252
|
-
|
|
255
|
+
A,
|
|
253
256
|
H
|
|
254
|
-
]),
|
|
255
|
-
!G || !
|
|
257
|
+
]), ye = f(async (e) => {
|
|
258
|
+
!G || !d || (W({
|
|
256
259
|
...G,
|
|
257
260
|
pages: e.map((e, t) => ({
|
|
258
261
|
...e,
|
|
259
262
|
index: t
|
|
260
263
|
}))
|
|
261
|
-
}), await U(
|
|
264
|
+
}), await U(d, e.map((e) => e.id)));
|
|
262
265
|
}, [
|
|
263
266
|
G,
|
|
264
|
-
|
|
267
|
+
d,
|
|
265
268
|
W,
|
|
266
269
|
U
|
|
267
270
|
]);
|
|
268
|
-
return
|
|
271
|
+
return ae ? /* @__PURE__ */ v("div", {
|
|
272
|
+
className: "flex items-center justify-center h-full",
|
|
273
|
+
children: /* @__PURE__ */ v("div", { className: "animate-spin w-8 h-8 border-4 border-action-primary-bg border-t-transparent rounded-full" })
|
|
274
|
+
}) : oe ? P ? /* @__PURE__ */ v("div", {
|
|
269
275
|
className: "flex flex-col items-center justify-center h-full p-6",
|
|
270
|
-
children: /* @__PURE__ */
|
|
276
|
+
children: /* @__PURE__ */ y("div", {
|
|
271
277
|
className: "bg-status-error-bg border border-status-error-border rounded-lg p-4 max-w-md",
|
|
272
278
|
children: [
|
|
273
|
-
/* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ v("h3", {
|
|
274
280
|
className: "text-sm font-medium text-status-error-text",
|
|
275
281
|
children: "Failed to load dashboard"
|
|
276
282
|
}),
|
|
277
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ v("p", {
|
|
278
284
|
className: "text-sm text-text-secondary mt-1",
|
|
279
285
|
children: P.message
|
|
280
286
|
}),
|
|
281
|
-
/* @__PURE__ */
|
|
287
|
+
/* @__PURE__ */ v("button", {
|
|
282
288
|
type: "button",
|
|
283
|
-
onClick: () =>
|
|
289
|
+
onClick: () => b("/dashboards"),
|
|
284
290
|
className: "mt-3 px-3 py-1.5 text-sm font-medium text-action-primary-fg bg-action-primary-bg hover:bg-action-primary-bgHover rounded-md",
|
|
285
291
|
children: "Back to Dashboards"
|
|
286
292
|
})
|
|
287
293
|
]
|
|
288
294
|
})
|
|
289
|
-
}) :
|
|
295
|
+
}) : ue || !G ? /* @__PURE__ */ v("div", {
|
|
290
296
|
className: "flex items-center justify-center h-full",
|
|
291
|
-
children: /* @__PURE__ */
|
|
292
|
-
}) : /* @__PURE__ */
|
|
293
|
-
topbar: /* @__PURE__ */
|
|
297
|
+
children: /* @__PURE__ */ v("div", { className: "animate-spin w-8 h-8 border-4 border-action-primary-bg border-t-transparent rounded-full" })
|
|
298
|
+
}) : /* @__PURE__ */ y(ee, {
|
|
299
|
+
topbar: /* @__PURE__ */ v(c, {
|
|
294
300
|
title: G.title || "Untitled dashboard",
|
|
295
|
-
onBack:
|
|
296
|
-
actions: /* @__PURE__ */
|
|
301
|
+
onBack: $,
|
|
302
|
+
actions: /* @__PURE__ */ y("div", {
|
|
297
303
|
className: "flex items-center gap-2",
|
|
298
|
-
children: [
|
|
304
|
+
children: [T ? /* @__PURE__ */ v("span", {
|
|
299
305
|
className: "text-xs font-medium text-status-error-text",
|
|
300
306
|
role: "alert",
|
|
301
|
-
children:
|
|
302
|
-
}) : null, /* @__PURE__ */
|
|
307
|
+
children: T
|
|
308
|
+
}) : null, C ? /* @__PURE__ */ v("button", {
|
|
303
309
|
type: "button",
|
|
304
310
|
"data-testid": "open-custom-widget-builder",
|
|
305
|
-
onClick: () =>
|
|
311
|
+
onClick: () => k(!0),
|
|
306
312
|
className: "rounded-md border border-border-default px-2 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken focus:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg",
|
|
307
313
|
children: "AI widget"
|
|
308
|
-
})]
|
|
314
|
+
}) : null]
|
|
309
315
|
})
|
|
310
316
|
}),
|
|
311
317
|
children: [
|
|
312
|
-
/* @__PURE__ */
|
|
318
|
+
/* @__PURE__ */ v(s, { canvas: /* @__PURE__ */ v(u, {
|
|
313
319
|
dashboardId: G.id,
|
|
314
|
-
pageId:
|
|
320
|
+
pageId: A || G.pages?.[0]?.id,
|
|
315
321
|
title: G.title,
|
|
316
322
|
onPaste: Q,
|
|
317
|
-
onSave:
|
|
318
|
-
isSaving:
|
|
319
|
-
onExport:
|
|
323
|
+
onSave: se ? de : void 0,
|
|
324
|
+
isSaving: ce,
|
|
325
|
+
onExport: S ? fe : void 0,
|
|
320
326
|
pages: G.pages.map((e) => ({
|
|
321
327
|
id: e.id,
|
|
322
328
|
name: e.title || `Page ${(e.index ?? 0) + 1}`,
|
|
323
329
|
order: e.index ?? 0
|
|
324
330
|
})),
|
|
325
|
-
activePageId:
|
|
326
|
-
onPageChange:
|
|
327
|
-
onPageAdd:
|
|
328
|
-
onPageRename:
|
|
329
|
-
onPageDuplicate:
|
|
330
|
-
onPageDelete:
|
|
331
|
-
onPagesReorder:
|
|
331
|
+
activePageId: A || G.pages?.[0]?.id,
|
|
332
|
+
onPageChange: me,
|
|
333
|
+
onPageAdd: he,
|
|
334
|
+
onPageRename: ge,
|
|
335
|
+
onPageDuplicate: _e,
|
|
336
|
+
onPageDelete: ve,
|
|
337
|
+
onPagesReorder: ye,
|
|
332
338
|
showPageTabs: !0
|
|
333
339
|
}) }),
|
|
334
|
-
/* @__PURE__ */
|
|
335
|
-
isOpen:
|
|
340
|
+
/* @__PURE__ */ v(te, {
|
|
341
|
+
isOpen: D,
|
|
336
342
|
dashboardId: G.id,
|
|
337
343
|
dashboardName: G.title,
|
|
338
|
-
onClose:
|
|
344
|
+
onClose: pe
|
|
339
345
|
}),
|
|
340
|
-
/* @__PURE__ */
|
|
341
|
-
isOpen:
|
|
342
|
-
onClose: () =>
|
|
346
|
+
/* @__PURE__ */ v(ne, {
|
|
347
|
+
isOpen: le,
|
|
348
|
+
onClose: () => k(!1),
|
|
343
349
|
dashboardId: G.id,
|
|
344
|
-
pageId:
|
|
350
|
+
pageId: A || G.pages?.[0]?.id || ""
|
|
345
351
|
})
|
|
346
352
|
]
|
|
353
|
+
}) : /* @__PURE__ */ v(g, {
|
|
354
|
+
title: "Access Denied",
|
|
355
|
+
description: "You don't have permission to view this dashboard."
|
|
347
356
|
});
|
|
348
357
|
});
|
|
349
358
|
//#endregion
|
|
350
|
-
export {
|
|
359
|
+
export { x as DashboardBuilderPage, x as default };
|
|
351
360
|
|
|
352
361
|
//# sourceMappingURL=DashboardBuilderPage.js.map
|