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 {
|
||||
block: string;
|
||||
showConsole: boolean;
|
||||
showNotes: boolean;
|
||||
showNotes?: boolean;
|
||||
showPreview: boolean;
|
||||
superBlock: string;
|
||||
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
|
||||
} from '../redux';
|
||||
import { getGuideUrl } from '../utils';
|
||||
import DesktopLayout from './DesktopLayout';
|
||||
import MobileLayout from './MobileLayout';
|
||||
import MultifileEditor from './MultifileEditor';
|
||||
import DesktopLayout from './desktop-layout';
|
||||
|
||||
import './classic.css';
|
||||
import '../components/test-frame.css';
|
||||
@ -94,7 +94,7 @@ interface ShowClassicProps {
|
||||
}
|
||||
|
||||
interface ShowClassicState {
|
||||
layout: ReflexLayout | string;
|
||||
layout: ReflexLayout;
|
||||
resizing: boolean;
|
||||
}
|
||||
|
||||
@ -143,9 +143,9 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
this.instructionsPanelRef = React.createRef();
|
||||
}
|
||||
|
||||
getLayoutState(): ReflexLayout | string {
|
||||
getLayoutState(): ReflexLayout {
|
||||
// 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
|
||||
if (!reflexLayout) return BASE_LAYOUT;
|
||||
@ -333,7 +333,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
containerRef={this.containerRef}
|
||||
description={description}
|
||||
editorRef={this.editorRef}
|
||||
hasEditableBoundries={this.hasEditableBoundries()}
|
||||
hasEditableBoundaries={this.hasEditableBoundaries()}
|
||||
initialTests={tests}
|
||||
resizeProps={this.resizeProps}
|
||||
title={title}
|
||||
@ -363,7 +363,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
);
|
||||
}
|
||||
|
||||
hasEditableBoundries() {
|
||||
hasEditableBoundaries() {
|
||||
const { challengeFiles } = this.props;
|
||||
return (
|
||||
challengeFiles?.some(
|
||||
@ -424,7 +424,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
block={block}
|
||||
challengeFiles={challengeFiles}
|
||||
editor={this.renderEditor()}
|
||||
hasEditableBoundries={this.hasEditableBoundries()}
|
||||
hasEditableBoundaries={this.hasEditableBoundaries()}
|
||||
hasPreview={this.hasPreview()}
|
||||
instructions={this.renderInstructionsPanel({
|
||||
showToolPanel: true
|
||||
|
Reference in New Issue
Block a user