Skip to content

Commit 7de171c

Browse files
authored
Merge pull request #78 from topcoder-platform/TCA-443_persist-layout-in-localstorage
TCA-443 - persist layout selection in localstorage
2 parents b98dcb1 + 75a05df commit 7de171c

File tree

3 files changed

+74
-32
lines changed

3 files changed

+74
-32
lines changed

client/src/templates/Challenges/classic/action-row.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
33

44
import BreadCrumb from '../components/bread-crumb';
55
import EditorTabs from './editor-tabs';
6+
import { DesktopLayoutPanels } from './use-desktop-layout-state';
67

78
interface ActionRowProps {
89
block: string;
@@ -14,7 +15,7 @@ interface ActionRowProps {
1415
showInstructions: boolean;
1516
showPreview: boolean;
1617
superBlock: string;
17-
togglePane: (pane: string) => void;
18+
togglePane: (pane: DesktopLayoutPanels) => void;
1819
showBreadcrumbs?: boolean;
1920
}
2021

@@ -46,7 +47,7 @@ const ActionRow = ({
4647
className={
4748
showInstructions ? 'btn-tab-primary' : 'btn-tab-primary--outline'
4849
}
49-
onClick={() => togglePane('showInstructions')}
50+
onClick={() => togglePane(DesktopLayoutPanels.Instructions)}
5051
>
5152
{t('learn.editor-tabs.instructions')}
5253
</button>
@@ -57,7 +58,7 @@ const ActionRow = ({
5758
className={
5859
showConsole ? 'btn-tab-primary' : 'btn-tab-primary--outline'
5960
}
60-
onClick={() => togglePane('showConsole')}
61+
onClick={() => togglePane(DesktopLayoutPanels.Console)}
6162
>
6263
{t('learn.editor-tabs.console')}
6364
</button>
@@ -67,7 +68,7 @@ const ActionRow = ({
6768
className={
6869
showNotes ? 'btn-tab-primary' : 'btn-tab-primary--outline'
6970
}
70-
onClick={() => togglePane('showNotes')}
71+
onClick={() => togglePane(DesktopLayoutPanels.Notes)}
7172
>
7273
{t('learn.editor-tabs.notes')}
7374
</button>
@@ -78,7 +79,7 @@ const ActionRow = ({
7879
className={
7980
showPreview ? 'btn-tab-primary' : 'btn-tab-primary--outline'
8081
}
81-
onClick={() => togglePane('showPreview')}
82+
onClick={() => togglePane(DesktopLayoutPanels.Preview)}
8283
>
8384
{t('learn.editor-tabs.preview')}
8485
</button>

client/src/templates/Challenges/classic/desktop-layout.tsx

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { first } from 'lodash-es';
2-
import React, { useState, ReactElement } from 'react';
2+
import React, { ReactElement } from 'react';
33
import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
44
import { sortChallengeFiles } from '../../../../../utils/sort-challengefiles';
55
import { GoogleTagManager } from '../../../analytics/google-tag-manater';
@@ -10,6 +10,7 @@ import {
1010
ResizeProps
1111
} from '../../../redux/prop-types';
1212
import ActionRow from './action-row';
13+
import { useDesktopLayoutState } from './use-desktop-layout-state';
1314

1415
type Pane = { flex: number };
1516

@@ -43,32 +44,10 @@ const reflexProps = {
4344
};
4445

4546
const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
46-
const [showInstructions, setShowInstructions] = useState(true);
47-
const [showNotes, setShowNotes] = useState(false);
48-
const [showPreview, setShowPreview] = useState(true);
49-
const [showConsole, setShowConsole] = useState(false);
50-
51-
const togglePane = (pane: string): void => {
52-
switch (pane) {
53-
case 'showInstructions':
54-
setShowInstructions(!showInstructions);
55-
break;
56-
case 'showPreview':
57-
setShowPreview(!showPreview);
58-
break;
59-
case 'showConsole':
60-
setShowConsole(!showConsole);
61-
break;
62-
case 'showNotes':
63-
setShowNotes(!showNotes);
64-
break;
65-
default:
66-
setShowInstructions(false);
67-
setShowConsole(false);
68-
setShowPreview(false);
69-
setShowNotes(false);
70-
}
71-
};
47+
const {
48+
layoutState: { showInstructions, showNotes, showPreview, showConsole },
49+
togglePane
50+
} = useDesktopLayoutState();
7251

7352
const getChallengeFile = () => {
7453
const { challengeFiles } = props;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { useReducer } from 'react';
2+
3+
const STORAGE_KEY = 'fcc:desktop:layout:state';
4+
5+
export enum DesktopLayoutPanels {
6+
Instructions = 'showInstructions',
7+
Notes = 'showNotes',
8+
Preview = 'showPreview',
9+
Console = 'showConsole'
10+
}
11+
12+
interface DesktopLayoutState {
13+
[DesktopLayoutPanels.Instructions]: boolean;
14+
[DesktopLayoutPanels.Notes]: boolean;
15+
[DesktopLayoutPanels.Preview]: boolean;
16+
[DesktopLayoutPanels.Console]: boolean;
17+
}
18+
19+
const defaultLayoutState: DesktopLayoutState = {
20+
[DesktopLayoutPanels.Instructions]: true,
21+
[DesktopLayoutPanels.Notes]: false,
22+
[DesktopLayoutPanels.Preview]: true,
23+
[DesktopLayoutPanels.Console]: false
24+
};
25+
26+
const readFromStorage = (
27+
defaultState: DesktopLayoutState
28+
): DesktopLayoutState => {
29+
const lsData = localStorage.getItem(STORAGE_KEY);
30+
31+
try {
32+
return (JSON.parse(lsData ?? '') as DesktopLayoutState) || defaultState;
33+
} catch {
34+
return defaultState;
35+
}
36+
};
37+
38+
const layoutReducer = (
39+
state: DesktopLayoutState,
40+
panel: DesktopLayoutPanels
41+
) => {
42+
const nextState = {
43+
...state,
44+
[panel]: !state[panel]
45+
};
46+
47+
localStorage.setItem(STORAGE_KEY, JSON.stringify(nextState));
48+
49+
return nextState;
50+
};
51+
52+
export const useDesktopLayoutState = () => {
53+
const [layoutState, dispatch] = useReducer(
54+
layoutReducer,
55+
readFromStorage(defaultLayoutState)
56+
);
57+
58+
return {
59+
layoutState,
60+
togglePane: dispatch
61+
};
62+
};

0 commit comments

Comments
 (0)