make chart-specific props and event handlers optional

This commit is contained in:
Przemek Więch
2026-06-10 19:37:54 +02:00
parent fa6c7f9ff1
commit 4fa8695904
2 changed files with 18 additions and 16 deletions

View File

@@ -83,7 +83,7 @@ To refactor `app.tsx` safely and maintain continuous code correctness, we will m
* [x] **Step 1.1:** Create `src/components/error_display.tsx` and move `ErrorMessage` and `ErrorPopup` from `src/app.tsx`. Update imports in `src/app.tsx`. * [x] **Step 1.1:** Create `src/components/error_display.tsx` and move `ErrorMessage` and `ErrorPopup` from `src/app.tsx`. Update imports in `src/app.tsx`.
* [x] **Step 1.2:** Create `src/datasource/instances.ts` and move data source class instantiations. Update references in `src/app.tsx`. Refactor `EmbeddedDataSource` to clean up its message event listener when the loading promise resolves or rejects (or track listener state) to prevent duplicate event listener leaks on multiple page mounts. * [x] **Step 1.2:** Create `src/datasource/instances.ts` and move data source class instantiations. Update references in `src/app.tsx`. Refactor `EmbeddedDataSource` to clean up its message event listener when the loading promise resolves or rejects (or track listener state) to prevent duplicate event listener leaks on multiple page mounts.
* [x] **Step 1.3:** Create `src/util/url_args.ts` (the parsing utility) and `src/util/url_args.spec.ts` (its Jest unit test suite) together. Extract URL query parameter parsing functions and types from `src/app.tsx`, write comprehensive tests, update imports in `src/app.tsx`, and run `npm test` to verify. * [x] **Step 1.3:** Create `src/util/url_args.ts` (the parsing utility) and `src/util/url_args.spec.ts` (its Jest unit test suite) together. Extract URL query parameter parsing functions and types from `src/app.tsx`, write comprehensive tests, update imports in `src/app.tsx`, and run `npm test` to verify.
* [ ] **Step 1.4:** Modify `src/menu/top_bar.tsx` to make chart-specific props and event handlers optional (e.g. `data`, `allowAllRelativesChart`, `allowPrintAndDownload`, `eventHandlers`, etc.), preparing the component for rendering on the landing screen without dummy properties. * [x] **Step 1.4:** Modify `src/menu/top_bar.tsx` to make chart-specific props and event handlers optional (e.g. `data`, `allowAllRelativesChart`, `allowPrintAndDownload`, `eventHandlers`, etc.), preparing the component for rendering on the landing screen without dummy properties.
#### Phase 2: WebMCP Bridge Extraction #### Phase 2: WebMCP Bridge Extraction
* [ ] **Step 2.1:** Create `src/hooks/use_webmcp_bridge.ts` wrapping WebMCP registration and synchronization effects. * [ ] **Step 2.1:** Create `src/hooks/use_webmcp_bridge.ts` wrapping WebMCP registration and synchronization effects.

View File

