Merge branch 'master' into chore/test-against-nodejs-8-10

This commit is contained in:
Jim LAURIE 2018-06-11 15:39:20 +02:00 committed by GitHub
commit 5838d19f81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 254 additions and 125 deletions

View File

@ -16,6 +16,7 @@ import messages from './messages.json';
function LeftMenuLinkContainer({ layout, plugins }) {
const pluginsObject = plugins.toJS();
// Generate the list of sections
const pluginsSections = Object.keys(pluginsObject).reduce((acc, current) => {
pluginsObject[current].leftMenuSections.forEach((section = {}) => {
@ -38,7 +39,7 @@ function LeftMenuLinkContainer({ layout, plugins }) {
return acc;
}, {});
const linkSections = Object.keys(pluginsSections).map((current, j) => {
const contentTypesToShow = get(layout, 'layout.contentTypesToShow');
const contentTypes = contentTypesToShow
@ -68,7 +69,7 @@ function LeftMenuLinkContainer({ layout, plugins }) {
// Check if the plugins list is empty or not and display plugins by name
const pluginsLinks = !isEmpty(pluginsObject) ? (
map(sortBy(pluginsObject, 'name'), plugin => {
if (plugin.id !== 'email' && plugin.id !== 'content-manager') {
if (plugin.id !== 'email' && plugin.id !== 'content-manager' && plugin.id !== 'settings-manager') {
return (
<LeftMenuLink
key={get(plugin, 'id')}
@ -85,6 +86,8 @@ function LeftMenuLinkContainer({ layout, plugins }) {
</li>
);
const hasSettingsManager = get(pluginsObject, 'settings-manager', null);
return (
<div className={styles.leftMenuLinkContainer}>
{linkSections}
@ -105,11 +108,13 @@ function LeftMenuLinkContainer({ layout, plugins }) {
label={messages.installNewPlugin.id}
destination="/install-plugin"
/>
<LeftMenuLink
icon="gear"
label={messages.configuration.id}
destination="/configuration"
/>
{hasSettingsManager && (
<LeftMenuLink
icon="gear"
label={messages.configuration.id}
destination="/plugins/settings-manager"
/>
)}
</ul>
</div>
</div>

View File

@ -21,3 +21,7 @@ button {
margin-right: -2rem;
}
}
form .row {
text-align: left;
}

View File

@ -1,13 +1,14 @@
/**
*
* PopUpRelations
*
*/
*
* PopUpRelations
*
*/
import React from 'react';
import PropTypes from 'prop-types';
import { findIndex, get, isEmpty, map, take, takeRight } from 'lodash';
import { FormattedMessage } from 'react-intl';
import pluralize from 'pluralize';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Input from 'components/InputsIndex';
@ -17,12 +18,21 @@ import RelationNaturePicker from 'components/RelationNaturePicker';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/tabindex-no-positive */
class PopUpRelations extends React.Component { // eslint-disable-line react/prefer-stateless-function
class PopUpRelations extends React.Component {
// eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.popUpHeaderNavLinks = [
{ name: 'defineRelation', message: 'content-type-builder.popUpForm.navContainer.relation', nameToReplace: 'advancedSettings' },
{ name: 'advancedSettings', message: 'content-type-builder.popUpForm.navContainer.advanced', nameToReplace: 'defineRelation' },
{
name: 'defineRelation',
message: 'content-type-builder.popUpForm.navContainer.relation',
nameToReplace: 'advancedSettings',
},
{
name: 'advancedSettings',
message: 'content-type-builder.popUpForm.navContainer.advanced',
nameToReplace: 'defineRelation',
},
];
}
@ -33,12 +43,93 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
}
componentWillReceiveProps(nextProps) {
if (isEmpty(this.props.dropDownItems) && !isEmpty(nextProps.dropDownItems) && !this.props.isEditting) {
if (
isEmpty(this.props.dropDownItems) &&
!isEmpty(nextProps.dropDownItems) &&
!this.props.isEditting
) {
this.init(nextProps);
}
}
init = (props) => {
setPlaceholders = (firstCTName, secondCTName, relationType, values = this.props.values) => {
switch (relationType) {
case 'oneToMany':
firstCTName = pluralize(firstCTName);
break;
case 'manyToOne':
secondCTName = pluralize(secondCTName);
break;
case 'manyToMany':
firstCTName = pluralize(firstCTName);
secondCTName = pluralize(secondCTName);
break;
default:
// Do nothing
}
if (get(this.props.contentType, 'name') !== get(values, 'params.target')) {
this.props.onChange({ target: { name: 'name', value: firstCTName } });
this.props.onChange({ target: { name: 'params.key', value: secondCTName } });
this.props.resetFormErrors();
} else {
this.props.onChange({ target: { name: 'name', value: '' } });
this.props.onChange({ target: { name: 'params.key', value: '' } });
}
}
handleChange = e => {
this.props.onChange(e);
const shouldResetKeyParams = e.target.value === 'oneWay';
if (!this.props.isEditting && !shouldResetKeyParams) {
this.setPlaceholders(
get(this.props.values, ['params', 'target']),
get(this.props.contentType, 'name'),
e.target.value,
);
}
if (shouldResetKeyParams) {
this.props.onChange({ target: { name: 'params.key', value: '-' } });
}
}
handleClick = e => {
const value = e.target.id.split('.');
[
{
target: {
type: 'string',
value: value[0],
name: 'params.target',
},
},
{
target: {
type: 'string',
value: value[1] !== 'undefined' ? value[1] : '',
name: 'params.pluginValue',
},
},
].map(target => this.props.onChange(target));
if (!this.props.isEditting) {
if (get(this.props.contentType, 'name') !== value[0]) {
this.setPlaceholders(
value[0],
get(this.props.contentType, 'name'),
get(this.props.values, ['params', 'nature']),
value[0],
);
} else {
this.props.onChange({ target: { name: 'name', value: '' } });
this.props.onChange({ target: { name: 'params.key', value: '' } });
}
}
};
init = props => {
const target = {
name: 'params.target',
type: 'string',
@ -56,7 +147,14 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
},
});
}
}
if (get(props.contentType, 'name') !== get(props.dropDownItems, ['0', 'name'])) {
[
{ target: { name: 'name', value: get(props.dropDownItems, ['0', 'name']) } },
{ target: { name: 'params.key', value: get(props.contentType, 'name') } },
].map(target => this.props.onChange(target));
}
};
renderNavContainer = () => (
<div className={styles.navContainer}>
@ -70,7 +168,7 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
/>
))}
</div>
)
);
renderModalBodyAdvanced = () => (
<ModalBody className={`${styles.modalBodyAdvanced}`}>
@ -95,7 +193,10 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
<div className={styles.inputContainer}>
<div className="row">
{map(takeRight(this.props.form.items, 2), (value, index) => {
const addon = index === 0 ? get(this.props.values, 'name') : get(this.props.values, ['params', 'key']);
const addon =
index === 0
? get(this.props.values, 'name')
: get(this.props.values, ['params', 'key']);
return (
<Input
key={index}
@ -117,12 +218,25 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
</div>
</div>
</ModalBody>
)
);
renderModalBodyRelations = () => {
const header = get(this.props.values, ['params', 'pluginValue']) ?
get(this.props.dropDownItems, [findIndex(this.props.dropDownItems, {'name': get(this.props.values, ['params', 'target']), source: get(this.props.values, ['params', 'pluginValue']) })])
: get(this.props.dropDownItems, [findIndex(this.props.dropDownItems, ['name', get(this.props.values, ['params', 'target'])])]);
const header = get(this.props.values, ['params', 'pluginValue'])
? get(this.props.dropDownItems, [
findIndex(this.props.dropDownItems, {
name: get(this.props.values, ['params', 'target']),
source: get(this.props.values, ['params', 'pluginValue']),
}),
])
: get(this.props.dropDownItems, [
findIndex(this.props.dropDownItems, [
'name',
get(this.props.values, ['params', 'target']),
]),
]);
const errs = findIndex(this.props.formErrors, ['name',get(this.props.form, ['items', '0', 'name'])]) !== -1 ? this.props.formErrors[findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '0', 'name'])])].errors: [];
const errors = findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '1', 'name'])]) !== -1 ? this.props.formErrors[findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '1', 'name'])])].errors : [];
return (
<ModalBody className={`${styles.modalBody} ${styles.flex}`}>
@ -138,11 +252,11 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
onSubmit={this.props.onSubmit}
onChange={this.props.onChange}
didCheckErrors={this.props.didCheckErrors}
errors={findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '0', 'name'])]) !== -1 ? this.props.formErrors[findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '0', 'name'])])].errors : []}
errors={errs}
/>
<RelationNaturePicker
selectedIco={get(this.props.values, ['params', 'nature'])}
onChange={this.props.onChange}
onChange={this.handleChange}
contentTypeName={get(this.props.contentType, 'name')}
contentTypeTarget={get(this.props.values, ['params', 'target'])}
/>
@ -156,24 +270,46 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
value={get(this.props.values, ['params', 'key'])}
onChange={this.props.onChange}
didCheckErrors={this.props.didCheckErrors}
errors={findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '1', 'name'])]) !== -1 ? this.props.formErrors[findIndex(this.props.formErrors, ['name', get(this.props.form, ['items', '1', 'name'])])].errors : []}
errors={errors}
dropDownItems={this.props.dropDownItems}
onClick={this.handleClick}
/>
</ModalBody>
);
}
};
render() {
const loader = this.props.showLoader ?
<Button onClick={this.props.onSubmit} type="submit" className={styles.primary} disabled={this.props.showLoader}><p className={styles.saving}><span>.</span><span>.</span><span>.</span></p></Button>
: <Button type="submit" onClick={this.props.onSubmit} className={styles.primary}><FormattedMessage id="content-type-builder.form.button.continue" /></Button>;
const loader = this.props.showLoader ? (
<Button
onClick={this.props.onSubmit}
type="submit"
className={styles.primary}
disabled={this.props.showLoader}
>
<p className={styles.saving}>
<span>.</span>
<span>.</span>
<span>.</span>
</p>
</Button>
) : (
<Button type="submit" onClick={this.props.onSubmit} className={styles.primary}>
<FormattedMessage id="content-type-builder.form.button.continue" />
</Button>
);
const modalBody = this.props.showRelation ? this.renderModalBodyRelations(): this.renderModalBodyAdvanced();
const modalBody = this.props.showRelation
? this.renderModalBodyRelations()
: this.renderModalBodyAdvanced();
const handleToggle = this.props.toggle;
return (
<div className={styles.popUpRelations}>
<Modal isOpen={this.props.isOpen} toggle={this.props.toggle} className={`${styles.modalPosition}`}>
<Modal
isOpen={this.props.isOpen}
toggle={this.props.toggle}
className={`${styles.modalPosition}`}
>
<ModalHeader toggle={this.props.toggle} className={styles.popUpFormHeader} />
<div className={styles.headerContainer}>
<div className={styles.titleContainer}>
@ -190,7 +326,9 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
{modalBody}
<ModalFooter className={styles.modalFooter}>
<Button onClick={handleToggle} className={styles.secondary}><FormattedMessage id="content-type-builder.form.button.cancel" /></Button>
<Button onClick={handleToggle} className={styles.secondary}>
<FormattedMessage id="content-type-builder.form.button.cancel" />
</Button>
{loader}{' '}
</ModalFooter>
</Modal>
@ -203,19 +341,14 @@ PopUpRelations.propTypes = {
contentType: PropTypes.object,
didCheckErrors: PropTypes.bool.isRequired,
dropDownItems: PropTypes.array,
form: PropTypes.oneOfType([
PropTypes.array.isRequired,
PropTypes.object.isRequired,
]).isRequired,
formErrors: PropTypes.oneOfType([
PropTypes.array,
PropTypes.object,
]).isRequired,
form: PropTypes.oneOfType([PropTypes.array.isRequired, PropTypes.object.isRequired]).isRequired,
formErrors: PropTypes.oneOfType([PropTypes.array, PropTypes.object]).isRequired,
isEditting: PropTypes.bool,
isOpen: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
popUpTitle: PropTypes.string.isRequired,
resetFormErrors: PropTypes.func.isRequired,
routePath: PropTypes.string.isRequired,
showLoader: PropTypes.bool,
showRelation: PropTypes.bool.isRequired,

View File

@ -1,8 +1,8 @@
/**
*
* RelationBox
*
*/
*
* RelationBox
*
*/
import React from 'react';
import PropTypes from 'prop-types';
@ -16,7 +16,8 @@ import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable react/jsx-wrap-multilines */
class RelationBox extends React.Component { // eslint-disable-line react/prefer-stateless-function
class RelationBox extends React.Component {
// eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
@ -25,58 +26,64 @@ class RelationBox extends React.Component { // eslint-disable-line react/prefer-
};
}
handleClick = (e) => {
const value = e.target.id.split('.');
const target = {
type: 'string',
value: value[0],
name: 'params.target',
};
this.props.onChange({ target });
this.props.onChange({
target: {
type: 'string',
value: value[1] !== 'undefined' ? value[1] : '',
name: 'params.pluginValue',
},
});
getPlaceholder = () => {
switch (true) {
case this.props.relationType === 'oneToMany' && this.props.isFirstContentType:
return pluralize(this.props.contentTypeTargetPlaceholder);
case this.props.relationType === 'manyToOne' && !this.props.isFirstContentType:
return pluralize(this.props.contentTypeTargetPlaceholder);
case this.props.relationType === 'manyToMany':
return pluralize(this.props.contentTypeTargetPlaceholder);
default:
return this.props.contentTypeTargetPlaceholder;
}
}
toggle = () => this.setState({ showMenu: !this.state.showMenu });
renderDropdownMenu = () => (
<div className={styles.dropDown}>
<ButtonDropdown isOpen={this.state.showMenu} toggle={this.toggle} style={{ backgroundColor: 'transparent' }}>
<DropdownToggle caret>
</DropdownToggle>
<ButtonDropdown
isOpen={this.state.showMenu}
toggle={this.toggle}
style={{ backgroundColor: 'transparent' }}
>
<DropdownToggle caret />
<DropdownMenu className={styles.dropDownContent}>
{map(this.props.dropDownItems, (value, key) => {
const id = value.source ? `${value.name}.${value.source}` : `${value.name}. `;
let divStyle;
if (get(this.props.header, 'name') === value.name && !isEmpty(get(this.props.header,'source')) && value.source) {
divStyle = { color: '#323740', fontWeight: 'bold'};
} else if (value.source === get(this.props.header, 'source') && value.name === get(this.props.header, 'name')) {
divStyle = { color: '#323740', fontWeight: 'bold'};
if (
get(this.props.header, 'name') === value.name &&
!isEmpty(get(this.props.header, 'source')) &&
value.source
) {
divStyle = { color: '#323740', fontWeight: 'bold' };
} else if (
value.source === get(this.props.header, 'source') &&
value.name === get(this.props.header, 'name')
) {
divStyle = { color: '#323740', fontWeight: 'bold' };
} else {
divStyle = { color: 'rgba(50,55,64,0.75)' };
}
return (
<div style={{ height: '3.6rem'}} key={key}>
<DropdownItem onClick={this.handleClick} id={id}>
<div style={{ height: '3.6rem' }} key={key}>
<DropdownItem onClick={this.props.onClick} id={id}>
<div style={divStyle} id={`${value.name}.${value.source}`}>
<i className={`fa ${value.icon}`} style={divStyle} id={id} />
{value.name}&nbsp;
{value.source ? (
{value.source && (
<FormattedMessage id="content-type-builder.from">
{(message) => (
<span style={{ fontStyle: 'italic' }} id={id}>({message}: {value.source})</span>
{message => (
<span style={{ fontStyle: 'italic' }} id={id}>
({message}: {value.source})
</span>
)}
</FormattedMessage>
) : ''}
)}
</div>
</DropdownItem>
</div>
@ -85,63 +92,41 @@ class RelationBox extends React.Component { // eslint-disable-line react/prefer-
</DropdownMenu>
</ButtonDropdown>
</div>
)
);
render() {
let placeholder;
switch (true) {
case this.props.relationType === 'oneToMany' && this.props.isFirstContentType:
placeholder = pluralize(this.props.contentTypeTargetPlaceholder);
break;
case this.props.relationType === 'manyToOne' && !this.props.isFirstContentType:
placeholder = pluralize(this.props.contentTypeTargetPlaceholder);
break;
case this.props.relationType === 'manyToMany':
placeholder = pluralize(this.props.contentTypeTargetPlaceholder);
break;
default:
placeholder = this.props.contentTypeTargetPlaceholder;
}
const content = isEmpty(this.props.input) ?
<div /> :
<Input
disabled={this.props.relationType === 'oneWay' && this.props.tabIndex === '2'}
tabIndex={this.props.tabIndex}
type={get(this.props.input, 'type')}
onChange={this.props.onChange}
label={get(this.props.input, 'label')}
name={get(this.props.input, 'name')}
value={this.props.value}
placeholder={placeholder}
customBootstrapClass="col-md-12"
validations={get(this.props.input, 'validations')}
errors={this.props.errors}
didCheckErrors={this.props.didCheckErrors}
pluginID="content-type-builder"
autoFocus={this.props.autoFocus}
/>;
const dropDown = !isEmpty(this.props.dropDownItems) ? this.renderDropdownMenu() : '';
return (
<div className={styles.relationBox}>
<div className={styles.headerContainer}>
<i className={`fa ${get(this.props.header, 'icon')}`} />
{startCase(get(this.props.header, 'name'))}&nbsp;
<span style={{ fontStyle: 'italic', fontWeight: '500' }}>
{get(this.props.header, 'source') ? (
`(${get(this.props.header, 'source')})`
): ''}
{get(this.props.header, 'source') ? `(${get(this.props.header, 'source')})` : ''}
</span>
{dropDown}
{!isEmpty(this.props.dropDownItems) && this.renderDropdownMenu()}
</div>
<div className={styles.inputContainer}>
<form onSubmit={this.props.onSubmit}>
<div className="container-fluid">
<div className={`row ${styles.input}`}>
{content}
{!isEmpty(this.props.input) && (
<Input
disabled={this.props.relationType === 'oneWay' && this.props.tabIndex === '2'}
tabIndex={this.props.tabIndex}
type={get(this.props.input, 'type')}
onChange={this.props.onChange}
label={get(this.props.input, 'label')}
name={get(this.props.input, 'name')}
value={this.props.value}
placeholder={this.getPlaceholder()}
customBootstrapClass="col-md-12"
validations={get(this.props.input, 'validations')}
errors={this.props.errors}
didCheckErrors={this.props.didCheckErrors}
pluginID="content-type-builder"
autoFocus={this.props.autoFocus}
/>
)}
</div>
</div>
</form>
@ -161,6 +146,7 @@ RelationBox.propTypes = {
input: PropTypes.object,
isFirstContentType: PropTypes.bool,
onChange: PropTypes.func.isRequired,
onClick: PropTypes.func,
onSubmit: PropTypes.func.isRequired,
relationType: PropTypes.string,
tabIndex: PropTypes.string.isRequired,
@ -175,6 +161,7 @@ RelationBox.defaultProps = {
header: {},
input: {},
isFirstContentType: false,
onClick: () => {},
relationType: 'oneToOne',
value: '',
};

View File

@ -397,8 +397,6 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
if (target.name === 'params.nature' && target.value === "oneWay") {
this.props.changeInputAttribute('params.key', '-');
}else if (target.name === 'params.nature'){
this.props.changeInputAttribute('params.key', '');
}
} else {
@ -539,7 +537,6 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
}
render() {
// Ensure typeof(popUpFormType) is String
const popUpFormType = split(this.props.hash, '::')[1] || '';
const popUpTitle = this.generatePopUpTitle(popUpFormType);
@ -576,6 +573,7 @@ export class Form extends React.Component { // eslint-disable-line react/prefer-
formErrors={this.props.formErrors}
didCheckErrors={this.props.didCheckErrors}
isEditting={edit}
resetFormErrors={this.props.resetFormErrors}
/>
);
}

View File

@ -79,7 +79,9 @@ function formReducer(state = initialState, action) {
.update('formErrors', (list) => list.splice(findIndex(state.get('formErrors').toJS(), ['target', 'name']), 1))
.set('didCheckErrors', !state.get('didCheckErrors'));
case RESET_FORM_ERRORS:
return state.set('formErrors', List());
return state
.update('didCheckErrors', v => v = !v)
.set('formErrors', List());
case RESET_IS_FORM_SET:
return state
.set('isFormSet', false)

View File

@ -25,7 +25,7 @@
"glob": "^7.1.2",
"graphql": "^0.13.2",
"graphql-depth-limit": "^1.1.0",
"graphql-playground-middleware-koa": "^1.5.1",
"graphql-playground-middleware-koa": "^1.6.1",
"graphql-tools": "^2.23.1",
"graphql-type-json": "^0.2.0",
"pluralize": "^7.0.0",
@ -48,4 +48,4 @@
"npm": ">= 5.3.0"
},
"license": "MIT"
}
}