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}
+
+
+ );
+}