@@ -32,13 +32,13 @@ interface Props {
data?: JsonGedcomData; data?: JsonGedcomData;
standalone: boolean; standalone: boolean;
/** Whether to show the "All relatives" chart type in the menu. */ /** Whether to show the "All relatives" chart type in the menu. */
allowAllRelativesChart: boolean; allowAllRelativesChart?: boolean;
allowPrintAndDownload: boolean; allowPrintAndDownload?: boolean;
eventHandlers: EventHandlers; eventHandlers?: EventHandlers;
/** Whether to show additional WikiTree menus. */ /** Whether to show additional WikiTree menus. */
showWikiTreeMenus: boolean; showWikiTreeMenus?: boolean;
/** Whether the user has authorized Google Drive and has an active token. */ /** Whether the user has authorized Google Drive and has an active token. */
hasGoogleToken: boolean; hasGoogleToken?: boolean;
/** Callback to sign out of Google Drive. */ /** Callback to sign out of Google Drive. */
onGoogleSignOut?: () => void; onGoogleSignOut?: () => void;
/** Callback triggered when a new Google Drive token is acquired. */ /** Callback triggered when a new Google Drive token is acquired. */
@@ -101,7 +101,7 @@ export function TopBar(props: Props) {
return ( return (
<> <>
<Menu.Item <Menu.Item
onClick={props.eventHandlers.onPrint} onClick={props.eventHandlers?.onPrint}
disabled={!props.allowPrintAndDownload} disabled={!props.allowPrintAndDownload}
> >
<Icon name="print" /> <Icon name="print" />
@@ -122,19 +122,19 @@ export function TopBar(props: Props) {
disabled={!props.allowPrintAndDownload} disabled={!props.allowPrintAndDownload}
> >
<Dropdown.Menu> <Dropdown.Menu>
<Dropdown.Item onClick={props.eventHandlers.onDownloadPdf}> <Dropdown.Item onClick={props.eventHandlers?.onDownloadPdf}>
<FormattedMessage <FormattedMessage
id="menu.pdf_file" id="menu.pdf_file"
defaultMessage="PDF file" defaultMessage="PDF file"
/> />
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item onClick={props.eventHandlers.onDownloadPng}> <Dropdown.Item onClick={props.eventHandlers?.onDownloadPng}>
<FormattedMessage <FormattedMessage
id="menu.png_file" id="menu.png_file"
defaultMessage="PNG file" defaultMessage="PNG file"
/> />
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item onClick={props.eventHandlers.onDownloadSvg}> <Dropdown.Item onClick={props.eventHandlers?.onDownloadSvg}>
<FormattedMessage <FormattedMessage
id="menu.svg_file" id="menu.svg_file"
defaultMessage="SVG file" defaultMessage="SVG file"
@@ -156,7 +156,9 @@ export function TopBar(props: Props) {
</Dropdown> </Dropdown>
<SearchBar <SearchBar
data={props.data} data={props.data}
onSelection={props.eventHandlers.onSelection} onSelection={
props.eventHandlers?.onSelection || (() => undefined)
}
{...props} {...props}
/> />
</> </>
@@ -165,28 +167,28 @@ export function TopBar(props: Props) {
case ScreenSize.SMALL: case ScreenSize.SMALL:
return ( return (
<> <>
<Dropdown.Item onClick={props.eventHandlers.onPrint}> <Dropdown.Item onClick={props.eventHandlers?.onPrint}>
<Icon name="print" /> <Icon name="print" />
<FormattedMessage id="menu.print" defaultMessage="Print" /> <FormattedMessage id="menu.print" defaultMessage="Print" />
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Divider /> <Dropdown.Divider />
<Dropdown.Item onClick={props.eventHandlers.onDownloadPdf}> <Dropdown.Item onClick={props.eventHandlers?.onDownloadPdf}>
<Icon name="download" /> <Icon name="download" />
<FormattedMessage <FormattedMessage
id="menu.download_pdf" id="menu.download_pdf"
defaultMessage="Download PDF" defaultMessage="Download PDF"
/> />
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item onClick={props.eventHandlers.onDownloadPng}> <Dropdown.Item onClick={props.eventHandlers?.onDownloadPng}>
<Icon name="download" /> <Icon name="download" />
<FormattedMessage <FormattedMessage
id="menu.download_png" id="menu.download_png"
defaultMessage="Download PNG" defaultMessage="Download PNG"
/> />
</Dropdown.Item> </Dropdown.Item>
<Dropdown.Item onClick={props.eventHandlers.onDownloadSvg}> <Dropdown.Item onClick={props.eventHandlers?.onDownloadSvg}>
<Icon name="download" /> <Icon name="download" />
<FormattedMessage <FormattedMessage
id="menu.download_svg" id="menu.download_svg"
@@ -351,7 +353,7 @@ export function TopBar(props: Props) {
{props.showingChart && props.data && ( {props.showingChart && props.data && (
<SearchBar <SearchBar
data={props.data} data={props.data}
onSelection={props.eventHandlers.onSelection} onSelection={props.eventHandlers?.onSelection || (() => undefined)}
{...props} {...props}
/> />
)} )}