diff --git a/docs/APP_REFACTORING_DESIGN.md b/docs/APP_REFACTORING_DESIGN.md index 83e7d3c..a7b8fb4 100644 --- a/docs/APP_REFACTORING_DESIGN.md +++ b/docs/APP_REFACTORING_DESIGN.md @@ -80,7 +80,7 @@ To refactor `app.tsx` safely and maintain continuous code correctness, we will m ### Step-by-Step Execution Plan #### Phase 1: Pure Component and Utility Extraction -* [ ] **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`. * [ ] **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. * [ ] **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. diff --git a/src/app.tsx b/src/app.tsx index 4057ff4..cced8e9 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,15 +1,9 @@ import * as H from 'history'; import queryString from 'query-string'; import {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {FormattedMessage, useIntl} from 'react-intl'; +import {useIntl} from 'react-intl'; import {Navigate, Route, Routes, useLocation, useNavigate} from 'react-router'; -import { - Loader, - Message, - Portal, - SidebarPushable, - SidebarPusher, -} from 'semantic-ui-react'; +import {Loader, SidebarPushable, SidebarPusher} from 'semantic-ui-react'; import {IndiInfo} from 'topola'; import { Chart, @@ -19,6 +13,7 @@ import { downloadSvg, printChart, } from './chart'; +import {ErrorMessage, ErrorPopup} from './components/error_display'; import {DataSourceEnum, SourceSelection} from './datasource/data_source'; import {EmbeddedDataSource, EmbeddedSourceSpec} from './datasource/embedded'; import { @@ -87,43 +82,6 @@ function getStaticUrl(): string | undefined { const staticUrl = getStaticUrl(); -/** Shows an error message in the middle of the screen. */ -function ErrorMessage(props: {message?: string}) { - return ( - - - - -

{props.message}

-
- ); -} - -interface ErrorPopupProps { - message?: string; - open: boolean; - onDismiss: () => void; -} - -/** - * Shows a dismissable error message in the bottom left corner of the screen. - */ -function ErrorPopup(props: ErrorPopupProps) { - return ( - - - - - -

{props.message}

-
-
- ); -} - enum AppState { INITIAL, LOADING, diff --git a/src/components/error_display.tsx b/src/components/error_display.tsx new file mode 100644 index 0000000..643e933 --- /dev/null +++ b/src/components/error_display.tsx @@ -0,0 +1,39 @@ +import {FormattedMessage} from 'react-intl'; +import {Message, Portal} from 'semantic-ui-react'; + +/** Shows an error message in the middle of the screen. */ +export function ErrorMessage(props: {message?: string}) { + return ( + + + + +

{props.message}

+
+ ); +} + +export interface ErrorPopupProps { + message?: string; + open: boolean; + onDismiss: () => void; +} + +/** + * Shows a dismissable error message in the bottom left corner of the screen. + */ +export function ErrorPopup(props: ErrorPopupProps) { + return ( + + + + + +

{props.message}

+
+
+ ); +}