chore: TS migrate MultifileEditor (#45857)

This commit is contained in:
Niraj Nandish
2022-05-19 19:44:22 +04:00
committed by GitHub
parent be60ef2c5a
commit d4e01b66fb
4 changed files with 65 additions and 47 deletions

View File

@@ -1,4 +1,5 @@
declare module '@freecodecamp/react-bootstrap';
declare module '@freecodecamp/loop-protect';
declare module '@freecodecamp/strip-comments';
declare module '@types/react-redux';
declare module '@types/validator';

View File

@@ -346,7 +346,7 @@ export type CompletedChallenge = {
};
export type Ext = 'js' | 'html' | 'css' | 'jsx';
export type FileKey = 'scriptjs' | 'indexhtml' | 'stylescss';
export type FileKey = 'scriptjs' | 'indexhtml' | 'stylescss' | 'indexjsx';
export type ChallengeMeta = {
block: string;

View File

@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React, { useRef } from 'react';
import React, { MutableRefObject, RefObject, useRef } from 'react';
import { connect } from 'react-redux';
import { ReflexContainer, ReflexElement, ReflexSplitter } from 'react-reflex';
import { createSelector } from 'reselect';
import { editor } from 'monaco-editor';
import { isDonationModalOpenSelector, userSelector } from '../../../redux';
import {
canFocusEditorSelector,
@@ -11,46 +11,58 @@ import {
} from '../redux';
import { getTargetEditor } from '../utils/get-target-editor';
import './editor.css';
import {
ChallengeFile,
Dimensions,
Ext,
FileKey,
ResizeProps,
Test
} from '../../../redux/prop-types';
import { Themes } from '../../../components/settings/theme';
import Editor from './editor';
const propTypes = {
canFocus: PropTypes.bool,
// TODO: use shape
challengeFiles: PropTypes.array,
containerRef: PropTypes.any.isRequired,
contents: PropTypes.string,
description: PropTypes.string,
dimensions: PropTypes.object,
editorRef: PropTypes.any.isRequired,
ext: PropTypes.string,
fileKey: PropTypes.string,
initialEditorContent: PropTypes.string,
initialExt: PropTypes.string,
initialTests: PropTypes.array,
output: PropTypes.arrayOf(PropTypes.string),
resizeProps: PropTypes.shape({
onStopResize: PropTypes.func,
onResize: PropTypes.func
}),
theme: PropTypes.string,
title: PropTypes.string,
showProjectPreview: PropTypes.bool,
usesMultifileEditor: PropTypes.bool,
visibleEditors: PropTypes.shape({
scriptjs: PropTypes.bool,
indexjsx: PropTypes.bool,
stylescss: PropTypes.bool,
indexhtml: PropTypes.bool
})
type VisibleEditors = {
[key: string]: boolean;
};
interface MultifileEditorProps {
canFocus?: boolean;
challengeFiles: ChallengeFile[];
containerRef: RefObject<HTMLElement>;
contents?: string;
description: string;
dimensions?: Dimensions;
editorRef: MutableRefObject<editor.IStandaloneCodeEditor>;
ext?: Ext;
fileKey?: string;
initialEditorContent?: string;
initialExt?: string;
initialTests: Test[];
output?: string[];
resizeProps: ResizeProps;
title: string;
showProjectPreview: boolean;
usesMultifileEditor: boolean;
visibleEditors: {
indexhtml?: boolean;
indexjsx?: boolean;
stylescss?: boolean;
scriptjs?: boolean;
};
}
const mapStateToProps = createSelector(
visibleEditorsSelector,
canFocusEditorSelector,
consoleOutputSelector,
isDonationModalOpenSelector,
userSelector,
(visibleEditors, canFocus, output, open, { theme = 'default' }) => ({
(
visibleEditors: VisibleEditors,
canFocus: boolean,
output: string[],
open,
{ theme = Themes.Default }: { theme: Themes }
) => ({
visibleEditors,
canFocus: open ? false : canFocus,
output,
@@ -58,21 +70,19 @@ const mapStateToProps = createSelector(
})
);
const MultifileEditor = props => {
const MultifileEditor = (props: MultifileEditorProps) => {
const {
challengeFiles,
containerRef,
description,
editorRef,
initialTests,
theme,
resizeProps,
title,
visibleEditors: { stylescss, indexhtml, scriptjs, indexjsx },
usesMultifileEditor,
showProjectPreview
} = props;
const editorTheme = theme === 'night' ? 'vs-dark-custom' : 'vs-custom';
// TODO: the tabs mess up the rendering (scroll doesn't work properly and
// the in-editor description)
@@ -94,7 +104,7 @@ const MultifileEditor = props => {
if (stylescss) editorKeys.push('stylescss');
if (scriptjs) editorKeys.push('scriptjs');
const editorAndSplitterKeys = editorKeys.reduce((acc, key) => {
const editorAndSplitterKeys = editorKeys.reduce((acc: string[] | [], key) => {
if (acc.length === 0) {
return [key];
} else {
@@ -124,12 +134,16 @@ const MultifileEditor = props => {
canFocusOnMountRef={canFocusOnMountRef}
challengeFiles={challengeFiles}
containerRef={containerRef}
description={targetEditor === key ? description : null}
description={targetEditor === key ? description : ''}
editorRef={editorRef}
fileKey={key}
fileKey={key as FileKey}
initialTests={initialTests}
resizeProps={resizeProps}
theme={editorTheme}
contents={props.contents ?? ''}
dimensions={props.dimensions ?? { height: 0, width: 0 }}
ext={props.ext ?? 'html'}
initialEditorContent={props.initialEditorContent ?? ''}
initialExt={props.initialExt ?? ''}
title={title}
usesMultifileEditor={usesMultifileEditor}
showProjectPreview={showProjectPreview}
@@ -145,6 +159,5 @@ const MultifileEditor = props => {
};
MultifileEditor.displayName = 'MultifileEditor';
MultifileEditor.propTypes = propTypes;
export default connect(mapStateToProps)(MultifileEditor);

View File

@@ -1,5 +1,5 @@
import { graphql } from 'gatsby';
import React, { Component } from 'react';
import React, { Component, MutableRefObject } from 'react';
import Helmet from 'react-helmet';
import { TFunction, withTranslation } from 'react-i18next';
import { connect } from 'react-redux';
@@ -8,6 +8,7 @@ import Media from 'react-responsive';
import { bindActionCreators, Dispatch } from 'redux';
import { createStructuredSelector } from 'reselect';
import store from 'store';
import { editor } from 'monaco-editor';
import { challengeTypes } from '../../../../utils/challenge-types';
import LearnLayout from '../../../components/layouts/learn';
@@ -51,7 +52,7 @@ import {
} from '../redux';
import { savedChallengesSelector } from '../../../redux';
import { getGuideUrl } from '../utils';
import MultifileEditor from './MultifileEditor';
import MultifileEditor from './multifile-editor';
import DesktopLayout from './desktop-layout';
import MobileLayout from './mobile-layout';
@@ -141,7 +142,7 @@ const BASE_LAYOUT = {
class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
static displayName: string;
containerRef: React.RefObject<HTMLElement>;
editorRef: React.RefObject<HTMLElement>;
editorRef: React.RefObject<editor.IStandaloneCodeEditor | HTMLElement>;
instructionsPanelRef: React.RefObject<HTMLDivElement>;
resizeProps: ResizeProps;
@@ -385,7 +386,10 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
challengeFiles={challengeFiles}
containerRef={this.containerRef}
description={description}
editorRef={this.editorRef}
// Try to remove unknown
editorRef={
this.editorRef as MutableRefObject<editor.IStandaloneCodeEditor>
}
initialTests={tests}
resizeProps={this.resizeProps}
title={title}
@@ -449,7 +453,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
return (
<Hotkeys
editorRef={this.editorRef}
editorRef={this.editorRef as React.RefObject<HTMLElement>}
executeChallenge={executeChallenge}
innerRef={this.containerRef}
instructionsPanelRef={this.instructionsPanelRef}