LCOV - code coverage report
Current view: top level - dashql-app/src/session/dashboard - dashboard_overlays.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 50.0 % 68 34
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : 
       3              : import { useQueryState } from '../../connections/query_executor.js';
       4              : import { ButtonSize, ButtonVariant, IconButton } from '../../ui/foundations/button.js';
       5              : import { ButtonGroup } from '../../ui/foundations/button_group.js';
       6              : import { Overlay, OverlaySize } from '../../ui/foundations/overlay.js';
       7              : import { CheckIcon, ScreenFullIcon, ScreenNormalIcon, XIcon } from '../../ui/foundations/symbol_icon.js';
       8              : import { ChartBuilderOverlay } from '../chart_builder/chart_builder_overlay.js';
       9              : import { ResultTableOverlay } from '../../views/query_result/result_table_overlay.js';
      10              : import { ScriptEditor } from '../scripts/script_editor.js';
      11              : import type { ScriptData } from '../scripts/session_scripts.js';
      12              : import { scriptDisplayName } from '../scripts/script_types.js';
      13              : import * as styles from './dashboard.module.css';
      14              : 
      15              : /// The overlay that the board shows over its cards. The board owns it, a card that gets a renderer is rendered anew
      16              : /// as a visualized card and would close an overlay of its own.
      17              : export type DashboardOverlayState = { scriptKey: number; kind: 'chart' | 'editor' | 'table' } | null;
      18              : 
      19              : interface EditorProps {
      20              :     sessionId: string;
      21              :     script: ScriptData;
      22              :     onAcceptDiff: (scriptKey: number) => void;
      23              :     onRejectDiff: (scriptKey: number) => void;
      24              :     onClose: () => void;
      25              : }
      26              : 
      27              : /// The editor of a script in an overlay over the board. A staged rewrite shows as a diff in the editor, the header
      28              : /// accepts or rejects it. The overlay expands to fill the window like the chart builder.
      29            1 : export function DashboardEditorOverlay(props: EditorProps): React.ReactElement {
      30            1 :     const displayName = scriptDisplayName(props.script.fileName);
      31            1 :     const ignoreOutsideClick = React.useCallback(() => {}, []);
      32            1 :     const [expanded, setExpanded] = React.useState(false);
      33            1 :     return (
      34            1 :         <Overlay
      35            1 :             centered
      36            1 :             width={OverlaySize.XL}
      37            1 :             height={OverlaySize.L}
      38            1 :             maxHeight={OverlaySize.L}
      39            1 :             onEscape={props.onClose}
      40            1 :             onClickOutside={ignoreOutsideClick}
      41            1 :             expanded={expanded}
      42              :         >
      43            1 :             <section className={styles.editor_dialog} role="dialog" aria-modal="true" aria-label={`Edit ${displayName}`} data-testid="dashboard-editor-overlay">
      44            1 :                 <header className={styles.editor_dialog_header}>
      45            1 :                     <h2 className={styles.card_title}>{displayName}</h2>
      46            1 :                     {props.script.pendingDiff != null && (
      47            0 :                         <ButtonGroup aria-label="Accept or reject the change">
      48            0 :                             <IconButton
      49            0 :                                 variant={ButtonVariant.Default}
      50            0 :                                 size={ButtonSize.Small}
      51            0 :                                 aria-label="Accept change"
      52            0 :                                 data-testid="dashboard-editor-accept"
      53            0 :                                 onClick={() => props.onAcceptDiff(props.script.scriptKey)}
      54              :                             >
      55            0 :                                 <CheckIcon size={14} />
      56            0 :                             </IconButton>
      57            0 :                             <IconButton
      58            0 :                                 variant={ButtonVariant.Default}
      59            0 :                                 size={ButtonSize.Small}
      60            0 :                                 aria-label="Reject change"
      61            0 :                                 data-testid="dashboard-editor-reject"
      62            0 :                                 onClick={() => props.onRejectDiff(props.script.scriptKey)}
      63              :                             >
      64            0 :                                 <XIcon size={14} />
      65            0 :                             </IconButton>
      66            0 :                         </ButtonGroup>
      67              :                     )}
      68            1 :                     <IconButton
      69            1 :                         variant={ButtonVariant.Invisible}
      70            1 :                         size={ButtonSize.Small}
      71            1 :                         aria-label={expanded ? 'Restore size' : 'Expand'}
      72            1 :                         aria-pressed={expanded}
      73            1 :                         data-testid="dashboard-editor-expand"
      74            1 :                         onClick={() => setExpanded(e => !e)}
      75              :                     >
      76            1 :                         {expanded ? <ScreenNormalIcon size={16} /> : <ScreenFullIcon size={16} />}
      77            1 :                     </IconButton>
      78            1 :                     <IconButton variant={ButtonVariant.Invisible} size={ButtonSize.Small} aria-label="Close" onClick={props.onClose}>
      79            1 :                         <XIcon size={16} />
      80            1 :                     </IconButton>
      81            1 :                 </header>
      82            1 :                 <ScriptEditor sessionId={props.sessionId} scriptKey={props.script.scriptKey} className={styles.editor_dialog_editor} />
      83            1 :             </section>
      84            1 :         </Overlay>
      85              :     );
      86            1 : }
      87              : 
      88              : interface ChartProps {
      89              :     sessionId: string;
      90              :     script: ScriptData;
      91              :     onChange: (spec: string) => void;
      92              :     onClose: () => void;
      93              : }
      94              : 
      95              : /// The chart builder of a script, the preview shows its latest result
      96            0 : export function DashboardChartOverlay(props: ChartProps): React.ReactElement {
      97            0 :     const queryState = useQueryState(props.sessionId, props.script.latestQueryId);
      98            0 :     return (
      99            0 :         <ChartBuilderOverlay
     100            0 :             scriptName={scriptDisplayName(props.script.fileName)}
     101            0 :             visualizeQuery={props.script.annotations.visualizeQuery}
     102            0 :             queryState={queryState}
     103            0 :             onChange={props.onChange}
     104            0 :             onClose={props.onClose}
     105            0 :         />
     106              :     );
     107            0 : }
     108              : 
     109              : interface TableProps {
     110              :     sessionId: string;
     111              :     script: ScriptData;
     112              :     onClose: () => void;
     113              : }
     114              : 
     115              : /// The full result table of a script, the card shows the rows that fit into it
     116            0 : export function DashboardTableOverlay(props: TableProps): React.ReactElement | null {
     117            0 :     const queryState = useQueryState(props.sessionId, props.script.latestQueryId);
     118            0 :     if (queryState == null) return null;
     119            0 :     return <ResultTableOverlay scriptName={scriptDisplayName(props.script.fileName)} query={queryState} onClose={props.onClose} />;
     120            0 : }
        

Generated by: LCOV version 2.0-1