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:
@@ -139,6 +139,7 @@ export type ChallengeNode = {
|
||||
forumTopicId: number;
|
||||
guideUrl: string;
|
||||
head: string[];
|
||||
hasEditableBoundaries: boolean;
|
||||
helpCategory: string;
|
||||
id: string;
|
||||
instructions: string;
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -40,8 +40,6 @@ export const actionTypes = createTypes(
|
||||
'stopResetting',
|
||||
'submitChallenge',
|
||||
|
||||
'moveToTab',
|
||||
|
||||
'setEditorFocusability',
|
||||
'toggleVisibleEditor'
|
||||
],
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user