mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
fix: refactor it
This commit is contained in:
@@ -342,6 +342,7 @@ export type ChallengeMeta = {
|
||||
block: string;
|
||||
id: string;
|
||||
introPath: string;
|
||||
isFirstStep: boolean;
|
||||
nextChallengePath: string;
|
||||
prevChallengePath: string;
|
||||
removeComments: boolean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { first } from 'lodash-es';
|
||||
import React, { useState, ReactElement } from 'react';
|
||||
import React, { useState, useEffect, ReactElement } from 'react';
|
||||
import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
|
||||
import { createSelector } from 'reselect';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -29,6 +29,7 @@ interface DesktopLayoutProps {
|
||||
hasNotes: boolean;
|
||||
hasPreview: boolean;
|
||||
instructions: ReactElement;
|
||||
isFirstStep: boolean;
|
||||
layoutState: {
|
||||
codePane: Pane;
|
||||
editorPane: Pane;
|
||||
@@ -90,12 +91,12 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
|
||||
const togglePane = (pane: string): void => {
|
||||
switch (pane) {
|
||||
case 'showPreviewPane':
|
||||
if (!showPreviewPane && showPreviewPortal) setShowPreviewPortal(false);
|
||||
setShowPreviewPane(!showPreviewPane);
|
||||
if (showPreviewPortal) setShowPreviewPortal(false);
|
||||
portalWindow?.close();
|
||||
setShowPreviewPane(!showPreviewPane);
|
||||
break;
|
||||
case 'showPreviewPortal':
|
||||
if (!showPreviewPortal && showPreviewPane) setShowPreviewPane(false);
|
||||
if (showPreviewPane) setShowPreviewPane(false);
|
||||
setShowPreviewPortal(!showPreviewPortal);
|
||||
if (showPreviewPortal) portalWindow?.close();
|
||||
break;
|
||||
@@ -130,6 +131,7 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
|
||||
testOutput,
|
||||
hasNotes,
|
||||
hasPreview,
|
||||
isFirstStep,
|
||||
layoutState,
|
||||
notes,
|
||||
preview,
|
||||
@@ -137,6 +139,16 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
|
||||
windowTitle
|
||||
} = props;
|
||||
|
||||
// on mount
|
||||
useEffect(() => {
|
||||
if (isFirstStep) {
|
||||
setShowPreviewPortal(false);
|
||||
portalWindow?.close();
|
||||
setShowPreviewPane(true);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const challengeFile = getChallengeFile();
|
||||
const projectBasedChallenge = hasEditableBoundaries;
|
||||
const isMultifileCertProject =
|
||||
|
||||
@@ -480,7 +480,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
const {
|
||||
executeChallenge,
|
||||
pageContext: {
|
||||
challengeMeta: { nextChallengePath, prevChallengePath },
|
||||
challengeMeta: { isFirstStep, nextChallengePath, prevChallengePath },
|
||||
projectPreview: { challengeData, showProjectPreview }
|
||||
},
|
||||
challengeFiles,
|
||||
@@ -539,6 +539,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
|
||||
instructions={this.renderInstructionsPanel({
|
||||
showToolPanel: true
|
||||
})}
|
||||
isFirstStep={isFirstStep}
|
||||
layoutState={this.state.layout}
|
||||
notes={this.renderNotes(notes)}
|
||||
preview={this.renderPreview()}
|
||||
|
||||
@@ -6,11 +6,13 @@ import { createSelector } from 'reselect';
|
||||
import {
|
||||
storePortalWindow,
|
||||
removePortalWindow,
|
||||
setIsAdvancing
|
||||
setShowPreviewPane,
|
||||
setShowPreviewPortal
|
||||
} from '../redux/actions';
|
||||
import {
|
||||
portalWindowSelector,
|
||||
isAdvancingToChallengeSelector
|
||||
showPreviewPaneSelector,
|
||||
showPreviewPortalSelector
|
||||
} from '../redux/selectors';
|
||||
|
||||
interface PreviewPortalProps {
|
||||
@@ -21,21 +23,30 @@ interface PreviewPortalProps {
|
||||
storePortalWindow: (window: Window | null) => void;
|
||||
removePortalWindow: () => void;
|
||||
portalWindow: null | Window;
|
||||
setIsAdvancing: (arg: boolean) => void;
|
||||
isAdvancing: boolean;
|
||||
setShowPreviewPane: (arg: boolean) => void;
|
||||
setShowPreviewPortal: (arg: boolean) => void;
|
||||
showPreviewPane: boolean;
|
||||
showPreviewPortal: boolean;
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
storePortalWindow,
|
||||
removePortalWindow,
|
||||
setIsAdvancing
|
||||
setShowPreviewPane,
|
||||
setShowPreviewPortal
|
||||
};
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
isAdvancingToChallengeSelector,
|
||||
showPreviewPaneSelector,
|
||||
showPreviewPortalSelector,
|
||||
portalWindowSelector,
|
||||
(isAdvancing: boolean, portalWindow: null | Window) => ({
|
||||
isAdvancing,
|
||||
(
|
||||
showPreviewPane: boolean,
|
||||
showPreviewPortal: boolean,
|
||||
portalWindow: null | Window
|
||||
) => ({
|
||||
showPreviewPane,
|
||||
showPreviewPortal,
|
||||
portalWindow
|
||||
})
|
||||
);
|
||||
@@ -44,7 +55,8 @@ class PreviewPortal extends Component<PreviewPortalProps> {
|
||||
static displayName = 'PreviewPortal';
|
||||
mainWindow: Window;
|
||||
externalWindow: Window | null = null;
|
||||
isAdvancing: boolean;
|
||||
showPreviewPane: boolean;
|
||||
showPreviewPortal: boolean;
|
||||
containerEl;
|
||||
titleEl;
|
||||
styleEl;
|
||||
@@ -53,7 +65,8 @@ class PreviewPortal extends Component<PreviewPortalProps> {
|
||||
super(props);
|
||||
this.mainWindow = window;
|
||||
this.externalWindow = this.props.portalWindow;
|
||||
this.isAdvancing = this.props.isAdvancing;
|
||||
this.showPreviewPane = this.props.showPreviewPane;
|
||||
this.showPreviewPortal = this.props.showPreviewPortal;
|
||||
this.containerEl = document.createElement('div');
|
||||
this.titleEl = document.createElement('title');
|
||||
this.styleEl = document.createElement('style');
|
||||
@@ -109,11 +122,8 @@ class PreviewPortal extends Component<PreviewPortalProps> {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (!this.props.isAdvancing) {
|
||||
this.externalWindow?.close();
|
||||
}
|
||||
this.externalWindow?.close();
|
||||
this.props.removePortalWindow();
|
||||
this.props.setIsAdvancing(false);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -33,7 +33,6 @@ export const actionTypes = createTypes(
|
||||
'setShowPreviewPortal',
|
||||
'closeModal',
|
||||
'openModal',
|
||||
'setIsAdvancing',
|
||||
|
||||
'previewMounted',
|
||||
'projectPreviewMounted',
|
||||
|
||||
@@ -52,7 +52,6 @@ export const disableBuildOnError = createAction(
|
||||
export const storedCodeFound = createAction(actionTypes.storedCodeFound);
|
||||
export const noStoredCodeFound = createAction(actionTypes.noStoredCodeFound);
|
||||
export const saveEditorContent = createAction(actionTypes.saveEditorContent);
|
||||
export const setIsAdvancing = createAction(actionTypes.setIsAdvancing);
|
||||
export const closeModal = createAction(actionTypes.closeModal);
|
||||
export const openModal = createAction(actionTypes.openModal);
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import { omit } from 'lodash-es';
|
||||
import { ofType } from 'redux-observable';
|
||||
import { empty, of } from 'rxjs';
|
||||
import { catchError, concat, retry, switchMap, tap } from 'rxjs/operators';
|
||||
import { isChallenge } from '../../../utils/path-parsers';
|
||||
import { challengeTypes, submitTypes } from '../../../../utils/challenge-types';
|
||||
import { actionTypes as submitActionTypes } from '../../../redux/action-types';
|
||||
import {
|
||||
@@ -16,11 +15,7 @@ import { mapFilesToChallengeFiles } from '../../../utils/ajax';
|
||||
import { standardizeRequestBody } from '../../../utils/challenge-request-helpers';
|
||||
import postUpdate$ from '../utils/post-update';
|
||||
import { actionTypes } from './action-types';
|
||||
import {
|
||||
closeModal,
|
||||
updateSolutionFormValues,
|
||||
setIsAdvancing
|
||||
} from './actions';
|
||||
import { closeModal, updateSolutionFormValues } from './actions';
|
||||
import {
|
||||
challengeFilesSelector,
|
||||
challengeMetaSelector,
|
||||
@@ -177,7 +172,6 @@ export default function completionEpic(action$, state$) {
|
||||
};
|
||||
|
||||
return submitter(type, state).pipe(
|
||||
concat(of(setIsAdvancing(isChallenge(pathToNavigateTo())))),
|
||||
tap(res => {
|
||||
if (res.type !== submitActionTypes.updateFailed) {
|
||||
navigate(pathToNavigateTo());
|
||||
|
||||
@@ -45,8 +45,7 @@ const initialState = {
|
||||
showPreviewPortal: false,
|
||||
showPreviewPane: true,
|
||||
projectFormValues: {},
|
||||
successMessage: 'Happy Coding!',
|
||||
isAdvancing: false
|
||||
successMessage: 'Happy Coding!'
|
||||
};
|
||||
|
||||
export const epics = [
|
||||
@@ -201,10 +200,6 @@ export const reducer = handleActions(
|
||||
...state,
|
||||
successMessage: payload
|
||||
}),
|
||||
[actionTypes.setIsAdvancing]: (state, { payload }) => ({
|
||||
...state,
|
||||
isAdvancing: payload
|
||||
}),
|
||||
[actionTypes.closeModal]: (state, { payload }) => ({
|
||||
...state,
|
||||
modal: {
|
||||
|
||||
@@ -30,7 +30,6 @@ export const successMessageSelector = state => state[ns].successMessage;
|
||||
|
||||
export const projectFormValuesSelector = state =>
|
||||
state[ns].projectFormValues || {};
|
||||
export const isAdvancingToChallengeSelector = state => state[ns].isAdvancing;
|
||||
export const portalDocumentSelector = state => state[ns].portalWindow?.document;
|
||||
export const portalWindowSelector = state => state[ns].portalWindow;
|
||||
|
||||
|
||||
@@ -42,6 +42,14 @@ const views = {
|
||||
// quiz: Quiz
|
||||
};
|
||||
|
||||
function getIsFirstStep(_node, index, nodeArray) {
|
||||
const current = nodeArray[index];
|
||||
const previous = nodeArray[index - 1];
|
||||
|
||||
if (!previous) return true;
|
||||
return previous.node.challenge.block !== current.node.challenge.block;
|
||||
}
|
||||
|
||||
function getNextChallengePath(_node, index, nodeArray) {
|
||||
const next = nodeArray[index + 1];
|
||||
return next ? next.node.challenge.fields.slug : '/learn';
|
||||
@@ -79,6 +87,7 @@ exports.createChallengePages = function (createPage) {
|
||||
certification,
|
||||
superBlock,
|
||||
block,
|
||||
isFirstStep: getIsFirstStep(challenge, index, allChallengeEdges),
|
||||
template,
|
||||
required,
|
||||
nextChallengePath: getNextChallengePath(
|
||||
|
||||
Reference in New Issue
Block a user