feat(client): refactor desktop-layout to ts (#42651)
Co-authored-by: moT01 <20648924+moT01@users.noreply.github.com>
This commit is contained in:
@ -1,170 +0,0 @@
|
|||||||
import { first } from 'lodash-es';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
|
|
||||||
import envData from '../../../../../config/env.json';
|
|
||||||
import { sortChallengeFiles } from '../../../../../utils/sort-challengefiles';
|
|
||||||
import EditorTabs from './EditorTabs';
|
|
||||||
import ActionRow from './action-row.tsx';
|
|
||||||
|
|
||||||
const { showUpcomingChanges } = envData;
|
|
||||||
|
|
||||||
const paneType = {
|
|
||||||
flex: PropTypes.number
|
|
||||||
};
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
block: PropTypes.string,
|
|
||||||
challengeFiles: PropTypes.array,
|
|
||||||
editor: PropTypes.element,
|
|
||||||
hasEditableBoundries: PropTypes.bool,
|
|
||||||
hasPreview: PropTypes.bool,
|
|
||||||
instructions: PropTypes.element,
|
|
||||||
layoutState: PropTypes.shape({
|
|
||||||
codePane: paneType,
|
|
||||||
editorPane: paneType,
|
|
||||||
instructionPane: paneType,
|
|
||||||
previewPane: paneType,
|
|
||||||
testsPane: paneType
|
|
||||||
}),
|
|
||||||
preview: PropTypes.element,
|
|
||||||
resizeProps: PropTypes.shape({
|
|
||||||
onStopResize: PropTypes.func,
|
|
||||||
onResize: PropTypes.func
|
|
||||||
}),
|
|
||||||
superBlock: PropTypes.string,
|
|
||||||
testOutput: PropTypes.element
|
|
||||||
};
|
|
||||||
|
|
||||||
const reflexProps = {
|
|
||||||
propagateDimensions: true
|
|
||||||
};
|
|
||||||
|
|
||||||
class DesktopLayout extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = { showNotes: false, showPreview: true, showConsole: false };
|
|
||||||
this.switchDisplayTab = this.switchDisplayTab.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
switchDisplayTab(displayTab) {
|
|
||||||
this.setState(state => {
|
|
||||||
return {
|
|
||||||
[displayTab]: !state[displayTab]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getChallengeFile() {
|
|
||||||
const { challengeFiles } = this.props;
|
|
||||||
return first(sortChallengeFiles(challengeFiles));
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
resizeProps,
|
|
||||||
instructions,
|
|
||||||
editor,
|
|
||||||
testOutput,
|
|
||||||
hasPreview,
|
|
||||||
layoutState,
|
|
||||||
preview,
|
|
||||||
hasEditableBoundries,
|
|
||||||
superBlock,
|
|
||||||
block
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { showPreview, showConsole } = this.state;
|
|
||||||
|
|
||||||
const challengeFile = this.getChallengeFile();
|
|
||||||
const projectBasedChallenge = showUpcomingChanges && hasEditableBoundries;
|
|
||||||
const isPreviewDisplayable = projectBasedChallenge
|
|
||||||
? showPreview && hasPreview
|
|
||||||
: hasPreview;
|
|
||||||
const isConsoleDisplayable = projectBasedChallenge ? showConsole : true;
|
|
||||||
const { codePane, editorPane, instructionPane, previewPane, testsPane } =
|
|
||||||
layoutState;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='desktop-layout'>
|
|
||||||
{projectBasedChallenge && (
|
|
||||||
<ActionRow
|
|
||||||
block={block}
|
|
||||||
switchDisplayTab={this.switchDisplayTab}
|
|
||||||
{...this.state}
|
|
||||||
superBlock={superBlock}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<ReflexContainer orientation='vertical'>
|
|
||||||
{!projectBasedChallenge && (
|
|
||||||
<ReflexElement
|
|
||||||
flex={instructionPane.flex}
|
|
||||||
name='instructionPane'
|
|
||||||
{...resizeProps}
|
|
||||||
>
|
|
||||||
{instructions}
|
|
||||||
</ReflexElement>
|
|
||||||
)}
|
|
||||||
{!projectBasedChallenge && (
|
|
||||||
<ReflexSplitter propagate={true} {...resizeProps} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<ReflexElement
|
|
||||||
flex={editorPane.flex}
|
|
||||||
name='editorPane'
|
|
||||||
{...resizeProps}
|
|
||||||
>
|
|
||||||
{challengeFile && showUpcomingChanges && !hasEditableBoundries && (
|
|
||||||
<EditorTabs />
|
|
||||||
)}
|
|
||||||
{challengeFile && (
|
|
||||||
<ReflexContainer
|
|
||||||
key={challengeFile.fileKey}
|
|
||||||
orientation='horizontal'
|
|
||||||
>
|
|
||||||
<ReflexElement
|
|
||||||
flex={codePane.flex}
|
|
||||||
name='codePane'
|
|
||||||
{...reflexProps}
|
|
||||||
{...resizeProps}
|
|
||||||
>
|
|
||||||
{editor}
|
|
||||||
</ReflexElement>
|
|
||||||
{isConsoleDisplayable && (
|
|
||||||
<ReflexSplitter propagate={true} {...resizeProps} />
|
|
||||||
)}
|
|
||||||
{isConsoleDisplayable && (
|
|
||||||
<ReflexElement
|
|
||||||
flex={testsPane.flex}
|
|
||||||
name='testsPane'
|
|
||||||
{...reflexProps}
|
|
||||||
{...resizeProps}
|
|
||||||
>
|
|
||||||
{testOutput}
|
|
||||||
</ReflexElement>
|
|
||||||
)}
|
|
||||||
</ReflexContainer>
|
|
||||||
)}
|
|
||||||
</ReflexElement>
|
|
||||||
{isPreviewDisplayable && (
|
|
||||||
<ReflexSplitter propagate={true} {...resizeProps} />
|
|
||||||
)}
|
|
||||||
{isPreviewDisplayable && (
|
|
||||||
<ReflexElement
|
|
||||||
flex={previewPane.flex}
|
|
||||||
name='previewPane'
|
|
||||||
{...resizeProps}
|
|
||||||
>
|
|
||||||
{preview}
|
|
||||||
</ReflexElement>
|
|
||||||
)}
|
|
||||||
</ReflexContainer>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DesktopLayout.displayName = 'DesktopLayout';
|
|
||||||
DesktopLayout.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default DesktopLayout;
|
|
@ -7,7 +7,7 @@ import EditorTabs from './EditorTabs';
|
|||||||
interface ActionRowProps {
|
interface ActionRowProps {
|
||||||
block: string;
|
block: string;
|
||||||
showConsole: boolean;
|
showConsole: boolean;
|
||||||
showNotes: boolean;
|
showNotes?: boolean;
|
||||||
showPreview: boolean;
|
showPreview: boolean;
|
||||||
superBlock: string;
|
superBlock: string;
|
||||||
switchDisplayTab: (displayTab: string) => void;
|
switchDisplayTab: (displayTab: string) => void;
|
||||||
|
160
client/src/templates/Challenges/classic/desktop-layout.tsx
Normal file
160
client/src/templates/Challenges/classic/desktop-layout.tsx
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { first } from 'lodash-es';
|
||||||
|
import React, { useState, ReactElement } from 'react';
|
||||||
|
import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
|
||||||
|
import envData from '../../../../../config/env.json';
|
||||||
|
import { sortChallengeFiles } from '../../../../../utils/sort-challengefiles';
|
||||||
|
import {
|
||||||
|
ChallengeFile,
|
||||||
|
ChallengeFiles,
|
||||||
|
ResizePropsType
|
||||||
|
} from '../../../redux/prop-types';
|
||||||
|
import EditorTabs from './EditorTabs';
|
||||||
|
import ActionRow from './action-row';
|
||||||
|
|
||||||
|
const { showUpcomingChanges } = envData;
|
||||||
|
|
||||||
|
type Pane = { flex: number };
|
||||||
|
|
||||||
|
interface DesktopLayoutProps {
|
||||||
|
block: string;
|
||||||
|
challengeFiles: ChallengeFiles;
|
||||||
|
editor: ReactElement | null;
|
||||||
|
hasEditableBoundaries: boolean;
|
||||||
|
hasPreview: boolean;
|
||||||
|
instructions: ReactElement;
|
||||||
|
layoutState: {
|
||||||
|
codePane: Pane;
|
||||||
|
editorPane: Pane;
|
||||||
|
instructionPane: Pane;
|
||||||
|
previewPane: Pane;
|
||||||
|
testsPane: Pane;
|
||||||
|
};
|
||||||
|
preview: ReactElement;
|
||||||
|
resizeProps: ResizePropsType;
|
||||||
|
superBlock: string;
|
||||||
|
testOutput: ReactElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reflexProps = {
|
||||||
|
propagateDimensions: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
|
||||||
|
const [showNotes, setShowNotes] = useState(false);
|
||||||
|
const [showPreview, setShowPreview] = useState(true);
|
||||||
|
const [showConsole, setShowConsole] = useState(false);
|
||||||
|
|
||||||
|
const switchDisplayTab = (displayTab: string): void => {
|
||||||
|
switch (displayTab) {
|
||||||
|
case 'showPreview':
|
||||||
|
setShowPreview(!showPreview);
|
||||||
|
break;
|
||||||
|
case 'showConsole':
|
||||||
|
setShowConsole(!showConsole);
|
||||||
|
break;
|
||||||
|
case 'showNotes':
|
||||||
|
setShowNotes(!showNotes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setShowConsole(false);
|
||||||
|
setShowPreview(false);
|
||||||
|
setShowNotes(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getChallengeFile = () => {
|
||||||
|
const { challengeFiles } = props;
|
||||||
|
return first(sortChallengeFiles(challengeFiles)) as ChallengeFile | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
block,
|
||||||
|
resizeProps,
|
||||||
|
instructions,
|
||||||
|
editor,
|
||||||
|
testOutput,
|
||||||
|
hasPreview,
|
||||||
|
layoutState,
|
||||||
|
preview,
|
||||||
|
hasEditableBoundaries,
|
||||||
|
superBlock
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const challengeFile = getChallengeFile();
|
||||||
|
const projectBasedChallenge = showUpcomingChanges && hasEditableBoundaries;
|
||||||
|
const isPreviewDisplayable = projectBasedChallenge
|
||||||
|
? showPreview && hasPreview
|
||||||
|
: hasPreview;
|
||||||
|
const isConsoleDisplayable = projectBasedChallenge ? showConsole : true;
|
||||||
|
const { codePane, editorPane, instructionPane, previewPane, testsPane } =
|
||||||
|
layoutState;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='desktop-layout'>
|
||||||
|
{projectBasedChallenge && (
|
||||||
|
<ActionRow
|
||||||
|
block={block}
|
||||||
|
showConsole={showConsole}
|
||||||
|
showNotes={showNotes}
|
||||||
|
showPreview={showPreview}
|
||||||
|
superBlock={superBlock}
|
||||||
|
switchDisplayTab={switchDisplayTab}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<ReflexContainer orientation='vertical'>
|
||||||
|
{!projectBasedChallenge && (
|
||||||
|
<ReflexElement flex={instructionPane.flex} {...resizeProps}>
|
||||||
|
{instructions}
|
||||||
|
</ReflexElement>
|
||||||
|
)}
|
||||||
|
{!projectBasedChallenge && (
|
||||||
|
<ReflexSplitter propagate={true} {...resizeProps} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ReflexElement flex={editorPane.flex} {...resizeProps}>
|
||||||
|
{challengeFile && showUpcomingChanges && !hasEditableBoundaries && (
|
||||||
|
<EditorTabs />
|
||||||
|
)}
|
||||||
|
{challengeFile && (
|
||||||
|
<ReflexContainer
|
||||||
|
key={challengeFile.fileKey}
|
||||||
|
orientation='horizontal'
|
||||||
|
>
|
||||||
|
<ReflexElement
|
||||||
|
flex={codePane.flex}
|
||||||
|
{...reflexProps}
|
||||||
|
{...resizeProps}
|
||||||
|
>
|
||||||
|
{editor}
|
||||||
|
</ReflexElement>
|
||||||
|
{isConsoleDisplayable && (
|
||||||
|
<ReflexSplitter propagate={true} {...resizeProps} />
|
||||||
|
)}
|
||||||
|
{isConsoleDisplayable && (
|
||||||
|
<ReflexElement
|
||||||
|
flex={testsPane.flex}
|
||||||
|
{...reflexProps}
|
||||||
|
{...resizeProps}
|
||||||
|
>
|
||||||
|
{testOutput}
|
||||||
|
</ReflexElement>
|
||||||
|
)}
|
||||||
|
</ReflexContainer>
|
||||||
|
)}
|
||||||
|
</ReflexElement>
|
||||||
|
{isPreviewDisplayable && (
|
||||||
|
<ReflexSplitter propagate={true} {...resizeProps} />
|
||||||
|
)}
|
||||||
|
{isPreviewDisplayable && (
|
||||||
|
<ReflexElement flex={previewPane.flex} {...resizeProps}>
|
||||||
|
{preview}
|
||||||
|
</ReflexElement>
|
||||||
|
)}
|
||||||
|
</ReflexContainer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
DesktopLayout.displayName = 'DesktopLayout';
|
||||||
|
|
||||||
|
export default DesktopLayout;
|
@ -44,9 +44,9 @@ import {
|
|||||||
updateChallengeMeta
|
updateChallengeMeta
|
||||||
} from '../redux';
|
} from '../redux';
|
||||||
import { getGuideUrl } from '../utils';
|
import { getGuideUrl } from '../utils';
|
||||||
import DesktopLayout from './DesktopLayout';
|
|
||||||
import MobileLayout from './MobileLayout';
|
import MobileLayout from './MobileLayout';
|
||||||
import MultifileEditor from './MultifileEditor';
|
import MultifileEditor from './MultifileEditor';
|
||||||
|
import DesktopLayout from './desktop-layout';
|
||||||
|
|
||||||
import './classic.css';
|
import './classic.css';
|
||||||
import '../components/test-frame.css';
|
import '../components/test-frame.css';
|
||||||
@ -94,7 +94,7 @@ interface ShowClassicProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ShowClassicState {
|
interface ShowClassicState {
|
||||||
layout: ReflexLayout | string;
|
layout: ReflexLayout;
|
||||||
resizing: boolean;
|
resizing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +143,9 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
|||||||
this.instructionsPanelRef = React.createRef();
|
this.instructionsPanelRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
getLayoutState(): ReflexLayout | string {
|
getLayoutState(): ReflexLayout {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
const reflexLayout: ReflexLayout | string = store.get(REFLEX_LAYOUT);
|
const reflexLayout: ReflexLayout = store.get(REFLEX_LAYOUT);
|
||||||
|
|
||||||
// Validate if user has not done any resize of the panes
|
// Validate if user has not done any resize of the panes
|
||||||
if (!reflexLayout) return BASE_LAYOUT;
|
if (!reflexLayout) return BASE_LAYOUT;
|
||||||
@ -333,7 +333,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
|||||||
containerRef={this.containerRef}
|
containerRef={this.containerRef}
|
||||||
description={description}
|
description={description}
|
||||||
editorRef={this.editorRef}
|
editorRef={this.editorRef}
|
||||||
hasEditableBoundries={this.hasEditableBoundries()}
|
hasEditableBoundaries={this.hasEditableBoundaries()}
|
||||||
initialTests={tests}
|
initialTests={tests}
|
||||||
resizeProps={this.resizeProps}
|
resizeProps={this.resizeProps}
|
||||||
title={title}
|
title={title}
|
||||||
@ -363,7 +363,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasEditableBoundries() {
|
hasEditableBoundaries() {
|
||||||
const { challengeFiles } = this.props;
|
const { challengeFiles } = this.props;
|
||||||
return (
|
return (
|
||||||
challengeFiles?.some(
|
challengeFiles?.some(
|
||||||
@ -424,7 +424,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
|||||||
block={block}
|
block={block}
|
||||||
challengeFiles={challengeFiles}
|
challengeFiles={challengeFiles}
|
||||||
editor={this.renderEditor()}
|
editor={this.renderEditor()}
|
||||||
hasEditableBoundries={this.hasEditableBoundries()}
|
hasEditableBoundaries={this.hasEditableBoundaries()}
|
||||||
hasPreview={this.hasPreview()}
|
hasPreview={this.hasPreview()}
|
||||||
instructions={this.renderInstructionsPanel({
|
instructions={this.renderInstructionsPanel({
|
||||||
showToolPanel: true
|
showToolPanel: true
|
||||||
|
Reference in New Issue
Block a user