Skip to content

Commit 76f70bc

Browse files
authored
new-log-viewer: Persist active tab across sessions. (#93)
1 parent 02a80c8 commit 76f70bc

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

new-log-viewer/src/components/CentralContainer/Sidebar/index.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import {
22
useCallback,
3+
useEffect,
4+
useMemo,
35
useRef,
46
useState,
57
} from "react";
68

9+
import {CONFIG_KEY} from "../../../typings/config";
710
import {TAB_NAME} from "../../../typings/tab";
11+
import {
12+
getConfig,
13+
setConfig,
14+
} from "../../../utils/config";
815
import ResizeHandle from "./ResizeHandle";
916
import SidebarTabs from "./SidebarTabs";
1017

@@ -42,8 +49,8 @@ const setPanelWidth = (newValue: number) => {
4249
* @return
4350
*/
4451
const Sidebar = () => {
45-
const [activeTabName, setActiveTabName] = useState<TAB_NAME>(TAB_NAME.FILE_INFO);
46-
52+
const initialTabName = useMemo(() => getConfig(CONFIG_KEY.INITIAL_TAB_NAME), []);
53+
const [activeTabName, setActiveTabName] = useState<TAB_NAME>(initialTabName);
4754
const tabListRef = useRef<HTMLDivElement>(null);
4855

4956
const handleActiveTabNameChange = useCallback((tabName: TAB_NAME) => {
@@ -53,14 +60,15 @@ const Sidebar = () => {
5360
return;
5461
}
5562

63+
let newTabName = tabName;
64+
let newPanelWidth = PANEL_DEFAULT_WIDTH_IN_PIXELS;
5665
if (activeTabName === tabName) {
57-
setActiveTabName(TAB_NAME.NONE);
58-
setPanelWidth(tabListRef.current.clientWidth);
59-
60-
return;
66+
newTabName = TAB_NAME.NONE;
67+
newPanelWidth = tabListRef.current.clientWidth;
6168
}
62-
setActiveTabName(tabName);
63-
setPanelWidth(PANEL_DEFAULT_WIDTH_IN_PIXELS);
69+
setActiveTabName(newTabName);
70+
setConfig({key: CONFIG_KEY.INITIAL_TAB_NAME, value: newTabName});
71+
setPanelWidth(newPanelWidth);
6472
}, [activeTabName]);
6573

6674
const handleResizeHandleRelease = useCallback(() => {
@@ -92,6 +100,18 @@ const Sidebar = () => {
92100
}
93101
}, []);
94102

103+
// On initialization, do not show panel if there is no active tab.
104+
useEffect(() => {
105+
if (null === tabListRef.current) {
106+
console.error("Unexpected null tabListRef.current");
107+
108+
return;
109+
}
110+
if (TAB_NAME.NONE === initialTabName) {
111+
setPanelWidth(tabListRef.current.clientWidth);
112+
}
113+
}, [initialTabName]);
114+
95115
return (
96116
<div className={"sidebar-tabs-container"}>
97117
<SidebarTabs

new-log-viewer/src/typings/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {JsonlDecoderOptionsType} from "./decoders";
2+
import {TAB_NAME} from "./tab";
23

34

45
enum THEME_NAME {
@@ -9,6 +10,7 @@ enum THEME_NAME {
910

1011
enum CONFIG_KEY {
1112
DECODER_OPTIONS = "decoderOptions",
13+
INITIAL_TAB_NAME = "initialTabName",
1214
THEME = "theme",
1315
PAGE_SIZE = "pageSize",
1416
}
@@ -18,13 +20,15 @@ enum LOCAL_STORAGE_KEY {
1820
DECODER_OPTIONS_FORMAT_STRING = `${CONFIG_KEY.DECODER_OPTIONS}/formatString`,
1921
DECODER_OPTIONS_LOG_LEVEL_KEY = `${CONFIG_KEY.DECODER_OPTIONS}/logLevelKey`,
2022
DECODER_OPTIONS_TIMESTAMP_KEY = `${CONFIG_KEY.DECODER_OPTIONS}/timestampKey`,
23+
INITIAL_TAB_NAME = CONFIG_KEY.INITIAL_TAB_NAME,
2124
THEME = CONFIG_KEY.THEME,
2225
PAGE_SIZE = CONFIG_KEY.PAGE_SIZE,
2326
}
2427
/* eslint-enable @typescript-eslint/prefer-literal-enum-member */
2528

2629
type ConfigMap = {
2730
[CONFIG_KEY.DECODER_OPTIONS]: JsonlDecoderOptionsType,
31+
[CONFIG_KEY.INITIAL_TAB_NAME]: TAB_NAME,
2832
[CONFIG_KEY.THEME]: THEME_NAME,
2933
[CONFIG_KEY.PAGE_SIZE]: number,
3034
};

new-log-viewer/src/utils/config.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
THEME_NAME,
88
} from "../typings/config";
99
import {DecoderOptionsType} from "../typings/decoders";
10+
import {TAB_NAME} from "../typings/tab";
1011

1112

1213
const EXPORT_LOGS_CHUNK_SIZE = 10_000;
@@ -22,6 +23,7 @@ const CONFIG_DEFAULT: ConfigMap = Object.freeze({
2223
logLevelKey: "log.level",
2324
timestampKey: "@timestamp",
2425
},
26+
[CONFIG_KEY.INITIAL_TAB_NAME]: TAB_NAME.FILE_INFO,
2527
[CONFIG_KEY.THEME]: THEME_NAME.SYSTEM,
2628
[CONFIG_KEY.PAGE_SIZE]: 10_000,
2729
});
@@ -43,6 +45,9 @@ const testConfig = ({key, value}: ConfigUpdate): Nullable<string> => {
4345
result = "Decoder options cannot be empty.";
4446
}
4547
break;
48+
case CONFIG_KEY.INITIAL_TAB_NAME:
49+
// This config option is not intended for direct user input.
50+
break;
4651
case CONFIG_KEY.THEME:
4752
throw new Error(`"${key}" cannot be managed using these utilities.`);
4853
case CONFIG_KEY.PAGE_SIZE:
@@ -89,6 +94,9 @@ const setConfig = ({key, value}: ConfigUpdate): Nullable<string> => {
8994
value.timestampKey
9095
);
9196
break;
97+
case CONFIG_KEY.INITIAL_TAB_NAME:
98+
window.localStorage.setItem(CONFIG_KEY.INITIAL_TAB_NAME, value.toString());
99+
break;
92100
case CONFIG_KEY.THEME:
93101
throw new Error(`"${key}" cannot be managed using these utilities.`);
94102
case CONFIG_KEY.PAGE_SIZE:
@@ -125,6 +133,9 @@ const getConfig = <T extends CONFIG_KEY>(key: T): ConfigMap[T] => {
125133
),
126134
} as DecoderOptionsType;
127135
break;
136+
case CONFIG_KEY.INITIAL_TAB_NAME:
137+
value = window.localStorage.getItem(LOCAL_STORAGE_KEY.INITIAL_TAB_NAME);
138+
break;
128139
case CONFIG_KEY.THEME:
129140
throw new Error(`"${key}" cannot be managed using these utilities.`);
130141
case CONFIG_KEY.PAGE_SIZE:

0 commit comments

Comments
 (0)