Skip to content

Commit

Permalink
feat(client): save challenge layout in local storage (again) (freeCod…
Browse files Browse the repository at this point in the history
  • Loading branch information
ojeytonwilliams authored Jul 25, 2024
1 parent 0eebe3e commit cda00d4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 27 deletions.
17 changes: 15 additions & 2 deletions client/src/templates/Challenges/classic/desktop-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
<ReflexElement
flex={instructionPane.flex}
{...resizeProps}
name='instructionPane'
data-playwright-test-label='instruction-pane'
>
{instructions}
Expand All @@ -226,6 +227,7 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {

<ReflexElement
flex={editorPane.flex}
name='editorPane'
{...resizeProps}
data-playwright-test-label='editor-pane'
>
Expand All @@ -236,6 +238,7 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
>
<ReflexElement
flex={codePane.flex}
name='codePane'
{...reflexProps}
{...resizeProps}
>
Expand All @@ -258,17 +261,26 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
</ReflexElement>
{displayNotes && <ReflexSplitter propagate={true} {...resizeProps} />}
{displayNotes && (
<ReflexElement flex={notesPane.flex} {...resizeProps}>
<ReflexElement
name='notesPane'
flex={notesPane.flex}
{...resizeProps}
>
<Notes notes={notes} />
</ReflexElement>
)}

{(displayPreviewPane || displayPreviewConsole) && (
<ReflexSplitter propagate={true} {...resizeProps} />
<ReflexSplitter
data-playwright-test-label='preview-left-splitter'
propagate={true}
{...resizeProps}
/>
)}
{(displayPreviewPane || displayPreviewConsole) && (
<ReflexElement
flex={previewPane.flex}
name='previewPane'
{...resizeProps}
data-playwright-test-label='preview-pane'
>
Expand All @@ -279,6 +291,7 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
)}
{displayPreviewConsole && (
<ReflexElement
name='testsPane'
{...(displayPreviewPane && { flex: testsPane.flex })}
{...resizeProps}
>
Expand Down
40 changes: 15 additions & 25 deletions client/src/templates/Challenges/classic/show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,18 +244,16 @@ function ShowClassic({
challengeTypes.python
].includes(challengeType);
const getLayoutState = () => {
const reflexLayout = store.get(REFLEX_LAYOUT) as ReflexLayout;

// Validate if user has not done any resize of the panes
if (!reflexLayout) return BASE_LAYOUT;
const reflexLayout = store.get(REFLEX_LAYOUT) as ReflexLayout | null;

// Check that the layout values stored are valid (exist in base layout). If
// not valid, it will fallback to the base layout values and be set on next
// user resize.
const isValidLayout = isContained(
Object.keys(BASE_LAYOUT),
Object.keys(reflexLayout)
);
const isValidLayout =
reflexLayout &&
isContained(Object.keys(BASE_LAYOUT), Object.keys(reflexLayout));

if (!isValidLayout) store.remove(REFLEX_LAYOUT);

return isValidLayout ? reflexLayout : BASE_LAYOUT;
};
Expand All @@ -266,25 +264,17 @@ function ShowClassic({
const [layout, setLayout] = useState(getLayoutState());

const onStopResize = (event: HandlerProps) => {
const { name, flex } = event.component.props;

// Only interested in tracking layout updates for ReflexElement's
if (!name) {
setResizing(false);
return;
}

// Forcing a state update with the value of each panel since on stop resize
// is executed per each panel.
if (typeof layout === 'object') {
setLayout({
...layout,
[name]: { flex }
});
}
setResizing(false);
// 'name' is used to identify the Elements whose layout is stored.
const { name, flex } = event.component.props;

store.set(REFLEX_LAYOUT, layout);
// onStopResize can be called multiple times before the state changes, so
// we need an updater function to ensure all updates are applied.
setLayout(l => {
const newLayout = name ? { ...l, [name]: { flex } } : l;
store.set(REFLEX_LAYOUT, newLayout);
return newLayout;
});
};

const setHtmlHeight = () => {
Expand Down
30 changes: 30 additions & 0 deletions e2e/multifile-editor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,34 @@ test.describe('MultifileEditor Component', () => {
index++;
}
});

test('Reloading should preserve the editor layout', async ({
page,
isMobile
}) => {
test.skip(
isMobile,
'The mobile layout does not have resizable panes, so this test is not applicable.'
);

const desktopLayout = page.getByTestId('desktop-layout');
const splitter = desktopLayout.getByTestId('preview-left-splitter');
const editorPane = desktopLayout.getByTestId('editor-pane');
const initialStyle = await editorPane.getAttribute('style');
expect(initialStyle).toContain('flex: 1');

// Drag the splitter to resize the editor pane
await splitter.hover();
await page.mouse.down();
await page.mouse.move(100, 100);
await page.mouse.up();

const newStyle = await editorPane.getAttribute('style');
// It doesn't matter where it's dragged to, just that it's different:
expect(newStyle).not.toContain('flex: 1');

await page.reload();

expect(await editorPane.getAttribute('style')).toBe(newStyle);
});
});

0 comments on commit cda00d4

Please sign in to comment.