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

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