Skip to content

Commit

Permalink
NEW Connect Element to redux-form state and use activeTab as prop rat…
Browse files Browse the repository at this point in the history
…her than storing it in local state.
  • Loading branch information
raissanorth committed Oct 8, 2018
1 parent 2352a1d commit 88a491a
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 82 deletions.
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/styles/bundle.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client/src/components/ElementActions/AbstractAction.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ AbstractAction.propTypes = {
onClick: PropTypes.func,
title: PropTypes.string,
name: PropTypes.string,
active: PropTypes.bool,
};

AbstractAction.defaultProps = {
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/ElementEditor/Content.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Content extends PureComponent {
InlineEditFormComponent,
SummaryComponent,
activeTab,
onFormInit
} = this.props;

if (!content && !fileUrl) {
Expand All @@ -53,6 +54,7 @@ class Content extends PureComponent {
onClick={(event) => event.stopPropagation()}
elementId={id}
activeTab={activeTab}
onFormInit={onFormInit}
/>
}
</div>
Expand Down
86 changes: 73 additions & 13 deletions client/src/components/ElementEditor/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

import React, { Component, PropTypes } from 'react';
import { elementType } from 'types/elementType';
import { bindActionCreators, compose } from 'redux';
import { inject } from 'lib/Injector';
import i18n from 'i18n';
import classNames from 'classnames';
import { connect } from 'react-redux';
import { change } from 'redux-form';
import { loadElementFormStateName } from 'state/editor/loadElementFormStateName';


/**
* The Element component used in the context of an ElementEditor shows the summary
Expand All @@ -17,10 +22,11 @@ class Element extends Component {
this.handleKeyUp = this.handleKeyUp.bind(this);
this.handleExpand = this.handleExpand.bind(this);
this.handleTabClick = this.handleTabClick.bind(this);
this.updateFormTab = this.updateFormTab.bind(this);

this.state = {
previewExpanded: false,
activeTab: '',
initialTab: '',
};
}

Expand All @@ -46,15 +52,41 @@ class Element extends Component {
}

/**
* Update the active tab state on tab click that is passed down to InlineEditForm
* Dispatcher to Redux-Form state for the Tabs container 'value'
* @param {string} activeTab Name prop of the active tab
*/
updateFormTab(activeTab) {
const { element, actions } = this.props;
const { initialTab } = this.state;

const formStateName = loadElementFormStateName(element.ID);

if (!initialTab) {
this.setState({
initialTab: activeTab
});
}

if (activeTab || initialTab) {
actions.reduxForm.change(formStateName, 'Root', activeTab || initialTab);
}
}

/**
* Update the active tab on tab actions menu button click event. Is passed down to InlineEditForm.
*
* @param {string} toBeActiveTab
*/
handleTabClick(toBeActiveTab) {
this.setState({
activeTab: toBeActiveTab,
previewExpanded: true,
});
const { activeTab } = this.props;

if (toBeActiveTab !== activeTab) {
this.setState({
previewExpanded: true,
});

this.updateFormTab(toBeActiveTab);
}
}

/**
Expand Down Expand Up @@ -101,9 +133,10 @@ class Element extends Component {
link,
editTabs,
pageId,
activeTab
} = this.props;

const { previewExpanded, activeTab } = this.state;
const { previewExpanded } = this.state;

const linkTitle = i18n.inject(
i18n._t('ElementalElement.TITLE', 'Edit this {type} block'),
Expand All @@ -122,6 +155,7 @@ class Element extends Component {
this.getVersionedStateClassName()
);


return (
<div
className={elementClassNames}
Expand All @@ -146,6 +180,7 @@ class Element extends Component {
previewExpanded={previewExpanded}
expandable={element.InlineEditable}
handleEditTabsClick={this.handleTabClick}
activeTab={activeTab}
/>
<ContentComponent
id={element.ID}
Expand All @@ -154,12 +189,34 @@ class Element extends Component {
content={element.BlockSchema.content}
previewExpanded={previewExpanded}
activeTab={activeTab}
onFormInit={() => this.updateFormTab(activeTab)}
/>
</div>
);
}
}

function mapStateToProps(state, ownProps) {
const elementName = loadElementFormStateName(ownProps.element.ID).split('.')[1];

// InlineEditForm will neither have been rendered nor wrapped in redux-form
if (!state.form.formState.element || !state.form.formState.element[elementName]) {
return {};
}

const activeTab = state.form.formState.element[elementName].values.Root;
return { activeTab };
}

function mapDispatchToProps(dispatch) {
return {
actions: {
reduxForm: bindActionCreators({ change }, dispatch),
},
};
}


Element.propTypes = {
element: elementType,
link: PropTypes.string.isRequired,
Expand All @@ -172,10 +229,13 @@ Element.defaultProps = {

export { Element as Component };

export default inject(
['ElementHeader', 'ElementContent'],
(HeaderComponent, ContentComponent) => ({
HeaderComponent, ContentComponent,
}),
() => 'ElementEditor.ElementList.Element'
export default compose(
connect(mapStateToProps, mapDispatchToProps),
inject(
['ElementHeader', 'ElementContent'],
(HeaderComponent, ContentComponent) => ({
HeaderComponent, ContentComponent,
}),
() => 'ElementEditor.ElementList.Element'
)
)(Element);
13 changes: 10 additions & 3 deletions client/src/components/ElementEditor/ElementActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,21 @@ class ElementActions extends Component {
* @returns {DOMElement[]|null}
*/
renderEditTabs() {
const { editTabs } = this.props;
const { editTabs, activeTab } = this.props;

if (!editTabs || !editTabs.length) {
return null;
}

return editTabs.map(
({ name, title }) =>
<AbstractAction key={name} name={name} title={title} onClick={this.handleEditTabsClick} />
(<AbstractAction
key={name}
name={name}
title={title}
onClick={this.handleEditTabsClick}
active={name === activeTab}
/>)
);
}

Expand All @@ -52,7 +58,7 @@ class ElementActions extends Component {
const { children, editTabs } = this.props;

if (editTabs && editTabs.length && React.Children.count(children)) {
return <DropdownItem divider />;
return <DropdownItem divider role="separator" />;
}
return null;
}
Expand Down Expand Up @@ -91,6 +97,7 @@ class ElementActions extends Component {

ElementActions.propTypes = {
id: PropTypes.string,
activeTab: PropTypes.string,
editTabs: PropTypes.arrayOf(PropTypes.shape({
title: PropTypes.string,
name: PropTypes.string,
Expand Down
7 changes: 5 additions & 2 deletions client/src/components/ElementEditor/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,12 @@ class Header extends Component {
</div>
<h3 className="element-editor-header__title">{title}</h3>
</div>
<div className="element-editor-header__actions">
<div
role="none"
className="element-editor-header__actions"
onClick={(event) => event.stopPropagation()}
>
{expandable && <ElementActionsComponent {...this.props} />}

<i className={expandCaretClasses} title={expandTitle} />
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions client/src/components/ElementEditor/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,8 @@
background-color: $state-modified-bg;
}
}

.dropdown-item.active {
cursor: default;
}
}
68 changes: 6 additions & 62 deletions client/src/components/ElementEditor/InlineEditForm.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,11 @@
import React, { PureComponent, PropTypes } from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
import FormBuilderLoader from 'containers/FormBuilderLoader/FormBuilderLoader';
import { loadElementSchemaValue } from 'state/editor/loadElementSchemaValue';
import { bindActionCreators } from 'redux';
import { change } from 'redux-form/lib';
import Config from 'lib/Config';

class InlineEditForm extends PureComponent {
constructor(props) {
super(props);

const sectionKey = 'DNADesign\\Elemental\\Controllers\\ElementalAreaController';
const section = Config.getSection(sectionKey);
const formNameTemplate = section.form.elementForm.formNameTemplate;

this.state = {
formNameTemplate
};

this.updateFormTab = this.updateFormTab.bind(this);
}

componentDidMount() {
this.updateFormTab();
}

/**
* Update the active tab on tab actions menu button click event.
* @param event onChangeEvent from a input field.
*/
componentDidUpdate(prevProps) {
const { activeTab } = this.props;

if (activeTab !== prevProps.activeTab) {
this.updateFormTab();
}
}

getFormName(elementId) {
return `element.${this.state.formNameTemplate.replace('{id}', elementId)}`;
}

updateFormTab() {
const { elementId, actions, activeTab } = this.props;

// form value hardcoded since neither ElementAreaController.php's getElementForm() nor the
// schema data can't be accessed
if (activeTab !== '') {
actions.reduxForm.change(this.getFormName(elementId), 'Root', activeTab);
}
}

render() {
const { elementId, extraClass, onClick } = this.props;
const { elementId, extraClass, onClick, onFormInit } = this.props;

const classNames = classnames('element-editor-editform', extraClass);
const schemaUrl = loadElementSchemaValue('schemaUrl', elementId);
Expand All @@ -62,9 +14,12 @@ class InlineEditForm extends PureComponent {
formTag: 'div',
schemaUrl,
identifier: 'element',
onReduxFormInit: this.updateFormTab,
};

if (typeof onFormInit === 'function') {
formProps.onReduxFormInit = onFormInit;
}

return (
<div className={classNames} onClick={onClick} role="presentation">
<FormBuilderLoader {...formProps} />
Expand All @@ -73,21 +28,10 @@ class InlineEditForm extends PureComponent {
}
}

function mapDispatchToProps(dispatch) {
return {
actions: {
reduxForm: bindActionCreators({ change }, dispatch),
},
};
}

InlineEditForm.propTypes = {
extraClass: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
onClick: PropTypes.func,
elementId: PropTypes.string,
activeTab: PropTypes.string,
};

export { InlineEditForm as Component };

export default connect(null, mapDispatchToProps)(InlineEditForm);
export default InlineEditForm;
18 changes: 18 additions & 0 deletions client/src/state/editor/loadElementFormStateName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Config from 'lib/Config';

/**
* Returns the named component from the elementForm's state data
*
* @param {number|null} elementId
* @returns {string}
*/
export const loadElementFormStateName = (elementId = null) => {
const sectionKey = 'DNADesign\\Elemental\\Controllers\\ElementalAreaController';
const section = Config.getSection(sectionKey);
const formNameTemplate = section.form.elementForm.formNameTemplate;

if (elementId) {
return `element.${formNameTemplate.replace('{id}', elementId)}`;
}
return formNameTemplate;
};

0 comments on commit 88a491a

Please sign in to comment.