LCOV - code coverage report
Current view: top level - dashql-app/src/shell_app - shell_navbar.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 96.2 % 105 101
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : 
       3              : import { AnchorAlignment, AnchorSide } from '../ui/foundations/anchored_position.js';
       4              : import { DASHQL_VERSION, HYPERDB_WASM_VERSION } from '../globals.js';
       5              : import { AnchoredOverlay } from '../ui/foundations/anchored_overlay.js';
       6              : import { ButtonVariant, IconButton } from '../ui/foundations/button.js';
       7              : import { FlavorLogo, useRequestedAppFlavor } from '../config/flavor_provider.js';
       8              : import { Tag, TagVariant } from '../ui/foundations/tag.js';
       9              : import { ShellInternals } from './internals.js';
      10              : 
      11              : import { XIcon } from '../ui/foundations/symbol_icon.js';
      12              : import symbols from '@ankoh/dashql-svg-symbols';
      13              : import * as styles from './shell_navbar.module.css';
      14              : 
      15              : interface VersionButtonProps {
      16              :     engineVersion: string | null;
      17              : }
      18              : 
      19            1 : const VersionButton: React.FC<VersionButtonProps> = (props: VersionButtonProps) => {
      20            1 :     const [isOpen, setIsOpen] = React.useState(false);
      21              : 
      22            1 :     return (
      23            1 :         <AnchoredOverlay
      24            1 :             open={isOpen}
      25            1 :             onOpen={() => setIsOpen(true)}
      26            1 :             onClose={() => setIsOpen(false)}
      27            1 :             side={AnchorSide.OutsideBottom}
      28            1 :             align={AnchorAlignment.End}
      29            1 :             anchorOffset={16}
      30            1 :             renderAnchor={(anchorProps: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
      31            1 :                 <button
      32            1 :                     {...anchorProps}
      33            1 :                     type="button"
      34            1 :                     className={styles.actionButton}
      35            1 :                     aria-label={`HyperDB WASM version ${HYPERDB_WASM_VERSION}`}
      36              :                 >
      37            1 :                     <svg className={styles.actionIcon} width="16px" height="16px" aria-hidden="true">
      38            1 :                         <use xlinkHref={`${symbols}#package`} />
      39            1 :                     </svg>
      40            1 :                     <span className={styles.actionLabel}>{HYPERDB_WASM_VERSION}</span>
      41            1 :                 </button>
      42              :             )}
      43              :         >
      44            1 :             <div className={styles.versionOverlay}>
      45            1 :                 <div className={styles.versionHeader}>
      46            1 :                     <div className={styles.versionTitle}>Version</div>
      47            1 :                     <IconButton
      48            1 :                         variant={ButtonVariant.Invisible}
      49            1 :                         aria-label="Close"
      50            1 :                         onClick={() => setIsOpen(false)}
      51              :                     >
      52            1 :                         <XIcon />
      53            1 :                     </IconButton>
      54            1 :                 </div>
      55            1 :                 <div className={styles.versionInfo}>
      56            1 :                     <div className={styles.versionLabel}>
      57            1 :                         <svg width="16px" height="16px" aria-hidden="true">
      58            1 :                             <use xlinkHref={`${symbols}#hyper_outlines`} />
      59            1 :                         </svg>
      60            1 :                         <span>hyperdb</span>
      61            1 :                     </div>
      62            1 :                     <div>{props.engineVersion ?? 'Loading...'}</div>
      63            1 :                     <a
      64            1 :                         className={styles.versionLinkButton}
      65            1 :                         href="https://www.npmjs.com/package/hyperdb-wasm"
      66            1 :                         target="_blank"
      67            1 :                         rel="noopener noreferrer"
      68            1 :                         aria-label="Open hyperdb-wasm on npm"
      69              :                     >
      70            1 :                         <svg width="16px" height="16px" aria-hidden="true">
      71            1 :                             <use xlinkHref={`${symbols}#npmjs`} />
      72            1 :                         </svg>
      73            1 :                         <span>hyperdb-wasm</span>
      74            1 :                     </a>
      75            1 :                     <div>{HYPERDB_WASM_VERSION}</div>
      76            1 :                     <a
      77            1 :                         className={styles.versionLinkButton}
      78            1 :                         href="https://github.com/ankoh/dashql"
      79            1 :                         target="_blank"
      80            1 :                         rel="noopener noreferrer"
      81            1 :                         aria-label="Open DashQL on GitHub"
      82              :                     >
      83            1 :                         <svg width="16px" height="16px" aria-hidden="true">
      84            1 :                             <use xlinkHref={`${symbols}#github`} />
      85            1 :                         </svg>
      86            1 :                         <span>dashql</span>
      87            1 :                     </a>
      88            1 :                     <div>{DASHQL_VERSION}</div>
      89            1 :                 </div>
      90            1 :             </div>
      91            1 :         </AnchoredOverlay>
      92              :     );
      93            1 : };
      94              : 
      95              : /// The height of a wordmark in the navbar
      96            1 : const WORDMARK_HEIGHT = 16;
      97              : 
      98              : /// The brand of the shell.
      99              : /// The shell is branded for Hyper, a flavor requested by the url replaces the Hyper banner with its logo and tagline.
     100            1 : const ShellBrand: React.FC = () => {
     101            1 :     const flavor = useRequestedAppFlavor();
     102            1 :     if (flavor == null) {
     103            1 :         return (
     104            1 :             <svg className={styles.brand_logo} width="100%" height="100%" aria-hidden="true">
     105            1 :                 <use xlinkHref={`${symbols}#hyper_banner`} />
     106            1 :             </svg>
     107              :         );
     108              :     }
     109            1 :     return (
     110            1 :         <span className={styles.brand_mark} data-testid="shell-flavor-brand">
     111            1 :             {flavor.logo.wordmark
     112            1 :                 ? <FlavorLogo height={WORDMARK_HEIGHT} ariaHidden />
     113            0 :                 : <>
     114            0 :                     <FlavorLogo height={24} ariaHidden />
     115            0 :                     <span>{flavor.displayName}</span>
     116            0 :                 </>}
     117            1 :             {flavor.tagline != null && (
     118            1 :                 <Tag variant={TagVariant.Outline} className={styles.brand_tagline}>{flavor.tagline}</Tag>
     119              :             )}
     120            1 :         </span>
     121              :     );
     122            1 : };
     123              : 
     124              : interface ShellNavBarProps {
     125              :     engineVersion: string | null;
     126              :     onReset: () => void;
     127              :     Internals?: React.ComponentType;
     128              : }
     129              : 
     130            1 : export const ShellNavBar: React.FC<ShellNavBarProps> = (props: ShellNavBarProps) => {
     131            1 :     const Internals = props.Internals ?? ShellInternals;
     132            1 :     return (
     133            1 :         <header className={styles.navbar}>
     134            1 :             <button
     135            1 :                 type="button"
     136            1 :                 className={styles.brand}
     137            1 :                 aria-label="Reset shell"
     138            1 :                 data-testid="shell-reset"
     139            1 :                 onClick={props.onReset}
     140              :             >
     141            1 :                 <ShellBrand />
     142            1 :             </button>
     143            1 :             <nav className={styles.actions} aria-label="Shell utilities">
     144            1 :                 <Internals />
     145            1 :                 <VersionButton engineVersion={props.engineVersion} />
     146            1 :             </nav>
     147            1 :         </header>
     148              :     );
     149            1 : };
        

Generated by: LCOV version 2.0-1