diff --git a/client/gatsby-node.js b/client/gatsby-node.js index 6fa003143a..1a895117d2 100644 --- a/client/gatsby-node.js +++ b/client/gatsby-node.js @@ -80,6 +80,7 @@ exports.createPages = function createPages({ graphql, actions, reporter }) { fields { slug } + hasEditableBoundaries id order required { diff --git a/client/src/redux/prop-types.ts b/client/src/redux/prop-types.ts index 30a7c41260..18a60b8b77 100644 --- a/client/src/redux/prop-types.ts +++ b/client/src/redux/prop-types.ts @@ -139,6 +139,7 @@ export type ChallengeNode = { forumTopicId: number; guideUrl: string; head: string[]; + hasEditableBoundaries: boolean; helpCategory: string; id: string; instructions: string; diff --git a/client/src/templates/Challenges/classic/mobile-layout.tsx b/client/src/templates/Challenges/classic/mobile-layout.tsx index 7c1881e76d..f3c41fc9cd 100644 --- a/client/src/templates/Challenges/classic/mobile-layout.tsx +++ b/client/src/templates/Challenges/classic/mobile-layout.tsx @@ -1,52 +1,55 @@ import { TabPane, Tabs } from '@freecodecamp/react-bootstrap'; import i18next from 'i18next'; import React, { Component, ReactElement } from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators, Dispatch } from 'redux'; -import { createStructuredSelector } from 'reselect'; import envData from '../../../../../config/env.json'; import ToolPanel from '../components/tool-panel'; -import { currentTabSelector, moveToTab } from '../redux'; import EditorTabs from './editor-tabs'; const { showUpcomingChanges } = envData; -const mapStateToProps = createStructuredSelector({ - currentTab: currentTabSelector as (state: unknown) => number -}); - -const mapDispatchToProps = (dispatch: Dispatch) => - bindActionCreators( - { - moveToTab - }, - dispatch - ); interface MobileLayoutProps { - currentTab: number; editor: JSX.Element | null; guideUrl: string; hasEditableBoundaries: boolean; hasNotes: boolean; hasPreview: boolean; instructions: JSX.Element; - moveToTab: typeof moveToTab; notes: ReactElement; preview: JSX.Element; testOutput: JSX.Element; videoUrl: string; usesMultifileEditor: boolean; } -class MobileLayout extends Component { + +enum Tab { + Editor = 'editor', + Preview = 'preview', + Console = 'console', + Notes = 'notes', + Instructions = 'instructions' +} + +interface MobileLayoutState { + currentTab: Tab; +} + +class MobileLayout extends Component { static displayName: string; - componentDidMount() { - if (this.props.currentTab !== 1) this.props.moveToTab(1); - } + + state: MobileLayoutState = { + currentTab: this.props.hasEditableBoundaries ? Tab.Editor : Tab.Instructions + }; + + switchTab = (tab: Tab) => { + this.setState({ + currentTab: tab + }); + }; + render() { + const { currentTab } = this.state; const { - currentTab, - moveToTab, hasEditableBoundaries, instructions, editor, @@ -69,26 +72,24 @@ class MobileLayout extends Component { // but still needs a way to switch between the different tabs. const projectBasedChallenge = showUpcomingChanges && usesMultifileEditor; - const eventKeys = [1, 2, 3, 4, 5]; - return ( <> {!hasEditableBoundaries && ( {instructions} )} @@ -96,7 +97,7 @@ class MobileLayout extends Component { {editor} @@ -104,7 +105,7 @@ class MobileLayout extends Component { {hasNotes && projectBasedChallenge && ( {notes} @@ -112,7 +113,7 @@ class MobileLayout extends Component { )} {hasPreview && ( {preview} @@ -127,4 +128,4 @@ class MobileLayout extends Component { MobileLayout.displayName = 'MobileLayout'; -export default connect(mapStateToProps, mapDispatchToProps)(MobileLayout); +export default MobileLayout; diff --git a/client/src/templates/Challenges/classic/show.tsx b/client/src/templates/Challenges/classic/show.tsx index 8e3ec4b5d8..960a6469e2 100644 --- a/client/src/templates/Challenges/classic/show.tsx +++ b/client/src/templates/Challenges/classic/show.tsx @@ -398,20 +398,12 @@ class ShowClassic extends Component { ); } - hasEditableBoundaries() { - const { challengeFiles } = this.props; - return ( - challengeFiles?.some( - challengeFile => challengeFile.editableRegionBoundaries?.length === 2 - ) ?? false - ); - } - render() { const { block, fields: { blockName }, forumTopicId, + hasEditableBoundaries, superBlock, title, usesMultifileEditor, @@ -443,7 +435,7 @@ class ShowClassic extends Component { { block={block} challengeFiles={challengeFiles} editor={this.renderEditor()} - hasEditableBoundaries={this.hasEditableBoundaries()} + hasEditableBoundaries={hasEditableBoundaries} hasNotes={!!notes} hasPreview={this.hasPreview()} instructions={this.renderInstructionsPanel({ @@ -504,6 +496,7 @@ export const query = graphql` block title description + hasEditableBoundaries instructions notes removeComments diff --git a/client/src/templates/Challenges/redux/action-types.js b/client/src/templates/Challenges/redux/action-types.js index 5b37a40cfc..d7488e90b0 100644 --- a/client/src/templates/Challenges/redux/action-types.js +++ b/client/src/templates/Challenges/redux/action-types.js @@ -40,8 +40,6 @@ export const actionTypes = createTypes( 'stopResetting', 'submitChallenge', - 'moveToTab', - 'setEditorFocusability', 'toggleVisibleEditor' ], diff --git a/client/src/templates/Challenges/redux/index.js b/client/src/templates/Challenges/redux/index.js index 28d80012cf..7577a902f0 100644 --- a/client/src/templates/Challenges/redux/index.js +++ b/client/src/templates/Challenges/redux/index.js @@ -120,8 +120,6 @@ export const resetChallenge = createAction(actionTypes.resetChallenge); export const stopResetting = createAction(actionTypes.stopResetting); export const submitChallenge = createAction(actionTypes.submitChallenge); -export const moveToTab = createAction(actionTypes.moveToTab); - export const setEditorFocusability = createAction( actionTypes.setEditorFocusability ); @@ -344,10 +342,6 @@ export const reducer = handleActions( [payload]: true } }), - [actionTypes.moveToTab]: (state, { payload }) => ({ - ...state, - currentTab: payload - }), [actionTypes.executeChallenge]: state => ({ ...state, currentTab: 3 diff --git a/curriculum/challenges/_meta/basic-javascript-rpg-game/meta.json b/curriculum/challenges/_meta/basic-javascript-rpg-game/meta.json index 2ac4f74265..f8df0d0480 100644 --- a/curriculum/challenges/_meta/basic-javascript-rpg-game/meta.json +++ b/curriculum/challenges/_meta/basic-javascript-rpg-game/meta.json @@ -2,6 +2,7 @@ "name": "Basic JavaScript RPG Game", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "basic-javascript-rpg-game", "order": 10, "time": "2 hours", diff --git a/curriculum/challenges/_meta/d3-dashboard/meta.json b/curriculum/challenges/_meta/d3-dashboard/meta.json index c6752b0923..f9f5c6e26b 100644 --- a/curriculum/challenges/_meta/d3-dashboard/meta.json +++ b/curriculum/challenges/_meta/d3-dashboard/meta.json @@ -2,6 +2,7 @@ "name": "D3 Dashboard", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "d3-dashboard", "order": 3, "time": "5 hours", diff --git a/curriculum/challenges/_meta/functional-programming-spreadsheet/meta.json b/curriculum/challenges/_meta/functional-programming-spreadsheet/meta.json index b8bbc2ee29..87a0f9be04 100644 --- a/curriculum/challenges/_meta/functional-programming-spreadsheet/meta.json +++ b/curriculum/challenges/_meta/functional-programming-spreadsheet/meta.json @@ -2,6 +2,7 @@ "name": "Functional Programming Spreadsheet", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "functional-programming-spreadsheet", "order": 12, "time": "2 hours", diff --git a/curriculum/challenges/_meta/intermediate-javascript-calorie-counter/meta.json b/curriculum/challenges/_meta/intermediate-javascript-calorie-counter/meta.json index 107e7d616d..e5f984a42f 100644 --- a/curriculum/challenges/_meta/intermediate-javascript-calorie-counter/meta.json +++ b/curriculum/challenges/_meta/intermediate-javascript-calorie-counter/meta.json @@ -2,6 +2,7 @@ "name": "Intermediate JavaScript Calorie Counter", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "intermediate-javascript-calorie-counter", "order": 11, "time": "2 hours", diff --git a/curriculum/challenges/_meta/learn-accessibility-by-building-a-quiz/meta.json b/curriculum/challenges/_meta/learn-accessibility-by-building-a-quiz/meta.json index b98701ffe6..94f2af52a0 100644 --- a/curriculum/challenges/_meta/learn-accessibility-by-building-a-quiz/meta.json +++ b/curriculum/challenges/_meta/learn-accessibility-by-building-a-quiz/meta.json @@ -2,6 +2,7 @@ "name": "Learn Accessibility by Building a Quiz", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-accessibility-by-building-a-quiz", "order": 42, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-basic-css-by-building-a-cafe-menu/meta.json b/curriculum/challenges/_meta/learn-basic-css-by-building-a-cafe-menu/meta.json index 7a139f3401..cd14d49c3c 100644 --- a/curriculum/challenges/_meta/learn-basic-css-by-building-a-cafe-menu/meta.json +++ b/curriculum/challenges/_meta/learn-basic-css-by-building-a-cafe-menu/meta.json @@ -2,6 +2,7 @@ "name": "Learn Basic CSS by Building a Cafe Menu", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-basic-css-by-building-a-cafe-menu", "order": 10, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-css-animation-by-building-a-ferris-wheel/meta.json b/curriculum/challenges/_meta/learn-css-animation-by-building-a-ferris-wheel/meta.json index 131d23f3f9..ef7dce0f88 100644 --- a/curriculum/challenges/_meta/learn-css-animation-by-building-a-ferris-wheel/meta.json +++ b/curriculum/challenges/_meta/learn-css-animation-by-building-a-ferris-wheel/meta.json @@ -2,6 +2,7 @@ "name": "Learn CSS Animation by Building a Ferris Wheel", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-css-animation-by-building-a-ferris-wheel", "order": 15, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-css-flexbox-by-building-a-photo-gallery/meta.json b/curriculum/challenges/_meta/learn-css-flexbox-by-building-a-photo-gallery/meta.json index 42a800df5b..a7ba45ac9f 100644 --- a/curriculum/challenges/_meta/learn-css-flexbox-by-building-a-photo-gallery/meta.json +++ b/curriculum/challenges/_meta/learn-css-flexbox-by-building-a-photo-gallery/meta.json @@ -2,6 +2,7 @@ "name": "Learn CSS Flexbox by Building a Photo Gallery", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-css-flexbox-by-building-a-photo-gallery", "order": 20, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-css-grid-by-building-a-magazine/meta.json b/curriculum/challenges/_meta/learn-css-grid-by-building-a-magazine/meta.json index 4ae209c001..ad45376cbd 100644 --- a/curriculum/challenges/_meta/learn-css-grid-by-building-a-magazine/meta.json +++ b/curriculum/challenges/_meta/learn-css-grid-by-building-a-magazine/meta.json @@ -2,6 +2,7 @@ "name": "Learn CSS Grid by Building a Magazine", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-css-grid-by-building-a-magazine", "order": 16, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-css-variables-by-building-a-city-skyline/meta.json b/curriculum/challenges/_meta/learn-css-variables-by-building-a-city-skyline/meta.json index 409c39852e..d5664a9f1b 100644 --- a/curriculum/challenges/_meta/learn-css-variables-by-building-a-city-skyline/meta.json +++ b/curriculum/challenges/_meta/learn-css-variables-by-building-a-city-skyline/meta.json @@ -2,6 +2,7 @@ "name": "Learn CSS Variables by Building a City Skyline", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-css-variables-by-building-a-city-skyline", "order": 8, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-html-by-building-a-cat-photo-app/meta.json b/curriculum/challenges/_meta/learn-html-by-building-a-cat-photo-app/meta.json index 7128761f4f..99224535d4 100644 --- a/curriculum/challenges/_meta/learn-html-by-building-a-cat-photo-app/meta.json +++ b/curriculum/challenges/_meta/learn-html-by-building-a-cat-photo-app/meta.json @@ -2,6 +2,7 @@ "name": "Learn HTML by Building a Cat Photo App", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-html-by-building-a-cat-photo-app", "order": 9, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-html-forms-by-building-a-registration-form/meta.json b/curriculum/challenges/_meta/learn-html-forms-by-building-a-registration-form/meta.json index 56bdb3b3a8..421039d201 100644 --- a/curriculum/challenges/_meta/learn-html-forms-by-building-a-registration-form/meta.json +++ b/curriculum/challenges/_meta/learn-html-forms-by-building-a-registration-form/meta.json @@ -2,6 +2,7 @@ "name": "Learn HTML Forms by Building a Registration Form", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-html-forms-by-building-a-registration-form", "order": 23, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-intermediate-css-by-building-a-picasso-painting/meta.json b/curriculum/challenges/_meta/learn-intermediate-css-by-building-a-picasso-painting/meta.json index 89866e64fe..cd78d87636 100644 --- a/curriculum/challenges/_meta/learn-intermediate-css-by-building-a-picasso-painting/meta.json +++ b/curriculum/challenges/_meta/learn-intermediate-css-by-building-a-picasso-painting/meta.json @@ -2,6 +2,7 @@ "name": "Learn Intermediate CSS by Building a Picasso Painting", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-intermediate-css-by-building-a-picasso-painting", "order": 11, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-responsive-web-design-by-building-a-piano/meta.json b/curriculum/challenges/_meta/learn-responsive-web-design-by-building-a-piano/meta.json index ea91978a79..34c32833f4 100644 --- a/curriculum/challenges/_meta/learn-responsive-web-design-by-building-a-piano/meta.json +++ b/curriculum/challenges/_meta/learn-responsive-web-design-by-building-a-piano/meta.json @@ -2,6 +2,7 @@ "name": "Learn Responsive Web Design by Building a Piano", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-responsive-web-design-by-building-a-piano", "order": 13, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-the-css-box-model-by-building-a-rothko-painting/meta.json b/curriculum/challenges/_meta/learn-the-css-box-model-by-building-a-rothko-painting/meta.json index ee18cc9481..fd2d01c46c 100644 --- a/curriculum/challenges/_meta/learn-the-css-box-model-by-building-a-rothko-painting/meta.json +++ b/curriculum/challenges/_meta/learn-the-css-box-model-by-building-a-rothko-painting/meta.json @@ -2,6 +2,7 @@ "name": "Learn the CSS Box Model by Building a Rothko Painting", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-the-css-box-model-by-building-a-rothko-painting", "order": 12, "time": "5 hours", diff --git a/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json b/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json index 323a4f00bc..7fac00490f 100644 --- a/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json +++ b/curriculum/challenges/_meta/learn-typography-by-building-a-nutrition-label/meta.json @@ -2,6 +2,7 @@ "name": "Learn Typography by Building a Nutrition Label", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "learn-typography-by-building-a-nutrition-label", "order": 25, "time": "5 hours", diff --git a/curriculum/getChallenges.js b/curriculum/getChallenges.js index 7d254af58f..fe5fa8d464 100644 --- a/curriculum/getChallenges.js +++ b/curriculum/getChallenges.js @@ -296,6 +296,7 @@ ${getFullPath('english')} ); const { name: blockName, + hasEditableBoundaries, order, isPrivate, required = [], @@ -304,6 +305,7 @@ ${getFullPath('english')} usesMultifileEditor } = meta; challenge.block = dasherize(blockName); + challenge.hasEditableBoundaries = !!hasEditableBoundaries; challenge.order = order; const superOrder = getSuperOrder(superBlock); if (superOrder !== null) challenge.superOrder = superOrder; diff --git a/curriculum/schema/challengeSchema.js b/curriculum/schema/challengeSchema.js index a086146c1c..4c34a59265 100644 --- a/curriculum/schema/challengeSchema.js +++ b/curriculum/schema/challengeSchema.js @@ -39,6 +39,7 @@ const schema = Joi.object() }), challengeFiles: Joi.array().items(fileJoi), guideUrl: Joi.string().uri({ scheme: 'https' }), + hasEditableBoundaries: Joi.boolean(), helpCategory: Joi.valid( 'JavaScript', 'HTML-CSS', diff --git a/tools/challenge-helper-scripts/base-meta.json b/tools/challenge-helper-scripts/base-meta.json index 281a91cbce..6e6c2486dd 100644 --- a/tools/challenge-helper-scripts/base-meta.json +++ b/tools/challenge-helper-scripts/base-meta.json @@ -2,6 +2,7 @@ "name": "", "isUpcomingChange": true, "usesMultifileEditor": true, + "hasEditableBoundaries": true, "dashedName": "", "order": 42, "time": "5 hours",