From 2bddbbff42a8613cd7186105d3a12a2b7a45e851 Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Tue, 19 Oct 2021 15:51:38 +0100 Subject: [PATCH] feat(client): refactor desktop-layout to ts (#42651) Co-authored-by: moT01 <20648924+moT01@users.noreply.github.com> --- .../Challenges/classic/DesktopLayout.js | 170 ------------------ .../Challenges/classic/action-row.tsx | 2 +- .../Challenges/classic/desktop-layout.tsx | 160 +++++++++++++++++ .../src/templates/Challenges/classic/show.tsx | 14 +- 4 files changed, 168 insertions(+), 178 deletions(-) delete mode 100644 client/src/templates/Challenges/classic/DesktopLayout.js create mode 100644 client/src/templates/Challenges/classic/desktop-layout.tsx diff --git a/client/src/templates/Challenges/classic/DesktopLayout.js b/client/src/templates/Challenges/classic/DesktopLayout.js deleted file mode 100644 index e1e11e2b22..0000000000 --- a/client/src/templates/Challenges/classic/DesktopLayout.js +++ /dev/null @@ -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 ( -
- {projectBasedChallenge && ( - - )} - - {!projectBasedChallenge && ( - - {instructions} - - )} - {!projectBasedChallenge && ( - - )} - - - {challengeFile && showUpcomingChanges && !hasEditableBoundries && ( - - )} - {challengeFile && ( - - - {editor} - - {isConsoleDisplayable && ( - - )} - {isConsoleDisplayable && ( - - {testOutput} - - )} - - )} - - {isPreviewDisplayable && ( - - )} - {isPreviewDisplayable && ( - - {preview} - - )} - -
- ); - } -} - -DesktopLayout.displayName = 'DesktopLayout'; -DesktopLayout.propTypes = propTypes; - -export default DesktopLayout; diff --git a/client/src/templates/Challenges/classic/action-row.tsx b/client/src/templates/Challenges/classic/action-row.tsx index a569c3fcbe..41f04401a4 100644 --- a/client/src/templates/Challenges/classic/action-row.tsx +++ b/client/src/templates/Challenges/classic/action-row.tsx @@ -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; diff --git a/client/src/templates/Challenges/classic/desktop-layout.tsx b/client/src/templates/Challenges/classic/desktop-layout.tsx new file mode 100644 index 0000000000..0b969b4706 --- /dev/null +++ b/client/src/templates/Challenges/classic/desktop-layout.tsx @@ -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 ( +
+ {projectBasedChallenge && ( + + )} + + {!projectBasedChallenge && ( + + {instructions} + + )} + {!projectBasedChallenge && ( + + )} + + + {challengeFile && showUpcomingChanges && !hasEditableBoundaries && ( + + )} + {challengeFile && ( + + + {editor} + + {isConsoleDisplayable && ( + + )} + {isConsoleDisplayable && ( + + {testOutput} + + )} + + )} + + {isPreviewDisplayable && ( + + )} + {isPreviewDisplayable && ( + + {preview} + + )} + +
+ ); +}; + +DesktopLayout.displayName = 'DesktopLayout'; + +export default DesktopLayout; diff --git a/client/src/templates/Challenges/classic/show.tsx b/client/src/templates/Challenges/classic/show.tsx index 939c415ba4..340b41caa8 100644 --- a/client/src/templates/Challenges/classic/show.tsx +++ b/client/src/templates/Challenges/classic/show.tsx @@ -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 { 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 { 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 { ); } - hasEditableBoundries() { + hasEditableBoundaries() { const { challengeFiles } = this.props; return ( challengeFiles?.some( @@ -424,7 +424,7 @@ class ShowClassic extends Component { block={block} challengeFiles={challengeFiles} editor={this.renderEditor()} - hasEditableBoundries={this.hasEditableBoundries()} + hasEditableBoundaries={this.hasEditableBoundaries()} hasPreview={this.hasPreview()} instructions={this.renderInstructionsPanel({ showToolPanel: true