Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUGFIX: Move tab state to redux store instead of reduxForm #694

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/vendor.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions client/src/boot/registerReducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import SchemaReducer from 'state/schema/SchemaReducer';
import RecordsReducer from 'state/records/RecordsReducer';
import BreadcrumbsReducer from 'state/breadcrumbs/BreadcrumbsReducer';
import TreeDropdownFieldReducer from 'state/treeDropdownField/TreeDropdownFieldReducer';
import TabsReducer from 'state/tabs/TabsReducer';
import MobileMenuReducer from 'state/mobileMenu/MobileMenuReducer';
import UnsavedFormsReducer from 'state/unsavedForms/UnsavedFormsReducer';
import usedOnReducer from 'state/usedOn/usedOnReducer';
Expand All @@ -27,6 +28,7 @@ export default (extra = {}) => {
breadcrumbs: BreadcrumbsReducer,
routing: routerReducer,
treeDropdownField: TreeDropdownFieldReducer,
tabs: TabsReducer,
mobileMenu: MobileMenuReducer,
unsavedForms: UnsavedFormsReducer,
usedOn: usedOnReducer,
Expand Down
41 changes: 34 additions & 7 deletions client/src/components/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { Component } from 'react';
import { TabContent, Nav, NavItem, NavLink } from 'reactstrap';
import classnames from 'classnames';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as Actions from 'state/tabs/TabsActions';

class Tabs extends Component {
constructor(props) {
Expand Down Expand Up @@ -59,8 +61,8 @@ class Tabs extends Component {
}

toggle(activeTab) {
if (this.props.value !== activeTab) {
this.props.onChange(activeTab);
if (this.props.activeTab !== activeTab) {
this.props.activateTab(activeTab);
}
}

Expand All @@ -75,7 +77,7 @@ class Tabs extends Component {
return null;
}

const currentTab = this.props.value || this.getDefaultActiveKey();
const currentTab = this.props.activeTab || this.getDefaultActiveKey();

const classNames = classnames({
active: currentTab === child.props.name,
Expand Down Expand Up @@ -116,7 +118,7 @@ class Tabs extends Component {
}

render() {
const { hideNav, children, value } = this.props;
const { hideNav, children, activeTab } = this.props;

const containerProps = this.getContainerProps();
const nav = hideNav ? null : this.renderNav();
Expand All @@ -125,7 +127,7 @@ class Tabs extends Component {
<div {...containerProps}>
<div className="wrapper">
{nav}
<TabContent activeTab={value || this.getDefaultActiveKey()}>
<TabContent activeTab={activeTab || this.getDefaultActiveKey()}>
{children}
</TabContent>
</div>
Expand All @@ -139,7 +141,8 @@ Tabs.propTypes = {
defaultActiveKey: PropTypes.string,
extraClass: PropTypes.string,
hideNav: PropTypes.bool,
onChange: PropTypes.func, // Comes from ReduxFormField
activateTab: PropTypes.func,
activeTab: PropTypes.string,
};

Tabs.defaultProps = {
Expand All @@ -148,4 +151,28 @@ Tabs.defaultProps = {
hideNav: false
};

export default Tabs;
export { Tabs as Component };

function mapStateToProps(state, ownProps) {
const id = ownProps.id;
const field = (state.tabs.fields[id])
? state.tabs.fields[id]
: {
activeTab: null,
};

return { ...field };
}

function mapDispatchToProps(dispatch, ownProps) {
return {
activateTab(activeTab) {
dispatch(Actions.activateTab(ownProps.id, activeTab));
}
};
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(Tabs);
2 changes: 1 addition & 1 deletion client/src/components/Tabs/tests/Tabs-test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* global jest, describe, it, expect */

import React from 'react';
import Tabs from '../Tabs';
import { Component as Tabs } from '../Tabs';
import Enzyme, { shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-15.4/build/index';

Expand Down
3 changes: 3 additions & 0 deletions client/src/state/tabs/TabsActionTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
TABS_ACTIVATE_TAB: 'TABS_ACTIVATE_TAB',
};
15 changes: 15 additions & 0 deletions client/src/state/tabs/TabsActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import ACTION_TYPES from './TabsActionTypes';

/**
* Sets the active tab
*
* @param {String} fieldId ID for field
* @param {String} name of the tab
* @return {Object}
*/
export function activateTab(fieldId, tab) {
return {
type: ACTION_TYPES.TABS_ACTIVATE_TAB,
payload: { fieldId, tab },
};
}
30 changes: 30 additions & 0 deletions client/src/state/tabs/TabsReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import deepFreeze from 'deep-freeze-strict';
import getFieldReducer from 'lib/reduxFieldReducer';
import ACTION_TYPES from './TabsActionTypes';

/**
* Default state
*/
const initialState = deepFreeze({ fields: {} });

/**
* Default object for an empty field state
*/
const initialFieldState = deepFreeze({
activeTab: null
});

export default function tabsReducer(state = initialState, action = null) {
// Get field reducer
const reduceField = getFieldReducer(state, action, initialFieldState);

// Actions
switch (action.type) {
case ACTION_TYPES.TABS_ACTIVATE_TAB: {
return reduceField(() => ({ activeTab: action.payload.tab }));
}

default:
return state;
}
}