diff --git a/packages/strapi-admin/admin/src/components/LeftMenuLinkContainer/index.js b/packages/strapi-admin/admin/src/components/LeftMenuLinkContainer/index.js index 5583826e45..5ea571e596 100755 --- a/packages/strapi-admin/admin/src/components/LeftMenuLinkContainer/index.js +++ b/packages/strapi-admin/admin/src/components/LeftMenuLinkContainer/index.js @@ -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 ( ); + const hasSettingsManager = get(pluginsObject, 'settings-manager', null); + return (
{linkSections} @@ -105,11 +108,13 @@ function LeftMenuLinkContainer({ layout, plugins }) { label={messages.installNewPlugin.id} destination="/install-plugin" /> - + {hasSettingsManager && ( + + )}
diff --git a/packages/strapi-admin/admin/src/styles/base/bootstrap-override.scss b/packages/strapi-admin/admin/src/styles/base/bootstrap-override.scss index 43130804f5..48f7707273 100644 --- a/packages/strapi-admin/admin/src/styles/base/bootstrap-override.scss +++ b/packages/strapi-admin/admin/src/styles/base/bootstrap-override.scss @@ -21,3 +21,7 @@ button { margin-right: -2rem; } } + +form .row { + text-align: left; +} diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpRelations/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpRelations/index.js index f947dfad06..2c05221a4b 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpRelations/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/PopUpRelations/index.js @@ -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 = () => (
@@ -70,7 +168,7 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref /> ))}
- ) + ); renderModalBodyAdvanced = () => ( @@ -95,7 +193,10 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref
{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 (
- ) + ); 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 ( @@ -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} /> @@ -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} /> ); - } + }; render() { - const loader = this.props.showLoader ? - - : ; + const loader = this.props.showLoader ? ( + + ) : ( + + ); - const modalBody = this.props.showRelation ? this.renderModalBodyRelations(): this.renderModalBodyAdvanced(); + const modalBody = this.props.showRelation + ? this.renderModalBodyRelations() + : this.renderModalBodyAdvanced(); const handleToggle = this.props.toggle; return (
- +
@@ -190,7 +326,9 @@ class PopUpRelations extends React.Component { // eslint-disable-line react/pref {modalBody} - + {loader}{' '} @@ -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, diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/RelationBox/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/RelationBox/index.js index 62cf93cf5e..d7d14bc604 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/components/RelationBox/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/RelationBox/index.js @@ -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 = () => (
- - - + + {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 ( -
- +
+
{value.name}  - {value.source ? ( + {value.source && ( - {(message) => ( - ({message}: {value.source}) + {message => ( + + ({message}: {value.source}) + )} - ) : ''} + )}
@@ -85,63 +92,41 @@ class RelationBox extends React.Component { // eslint-disable-line react/prefer-
- ) + ); 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) ? -
: - ; - - const dropDown = !isEmpty(this.props.dropDownItems) ? this.renderDropdownMenu() : ''; - return (
{startCase(get(this.props.header, 'name'))}  - {get(this.props.header, 'source') ? ( - `(${get(this.props.header, 'source')})` - ): ''} + {get(this.props.header, 'source') ? `(${get(this.props.header, 'source')})` : ''} - {dropDown} + {!isEmpty(this.props.dropDownItems) && this.renderDropdownMenu()}
- {content} + {!isEmpty(this.props.input) && ( + + )}
@@ -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: '', }; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js index 1eaea03009..f9fc05446b 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/index.js @@ -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} /> ); } diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/reducer.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/reducer.js index ddede0e91f..6ee48bf98c 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/reducer.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/Form/reducer.js @@ -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) diff --git a/packages/strapi-plugin-graphql/package.json b/packages/strapi-plugin-graphql/package.json index 5c1235cbcc..301b5783f4 100644 --- a/packages/strapi-plugin-graphql/package.json +++ b/packages/strapi-plugin-graphql/package.json @@ -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" -} \ No newline at end of file +}