fix: simplify mobile layout tabs (#44431)

* fix: simplify mobile layout tabs

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>


Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Tom
2021-12-15 07:52:44 -06:00
committed by GitHub
parent 62071589d3
commit 580a51f7a7
25 changed files with 60 additions and 52 deletions

View File

@ -80,6 +80,7 @@ exports.createPages = function createPages({ graphql, actions, reporter }) {
fields {
slug
}
hasEditableBoundaries
id
order
required {

View File

@ -139,6 +139,7 @@ export type ChallengeNode = {
forumTopicId: number;
guideUrl: string;
head: string[];
hasEditableBoundaries: boolean;
helpCategory: string;
id: string;
instructions: string;

View File

@ -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<MobileLayoutProps> {
static displayName: string;
componentDidMount() {
if (this.props.currentTab !== 1) this.props.moveToTab(1);
enum Tab {
Editor = 'editor',
Preview = 'preview',
Console = 'console',
Notes = 'notes',
Instructions = 'instructions'
}
interface MobileLayoutState {
currentTab: Tab;
}
class MobileLayout extends Component<MobileLayoutProps, MobileLayoutState> {
static displayName: string;
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<MobileLayoutProps> {
// but still needs a way to switch between the different tabs.
const projectBasedChallenge = showUpcomingChanges && usesMultifileEditor;
const eventKeys = [1, 2, 3, 4, 5];
return (
<>
<Tabs
activeKey={currentTab}
defaultActiveKey={1}
defaultActiveKey={currentTab}
id='challenge-page-tabs'
onSelect={moveToTab}
onSelect={this.switchTab}
>
{!hasEditableBoundaries && (
<TabPane
eventKey={eventKeys.shift()}
eventKey={Tab.Instructions}
title={i18next.t('learn.editor-tabs.info')}
>
{instructions}
</TabPane>
)}
<TabPane
eventKey={eventKeys.shift()}
eventKey={Tab.Editor}
title={i18next.t('learn.editor-tabs.code')}
{...editorTabPaneProps}
>
@ -96,7 +97,7 @@ class MobileLayout extends Component<MobileLayoutProps> {
{editor}
</TabPane>
<TabPane
eventKey={eventKeys.shift()}
eventKey={Tab.Console}
title={i18next.t('learn.editor-tabs.tests')}
{...editorTabPaneProps}
>
@ -104,7 +105,7 @@ class MobileLayout extends Component<MobileLayoutProps> {
</TabPane>
{hasNotes && projectBasedChallenge && (
<TabPane
eventKey={eventKeys.shift()}
eventKey={Tab.Notes}
title={i18next.t('learn.editor-tabs.notes')}
>
{notes}
@ -112,7 +113,7 @@ class MobileLayout extends Component<MobileLayoutProps> {
)}
{hasPreview && (
<TabPane
eventKey={eventKeys.shift()}
eventKey={Tab.Preview}
title={i18next.t('learn.editor-tabs.preview')}
>
{preview}
@ -127,4 +128,4 @@ class MobileLayout extends Component<MobileLayoutProps> {
MobileLayout.displayName = 'MobileLayout';
export default connect(mapStateToProps, mapDispatchToProps)(MobileLayout);
export default MobileLayout;

View File

@ -398,20 +398,12 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
);
}
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<ShowClassicProps, ShowClassicState> {
<MobileLayout
editor={this.renderEditor()}
guideUrl={getGuideUrl({ forumTopicId, title })}
hasEditableBoundaries={this.hasEditableBoundaries()}
hasEditableBoundaries={hasEditableBoundaries}
hasNotes={!!notes}
hasPreview={this.hasPreview()}
instructions={this.renderInstructionsPanel({
@ -461,7 +453,7 @@ class ShowClassic extends Component<ShowClassicProps, ShowClassicState> {
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

View File

@ -40,8 +40,6 @@ export const actionTypes = createTypes(
'stopResetting',
'submitChallenge',
'moveToTab',
'setEditorFocusability',
'toggleVisibleEditor'
],

View File

@ -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

View File

@ -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",

View File

@ -2,6 +2,7 @@
"name": "D3 Dashboard",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"dashedName": "d3-dashboard",
"order": 3,
"time": "5 hours",

View File

@ -2,6 +2,7 @@
"name": "Functional Programming Spreadsheet",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"dashedName": "functional-programming-spreadsheet",
"order": 12,
"time": "2 hours",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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;

View File

@ -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',

View File

@ -2,6 +2,7 @@
"name": "",
"isUpcomingChange": true,
"usesMultifileEditor": true,
"hasEditableBoundaries": true,
"dashedName": "",
"order": 42,
"time": "5 hours",