LCOV - code coverage report
Current view: top level - dashql-app/src/views/query_result - data_table_cell_header_name.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 98.2 % 56 55
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as arrow from 'apache-arrow';
       2              : import * as React from 'react';
       3              : import * as styles from './data_table.module.css';
       4              : import symbols from '@ankoh/dashql-svg-symbols';
       5              : 
       6              : import { classNames } from '../../utils/classnames.js';
       7              : import { ButtonSize, ButtonVariant, IconButton } from '../../ui/foundations/button.js';
       8              : import { DataFrame } from '../../compute/data_frame.js';
       9              : import { DataTableLayout } from './data_table_layout.js';
      10              : import { arePropsEqualWithStyle } from './memo_props.js';
      11              : 
      12              : /// ---------------------------------------------------------------------------
      13              : /// Header Name Cell
      14              : /// ---------------------------------------------------------------------------
      15              : 
      16              : export interface HeaderNameCellProps {
      17              :     columnIndex: number;
      18              :     style: React.CSSProperties;
      19              :     table: arrow.Table;
      20              :     gridLayout: DataTableLayout;
      21              :     dataFrame: DataFrame | null;
      22              :     rightmostVisibleColumn: number;
      23              :     sortAscending: boolean | null;
      24              :     onOrderByColumn: (col: number) => void;
      25              :     onShowTable?: () => void;
      26              : }
      27              : 
      28            1 : function HeaderNameCellImpl(props: HeaderNameCellProps): React.ReactElement {
      29            1 :     if (props.columnIndex >= props.gridLayout.arrowFieldByColumnIndex.length) {
      30            0 :         return <div style={props.style} />;
      31              :     }
      32            1 :     const fieldId = props.gridLayout.arrowFieldByColumnIndex[props.columnIndex];
      33            1 :     const fieldName = props.table.schema.fields[fieldId].name;
      34            1 :     const isSorted = props.sortAscending != null;
      35            1 :     const sortState = props.sortAscending == null ? 'unsorted' : (props.sortAscending ? 'ascending' : 'descending');
      36            1 :     const sortLabel = `Sort ${fieldName}; currently ${sortState}`;
      37            1 :     const sortIcon = props.sortAscending === false ? 'sort_desc_16' : 'sort_asc_16';
      38            1 :     const sortButtonVariant = isSorted ? ButtonVariant.Default : ButtonVariant.Invisible;
      39              : 
      40            1 :     if (props.columnIndex == 0) {
      41              :         // Corner cell (top-left)
      42            1 :         return (
      43            1 :             <div className={classNames(styles.header_corner_cell, { [styles.header_cell_clickable]: props.onShowTable != null })} style={props.style} onClick={props.onShowTable}>
      44            1 :                 <span className={styles.header_cell_actions}>
      45            1 :                     <IconButton
      46            1 :                         variant={sortButtonVariant}
      47            1 :                         size={ButtonSize.Small}
      48            1 :                         aria-label={sortLabel}
      49            1 :                         onClick={(e) => { e.stopPropagation(); props.onOrderByColumn(fieldId); }}
      50            1 :                         disabled={props.dataFrame == null}
      51              :                     >
      52            1 :                         <svg width="16px" height="16px">
      53            1 :                             <use xlinkHref={`${symbols}#${sortIcon}`} />
      54            1 :                         </svg>
      55            1 :                     </IconButton>
      56            1 :                 </span>
      57            1 :             </div>
      58              :         );
      59            1 :     } else {
      60              :         // Regular header cell
      61            1 :         const isRightmost = props.columnIndex === props.rightmostVisibleColumn;
      62            1 :         return (
      63            1 :             <div
      64            1 :                 className={classNames(styles.header_cell, {
      65            1 :                     [styles.header_metadata_cell]: props.gridLayout.isSystemColumn[props.columnIndex] == 1,
      66            1 :                     [styles.header_cell_rightmost]: isRightmost,
      67            1 :                     [styles.header_cell_clickable]: props.onShowTable != null,
      68            1 :                 })}
      69            1 :                 style={props.style}
      70            1 :                 onClick={props.onShowTable}
      71              :             >
      72            1 :                 <span className={styles.header_cell_name}>
      73            1 :                     {fieldName}
      74            1 :                 </span>
      75            1 :                 <span className={styles.header_cell_actions}>
      76            1 :                     <IconButton
      77            1 :                         variant={sortButtonVariant}
      78            1 :                         size={ButtonSize.Small}
      79            1 :                         aria-label={sortLabel}
      80            1 :                         onClick={(e) => { e.stopPropagation(); props.onOrderByColumn(fieldId); }}
      81            1 :                         disabled={props.dataFrame == null}
      82              :                     >
      83            1 :                         <svg width="16px" height="16px">
      84            1 :                             <use xlinkHref={`${symbols}#${sortIcon}`} />
      85            1 :                         </svg>
      86            1 :                     </IconButton>
      87            1 :                 </span>
      88            1 :             </div>
      89              :         );
      90            1 :     }
      91            1 : }
      92              : 
      93            1 : export const HeaderNameCell = React.memo(HeaderNameCellImpl, arePropsEqualWithStyle);
        

Generated by: LCOV version 2.0-1