-
- LogEventNum -
- {" "}
-
- {" "}
- |
- PageNum -
- {" "}
- {pageNum}
- {" "}
- | FileName -
- {" "}
- {fileName}
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- >
+
);
};
diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx
new file mode 100644
index 00000000..a519af30
--- /dev/null
+++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx
@@ -0,0 +1,70 @@
+import React, {useContext} from "react";
+
+import NavigateBefore from "@mui/icons-material/NavigateBefore";
+import NavigateNext from "@mui/icons-material/NavigateNext";
+import SkipNext from "@mui/icons-material/SkipNext";
+import SkipPrevious from "@mui/icons-material/SkipPrevious";
+
+import {StateContext} from "../../contexts/StateContextProvider";
+import {UrlContext} from "../../contexts/UrlContextProvider";
+import {
+ ACTION_NAME,
+ handleAction,
+} from "../../utils/actions";
+import PageNumInput from "./PageNumInput";
+import SmallIconButton from "./SmallIconButton";
+
+
+/**
+ * Renders a navigation bar for page switching actions.
+ *
+ * @return
+ */
+const NavigationBar = () => {
+ const {numEvents} = useContext(StateContext);
+ const {logEventNum} = useContext(UrlContext);
+
+ const handleNavButtonClick = (event: React.MouseEvent
) => {
+ if (null === logEventNum) {
+ return;
+ }
+ const {actionName} = event.currentTarget.dataset as { actionName: ACTION_NAME };
+ if (Object.values(ACTION_NAME).includes(actionName)) {
+ handleAction(actionName, logEventNum, numEvents);
+ }
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default NavigationBar;
diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.css b/new-log-viewer/src/components/MenuBar/PageNumInput.css
new file mode 100644
index 00000000..afdc3b86
--- /dev/null
+++ b/new-log-viewer/src/components/MenuBar/PageNumInput.css
@@ -0,0 +1,9 @@
+.page-num-input input::-webkit-outer-spin-button,
+.page-num-input input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+.page-num-input-num-pages-text {
+ font-size: inherit !important;
+}
diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx
new file mode 100644
index 00000000..e8ad1489
--- /dev/null
+++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx
@@ -0,0 +1,99 @@
+import React, {
+ useContext,
+ useEffect,
+ useRef,
+ useState,
+} from "react";
+
+import {Typography} from "@mui/joy";
+import Input from "@mui/joy/Input";
+
+import {StateContext} from "../../contexts/StateContextProvider";
+
+import "./PageNumInput.css";
+
+
+const PAGE_NUM_INPUT_FIT_EXTRA_WIDTH = 2;
+
+
+/**
+ * Renders a component for inputting page number.
+ *
+ * @return
+ */
+const PageNumInput = () => {
+ const {loadPage, numPages, pageNum} = useContext(StateContext);
+ const adjustedPageNum = (null === pageNum) ?
+ 0 :
+ pageNum;
+
+ const [isEditing, setIsEditing] = useState(false);
+ const inputRef = useRef(null);
+
+ const handleSubmit = (ev?: React.FormEvent) => {
+ if ("undefined" !== typeof ev) {
+ ev.preventDefault();
+ }
+ if (null === inputRef.current || false === isEditing) {
+ return;
+ }
+
+ loadPage(Number(inputRef.current.value));
+ setIsEditing(false);
+ };
+
+ const handleBlur = () => {
+ handleSubmit();
+ };
+
+ const handleInputClick = () => {
+ inputRef.current?.select();
+ };
+
+ const adjustInputWidth = () => {
+ if (null === inputRef.current) {
+ return;
+ }
+ inputRef.current.style.width = "0";
+ inputRef.current.style.width = `${inputRef.current.scrollWidth + PAGE_NUM_INPUT_FIT_EXTRA_WIDTH}px`;
+ };
+
+ const handleInputChange = () => {
+ setIsEditing(true);
+ adjustInputWidth();
+ };
+
+ useEffect(() => {
+ if (null === inputRef.current) {
+ return;
+ }
+ inputRef.current.value = adjustedPageNum.toString();
+ adjustInputWidth();
+ }, [adjustedPageNum]);
+
+ return (
+
+ );
+};
+
+export default PageNumInput;
diff --git a/new-log-viewer/src/components/MenuBar/SmallIconButton.tsx b/new-log-viewer/src/components/MenuBar/SmallIconButton.tsx
new file mode 100644
index 00000000..3fc3447e
--- /dev/null
+++ b/new-log-viewer/src/components/MenuBar/SmallIconButton.tsx
@@ -0,0 +1,16 @@
+import {IconButton} from "@mui/joy";
+
+
+/**
+ * A small JoyUI IconButton.
+ *
+ * @param props The props for IconButton.
+ * @return
+ */
+const SmallIconButton = (props: React.ComponentProps) => (
+
+);
+
+export default SmallIconButton;
diff --git a/new-log-viewer/src/components/MenuBar/index.css b/new-log-viewer/src/components/MenuBar/index.css
new file mode 100644
index 00000000..5bcdd9a5
--- /dev/null
+++ b/new-log-viewer/src/components/MenuBar/index.css
@@ -0,0 +1,6 @@
+.menu-bar {
+ display: flex;
+ flex-direction: row;
+ height: var(--ylv-status-bar-height);
+ align-items: center;
+}
diff --git a/new-log-viewer/src/components/MenuBar/index.tsx b/new-log-viewer/src/components/MenuBar/index.tsx
new file mode 100644
index 00000000..e9955286
--- /dev/null
+++ b/new-log-viewer/src/components/MenuBar/index.tsx
@@ -0,0 +1,87 @@
+import {
+ useContext,
+ useState,
+} from "react";
+
+import {
+ Divider,
+ Sheet,
+ Stack,
+ Typography,
+} from "@mui/joy";
+
+import Description from "@mui/icons-material/Description";
+import FileOpenIcon from "@mui/icons-material/FileOpen";
+import Settings from "@mui/icons-material/Settings";
+
+import {StateContext} from "../../contexts/StateContextProvider";
+import {CURSOR_CODE} from "../../typings/worker";
+import {openFile} from "../../utils/file";
+import SettingsModal from "../modals/SettingsModal";
+import NavigationBar from "./NavigationBar";
+import SmallIconButton from "./SmallIconButton";
+
+import "./index.css";
+
+
+/**
+ * Renders a menu bar which displays file information and provides navigation and settings buttons.
+ *
+ * @return
+ */
+const MenuBar = () => {
+ const {fileName, loadFile} = useContext(StateContext);
+
+ const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
+
+ const handleOpenFileButtonClick = () => {
+ openFile((file) => {
+ loadFile(file, {code: CURSOR_CODE.LAST_EVENT, args: null});
+ });
+ };
+
+ const handleSettingsModalClose = () => {
+ setIsSettingsModalOpen(false);
+ };
+
+ const handleSettingsModalOpen = () => {
+ setIsSettingsModalOpen(true);
+ };
+
+ return (
+ <>
+
+
+
+
+ {fileName}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default MenuBar;
diff --git a/new-log-viewer/src/components/StatusBar/index.css b/new-log-viewer/src/components/StatusBar/index.css
new file mode 100644
index 00000000..2f9ba8f3
--- /dev/null
+++ b/new-log-viewer/src/components/StatusBar/index.css
@@ -0,0 +1,12 @@
+.status-bar {
+ align-items: center;
+ bottom: 0;
+ display: flex;
+ position: absolute;
+ width: 100%;
+}
+
+.status-message {
+ padding-left: 8px;
+ flex-grow: 1;
+}
diff --git a/new-log-viewer/src/components/StatusBar/index.tsx b/new-log-viewer/src/components/StatusBar/index.tsx
new file mode 100644
index 00000000..1d8598f2
--- /dev/null
+++ b/new-log-viewer/src/components/StatusBar/index.tsx
@@ -0,0 +1,54 @@
+import {useContext} from "react";
+
+import Button from "@mui/joy/Button";
+import Sheet from "@mui/joy/Sheet";
+import Typography from "@mui/joy/Typography";
+
+import {StateContext} from "../../contexts/StateContextProvider";
+import {
+ copyPermalinkToClipboard,
+ UrlContext,
+} from "../../contexts/UrlContextProvider";
+
+import "./index.css";
+
+
+/**
+ * Copies the permalink to the clipboard.
+ */
+const handleCopyLinkButtonClick = () => {
+ copyPermalinkToClipboard({}, {});
+};
+
+/**
+ * StatusBar component displays the current log event number and total number of events.
+ *
+ * @return
+ */
+const StatusBar = () => {
+ const {numEvents} = useContext(StateContext);
+ const {logEventNum} = useContext(UrlContext);
+
+ return (
+
+
+ Status message
+
+
+
+ );
+};
+
+export default StatusBar;
diff --git a/new-log-viewer/src/components/modals/SettingsModal/SettingsDialog.tsx b/new-log-viewer/src/components/modals/SettingsModal/SettingsDialog.tsx
new file mode 100644
index 00000000..ac14241c
--- /dev/null
+++ b/new-log-viewer/src/components/modals/SettingsModal/SettingsDialog.tsx
@@ -0,0 +1,201 @@
+import React, {forwardRef} from "react";
+
+import {
+ Button,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ ModalDialog,
+ ToggleButtonGroup,
+ useColorScheme,
+} from "@mui/joy";
+import FormControl from "@mui/joy/FormControl/FormControl";
+import FormHelperText from "@mui/joy/FormHelperText";
+import FormLabel from "@mui/joy/FormLabel/FormLabel";
+import Input from "@mui/joy/Input";
+import type {Mode} from "@mui/system/cssVars/useCurrentColorScheme";
+
+import DarkModeIcon from "@mui/icons-material/DarkMode";
+import LightModeIcon from "@mui/icons-material/LightMode";
+import SettingsBrightnessIcon from "@mui/icons-material/SettingsBrightness";
+
+import {Nullable} from "../../../typings/common";
+import {
+ CONFIG_KEY,
+ LOCAL_STORAGE_KEY,
+ THEME_NAME,
+} from "../../../typings/config";
+import {
+ getConfig,
+ setConfig,
+} from "../../../utils/config";
+
+
+const CONFIG_FORM_FIELDS = [
+ {
+ helperText: "[JSON] Log messages conversion formats.",
+ initialValue: getConfig(CONFIG_KEY.DECODER_OPTIONS).formatString,
+ label: "Decoder: Format string",
+ name: LOCAL_STORAGE_KEY.DECODER_OPTIONS_FORMAT_STRING,
+ type: "text",
+ },
+ {
+ helperText: "[JSON] Key to extract the log level from.",
+ initialValue: getConfig(CONFIG_KEY.DECODER_OPTIONS).logLevelKey,
+ label: "Decoder: Log level key",
+ name: LOCAL_STORAGE_KEY.DECODER_OPTIONS_LOG_LEVEL_KEY,
+ type: "text",
+ },
+ {
+ helperText: "[JSON] Key to extract the log timestamp from.",
+ initialValue: getConfig(CONFIG_KEY.DECODER_OPTIONS).timestampKey,
+ label: "Decoder: Timestamp key",
+ name: LOCAL_STORAGE_KEY.DECODER_OPTIONS_TIMESTAMP_KEY,
+ type: "text",
+ },
+ {
+ helperText: "Number of log messages to display per page.",
+ initialValue: getConfig(CONFIG_KEY.PAGE_SIZE),
+ label: "View: Page size",
+ name: LOCAL_STORAGE_KEY.PAGE_SIZE,
+ type: "number",
+ },
+];
+
+/**
+ * Handles the reset event for the configuration form.
+ *
+ * @param ev
+ */
+const handleConfigFormReset = (ev: React.FormEvent) => {
+ ev.preventDefault();
+ window.localStorage.clear();
+ window.location.reload();
+};
+
+/**
+ * Handles the submit event for the configuration form.
+ *
+ * @param ev
+ */
+const handleConfigFormSubmit = (ev: React.FormEvent) => {
+ ev.preventDefault();
+ const formData = new FormData(ev.target as HTMLFormElement);
+ const getFormDataValue = (key: string) => formData.get(key) as string;
+
+ const formatString = getFormDataValue(LOCAL_STORAGE_KEY.DECODER_OPTIONS_FORMAT_STRING);
+ const logLevelKey = getFormDataValue(LOCAL_STORAGE_KEY.DECODER_OPTIONS_LOG_LEVEL_KEY);
+ const timestampKey = getFormDataValue(LOCAL_STORAGE_KEY.DECODER_OPTIONS_TIMESTAMP_KEY);
+ const pageSize = getFormDataValue(LOCAL_STORAGE_KEY.PAGE_SIZE);
+
+ let error: Nullable = null;
+ error ||= setConfig({
+ key: CONFIG_KEY.DECODER_OPTIONS,
+ value: {formatString, logLevelKey, timestampKey},
+ });
+ error ||= setConfig({
+ key: CONFIG_KEY.PAGE_SIZE,
+ value: Number(pageSize),
+ });
+
+ if (null !== error) {
+ // eslint-disable-next-line no-warning-comments
+ // TODO: Show an error pop-up once NotificationProvider is implemented.
+ // eslint-disable-next-line no-alert
+ window.alert(error);
+ } else {
+ window.location.reload();
+ }
+};
+
+/**
+ * Renders a settings dialog for configurations.
+ *
+ * @return
+ */
+const SettingsDialog = forwardRef((_, ref) => {
+ const {setMode, mode} = useColorScheme();
+
+ return (
+
+ );
+});
+
+SettingsDialog.displayName = "SettingsDialog";
+
+export default SettingsDialog;
diff --git a/new-log-viewer/src/components/modals/SettingsModal/index.css b/new-log-viewer/src/components/modals/SettingsModal/index.css
new file mode 100644
index 00000000..77ec8381
--- /dev/null
+++ b/new-log-viewer/src/components/modals/SettingsModal/index.css
@@ -0,0 +1,15 @@
+.settings-dialog-title {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+}
+
+.settings-dialog-title-text {
+ flex-grow: 1;
+ font-size: 2rem;
+}
+
+.config-form-control {
+ margin-top: 16px;
+}
diff --git a/new-log-viewer/src/components/modals/SettingsModal/index.tsx b/new-log-viewer/src/components/modals/SettingsModal/index.tsx
new file mode 100644
index 00000000..ae0e8237
--- /dev/null
+++ b/new-log-viewer/src/components/modals/SettingsModal/index.tsx
@@ -0,0 +1,32 @@
+import Modal from "@mui/joy/Modal";
+
+import SettingsDialog from "./SettingsDialog";
+
+import "./index.css";
+
+
+interface SettingsModalProps {
+ isOpen: boolean,
+ onClose: () => void
+}
+
+/**
+ * Renders a modal for setting configurations.
+ *
+ * @param props
+ * @param props.isOpen
+ * @param props.onClose
+ * @return
+ */
+const SettingsModal = ({isOpen, onClose}: SettingsModalProps) => {
+ return (
+
+
+
+ );
+};
+
+export default SettingsModal;
diff --git a/new-log-viewer/src/components/theme.tsx b/new-log-viewer/src/components/theme.tsx
new file mode 100644
index 00000000..a183c719
--- /dev/null
+++ b/new-log-viewer/src/components/theme.tsx
@@ -0,0 +1,88 @@
+import {extendTheme} from "@mui/joy/styles";
+
+import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown";
+
+
+const APP_THEME = extendTheme({
+ colorSchemes: {
+ light: {
+ palette: {
+ primary: {
+ solidBg: "#005fb8",
+ solidHoverBg: "#0258a8",
+ solidActiveBg: "#005fb8",
+ },
+ neutral: {
+ solidBg: "#e5e5e5",
+ solidHoverBg: "#cccccc",
+ solidActiveBg: "#e5e5e5",
+ solidColor: "#3b3b3b",
+ },
+ focusVisible: "#005fb8",
+ },
+ },
+ dark: {
+ palette: {
+ primary: {
+ solidBg: "#0078d4",
+ solidHoverBg: "#026ec1",
+ solidActiveBg: "#0078d4",
+ },
+ neutral: {
+ solidBg: "#181818",
+ solidHoverBg: "#323232",
+ solidActiveBg: "#181818",
+ },
+ focusVisible: "#0078d4",
+ },
+ },
+ },
+ focus: {
+ default: {
+ outlineWidth: "3px",
+ },
+ },
+ fontFamily: {
+ body: "var(--ylv-ui-font-family)",
+ },
+ components: {
+ JoyButton: {
+ styleOverrides: {
+ root: {
+ borderRadius: "2px",
+ },
+ },
+ },
+ JoySelect: {
+ defaultProps: {
+ indicator: ,
+ },
+ styleOverrides: {
+ root: {
+ borderRadius: "2px",
+ },
+ },
+ },
+ JoyInput: {
+ styleOverrides: {
+ root: {
+ borderRadius: "2px",
+ },
+ },
+ },
+ JoyFormControl: {
+ styleOverrides: {
+ root: ({theme}) => ({
+ [theme.getColorSchemeSelector("dark")]: {
+ ":hover": {backgroundColor: "#232424"},
+ },
+ [theme.getColorSchemeSelector("light")]: {
+ ":hover": {backgroundColor: "#f8f8f8"},
+ },
+ }),
+ },
+ },
+ },
+});
+
+export default APP_THEME;
diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx
index bf3d4ec0..5d506d2c 100644
--- a/new-log-viewer/src/contexts/StateContextProvider.tsx
+++ b/new-log-viewer/src/contexts/StateContextProvider.tsx
@@ -38,6 +38,7 @@ interface StateContextType {
beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap,
fileName: string,
loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void,
+ loadPage: (newPageNum: number) => void,
logData: string,
numEvents: number,
numPages: number,
@@ -52,6 +53,7 @@ const STATE_DEFAULT: Readonly = Object.freeze({
beginLineNumToLogEventNum: new Map(),
fileName: "",
loadFile: () => null,
+ loadPage: () => null,
logData: "Loading...",
numEvents: 0,
numPages: 0,
@@ -124,6 +126,7 @@ const workerPostReq = (
* @param props.children
* @return
*/
+// eslint-disable-next-line max-lines-per-function
const StateContextProvider = ({children}: StateContextProviderProps) => {
const {filePath, logEventNum} = useContext(UrlContext);
@@ -186,6 +189,18 @@ const StateContextProvider = ({children}: StateContextProviderProps) => {
handleMainWorkerResp,
]);
+ const loadPage = (newPageNum: number) => {
+ if (null === mainWorkerRef.current) {
+ console.error("Unexpected null mainWorkerRef.current");
+
+ return;
+ }
+ workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, {
+ cursor: {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum}},
+ decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS),
+ });
+ };
+
// Synchronize `logEventNumRef` with `logEventNum`.
useEffect(() => {
logEventNumRef.current = logEventNum;
@@ -202,7 +217,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => {
// On `logEventNum` update, clamp it then switch page if necessary or simply update the URL.
useEffect(() => {
- if (null === mainWorkerRef.current || URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum) {
+ if (URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum) {
return;
}
@@ -221,10 +236,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => {
// NOTE: We don't need to call `updateLogEventNumInUrl()` since it's called when
// handling the `WORKER_RESP_CODE.PAGE_DATA` response (the response to
// `WORKER_REQ_CODE.LOAD_PAGE` requests) .
- workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, {
- cursor: {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum}},
- decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS),
- });
+ loadPage(newPageNum);
}
}
@@ -264,6 +276,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => {
beginLineNumToLogEventNum: beginLineNumToLogEventNumRef.current,
fileName: fileName,
loadFile: loadFile,
+ loadPage: loadPage,
logData: logData,
numEvents: numEvents,
numPages: numPagesRef.current,
diff --git a/new-log-viewer/src/index.css b/new-log-viewer/src/index.css
index b21e3278..22de1ccc 100644
--- a/new-log-viewer/src/index.css
+++ b/new-log-viewer/src/index.css
@@ -13,6 +13,10 @@ html {
--ylv-ui-font-family: -apple-system, BlinkMacSystemFont, system-ui, Ubuntu, "Droid Sans",
Roboto;
+ /* size globals */
+ --ylv-status-bar-height: 32px;
+ --ylv-menu-bar-height: 32px;
+
/* z-index globals
*
* Other z-index values in the project for reference:
diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts
index 65810e9c..cded5069 100644
--- a/new-log-viewer/src/utils/actions.ts
+++ b/new-log-viewer/src/utils/actions.ts
@@ -1,6 +1,13 @@
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
+import {updateWindowUrlHashParams} from "../contexts/UrlContextProvider";
import {Nullable} from "../typings/common";
+import {CONFIG_KEY} from "../typings/config";
+import {getConfig} from "./config";
+import {
+ getFirstItemNumInNextChunk,
+ getLastItemNumInPrevChunk,
+} from "./math";
enum ACTION_NAME {
@@ -62,8 +69,40 @@ const EDITOR_ACTIONS : ActionType[] = [
];
/* eslint-enable sort-keys */
+/**
+ * Handles an action based on the given action name, log event number, and total number of events.
+ *
+ * @param actionName
+ * @param logEventNum
+ * @param numEvents
+ */
+const handleAction = (actionName: ACTION_NAME, logEventNum: number, numEvents: number) => {
+ const pageSize = getConfig(CONFIG_KEY.PAGE_SIZE);
+ switch (actionName) {
+ case ACTION_NAME.FIRST_PAGE:
+ updateWindowUrlHashParams({logEventNum: 1});
+ break;
+ case ACTION_NAME.PREV_PAGE:
+ updateWindowUrlHashParams({
+ logEventNum: getLastItemNumInPrevChunk(logEventNum, pageSize),
+ });
+ break;
+ case ACTION_NAME.NEXT_PAGE:
+ updateWindowUrlHashParams({
+ logEventNum: getFirstItemNumInNextChunk(logEventNum, pageSize),
+ });
+ break;
+ case ACTION_NAME.LAST_PAGE:
+ updateWindowUrlHashParams({logEventNum: numEvents});
+ break;
+ default:
+ break;
+ }
+};
+
export {
ACTION_NAME,
EDITOR_ACTIONS,
+ handleAction,
};
export type {ActionType};
diff --git a/new-log-viewer/src/utils/config.ts b/new-log-viewer/src/utils/config.ts
index 895c1950..0661702d 100644
--- a/new-log-viewer/src/utils/config.ts
+++ b/new-log-viewer/src/utils/config.ts
@@ -41,10 +41,7 @@ const testConfig = ({key, value}: ConfigUpdate): Nullable => {
}
break;
case CONFIG_KEY.THEME:
- if (false === (Object.values(THEME_NAME)).includes(value)) {
- result = "Invalid theme name.";
- }
- break;
+ throw new Error(`${key} should be handled by JoyUI instead.`);
case CONFIG_KEY.PAGE_SIZE:
if (0 >= value || MAX_PAGE_SIZE < value) {
result = `Page size must be greater than 0 and less than ${MAX_PAGE_SIZE + 1}.`;
@@ -89,8 +86,7 @@ const setConfig = ({key, value}: ConfigUpdate): Nullable => {
);
break;
case CONFIG_KEY.THEME:
- window.localStorage.setItem(LOCAL_STORAGE_KEY.THEME, value);
- break;
+ throw new Error(`${key} should be handled by JoyUI instead.`);
case CONFIG_KEY.PAGE_SIZE:
window.localStorage.setItem(LOCAL_STORAGE_KEY.PAGE_SIZE, value.toString());
break;
@@ -124,10 +120,8 @@ const getConfig = (key: T): ConfigMap[T] => {
),
} as DecoderOptionsType;
break;
- case CONFIG_KEY.THEME: {
- value = window.localStorage.getItem(LOCAL_STORAGE_KEY.THEME);
- break;
- }
+ case CONFIG_KEY.THEME:
+ throw new Error(`${key} should be handled by JoyUI instead.`);
case CONFIG_KEY.PAGE_SIZE:
value = window.localStorage.getItem(LOCAL_STORAGE_KEY.PAGE_SIZE);
break;