mirror of
https://github.com/strapi/strapi.git
synced 2025-11-10 07:10:11 +00:00
handle nested forms
This commit is contained in:
parent
0a4d5fd021
commit
2e83559b58
@ -23,7 +23,11 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={key}>
|
<div key={key}>
|
||||||
<EditFormSection section={section} values={this.props.values} handleChange={this.props.handleChange} />
|
<EditFormSection
|
||||||
|
section={section}
|
||||||
|
values={this.props.values}
|
||||||
|
handleChange={this.props.handleChange}
|
||||||
|
/>
|
||||||
{line}
|
{line}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -9,12 +9,15 @@ import { map, isEmpty } from 'lodash';
|
|||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
// HOC Form
|
// HOC Form
|
||||||
import WithFormSection from 'components/WithFormSection';
|
import WithFormSection from 'components/WithFormSection';
|
||||||
|
// nested form
|
||||||
|
import EditFormSectionNested from 'components/EditFormSectionNested';
|
||||||
|
|
||||||
class EditFormSection extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
class EditFormSection extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||||
render() {
|
render() {
|
||||||
const sectionName = isEmpty(this.props.section.name) ? '' : <FormattedMessage {...{id: this.props.section.name}} />;
|
const sectionName = isEmpty(this.props.section.name) ? '' : <FormattedMessage {...{id: this.props.section.name}} />;
|
||||||
// get the styles from the WithFormSection HOC
|
// get the styles from the WithFormSection HOC
|
||||||
const styles = this.props.styles;
|
const styles = this.props.styles;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.editFormSection}>
|
<div className={styles.editFormSection}>
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
@ -25,10 +28,22 @@ class EditFormSection extends React.Component { // eslint-disable-line react/pre
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<form>
|
<form>
|
||||||
{map(this.props.section.items, (item, key) => (
|
{map(this.props.section.items, (item, key) => {
|
||||||
this.props.renderInput( item, key)
|
|
||||||
// this.props.renderInput(this.props.section.items, item, key)
|
if (this.props.showNestedForm) {
|
||||||
))}
|
return (
|
||||||
|
<div key={key}>
|
||||||
|
{this.props.renderInput(item, key)}
|
||||||
|
<EditFormSectionNested
|
||||||
|
section={item.items}
|
||||||
|
values={this.props.values}
|
||||||
|
handleChange={this.props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return this.props.renderInput(item, key);
|
||||||
|
})}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -38,9 +53,12 @@ class EditFormSection extends React.Component { // eslint-disable-line react/pre
|
|||||||
}
|
}
|
||||||
|
|
||||||
EditFormSection.propTypes = {
|
EditFormSection.propTypes = {
|
||||||
|
handleChange: React.PropTypes.func,
|
||||||
renderInput: React.PropTypes.func,
|
renderInput: React.PropTypes.func,
|
||||||
section: React.PropTypes.object,
|
section: React.PropTypes.object,
|
||||||
|
showNestedForm: React.PropTypes.bool,
|
||||||
styles: React.PropTypes.object,
|
styles: React.PropTypes.object,
|
||||||
|
values: React.PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WithFormSection(EditFormSection); // eslint-disable-line new-cap
|
export default WithFormSection(EditFormSection); // eslint-disable-line new-cap
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* EditFormSectionNested
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { map } from 'lodash';
|
||||||
|
|
||||||
|
// HOC
|
||||||
|
import WithFormSection from 'components/WithFormSection';
|
||||||
|
|
||||||
|
class EditFormSectionNested extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{map(this.props.section, (item, key) => (
|
||||||
|
this.props.renderInput(item, key)
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditFormSectionNested.propTypes = {
|
||||||
|
renderInput: React.PropTypes.func,
|
||||||
|
section: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.array,
|
||||||
|
React.PropTypes.object,
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WithFormSection(EditFormSectionNested); // eslint-disable-line new-cap
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
// import EditFormSectionNested from '../index';
|
||||||
|
|
||||||
|
import expect from 'expect';
|
||||||
|
// import { shallow } from 'enzyme';
|
||||||
|
// import React from 'react';
|
||||||
|
|
||||||
|
describe('<EditFormSectionNested />', () => {
|
||||||
|
it('Expect to have unit tests specified', () => {
|
||||||
|
expect(true).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -161,7 +161,7 @@ InputText.propTypes = {
|
|||||||
styles: React.PropTypes.object,
|
styles: React.PropTypes.object,
|
||||||
target: React.PropTypes.string.isRequired,
|
target: React.PropTypes.string.isRequired,
|
||||||
validations: React.PropTypes.object.isRequired,
|
validations: React.PropTypes.object.isRequired,
|
||||||
value: React.PropTypes.string.isRequired,
|
value: React.PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WithInput(InputText); // eslint-disable-line new-cap
|
export default WithInput(InputText); // eslint-disable-line new-cap
|
||||||
|
|||||||
@ -74,7 +74,7 @@ class InputToggle extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
InputToggle.propTypes = {
|
InputToggle.propTypes = {
|
||||||
customBootstrapClass: React.PropTypes.string,
|
customBootstrapClass: React.PropTypes.string,
|
||||||
handleChange: React.PropTypes.func.isRequired,
|
handleChange: React.PropTypes.func.isRequired,
|
||||||
isChecked: React.PropTypes.bool.isRequired,
|
isChecked: React.PropTypes.bool,
|
||||||
name: React.PropTypes.string,
|
name: React.PropTypes.string,
|
||||||
target: React.PropTypes.string.isRequired,
|
target: React.PropTypes.string.isRequired,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { forEach, has } from 'lodash';
|
import { forEach, has, isObject } from 'lodash';
|
||||||
|
|
||||||
import InputNumber from 'components/InputNumber';
|
import InputNumber from 'components/InputNumber';
|
||||||
import InputText from 'components/InputText';
|
import InputText from 'components/InputText';
|
||||||
@ -18,9 +18,11 @@ import styles from './styles.scss';
|
|||||||
|
|
||||||
const WithFormSection = (InnerComponent) => class extends React.Component {
|
const WithFormSection = (InnerComponent) => class extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
checkForNestedForm: React.PropTypes.bool,
|
|
||||||
handleChange: React.PropTypes.func.isRequired,
|
handleChange: React.PropTypes.func.isRequired,
|
||||||
section: React.PropTypes.object,
|
section: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.object,
|
||||||
|
React.PropTypes.array,
|
||||||
|
]),
|
||||||
values: React.PropTypes.object,
|
values: React.PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,40 +35,43 @@ const WithFormSection = (InnerComponent) => class extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange = ({ target }) => {
|
componentDidMount() {
|
||||||
|
// check if there is inside a section an input that requires nested input to display it on the entire line
|
||||||
|
if (isObject(this.props.section)) {
|
||||||
|
this.checkForNestedForm(this.props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.section !== this.props.section) {
|
||||||
|
this.setState({ showNestedForm: false, hasNestedInput: false, inputWithNestedForm: '' });
|
||||||
|
if (isObject(nextProps.section)) {
|
||||||
|
this.checkForNestedForm(nextProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForNestedForm(props) {
|
||||||
|
forEach(props.section.items, (input) => {
|
||||||
|
if(has(input, 'items')) {
|
||||||
|
this.setState({ hasNestedInput: true, inputWithNestedForm: input.target })
|
||||||
|
|
||||||
|
if (props.values[input.target]) {
|
||||||
|
this.setState({ showNestedForm: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange = ({ target }) => {
|
||||||
// display nestedForm if the selected input has a nested form
|
// display nestedForm if the selected input has a nested form
|
||||||
if (target.id === this.state.inputWithNestedForm) {
|
if (target.name === this.state.inputWithNestedForm) {
|
||||||
this.setState({ showNestedForm: true });
|
this.setState({ showNestedForm: target.value });
|
||||||
} else {
|
|
||||||
this.setState({ showNestedForm: false });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.props.handleChange({ target });
|
this.props.handleChange({ target });
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
// check if there is inside a section an input that requires nested input to display it on the entire line
|
|
||||||
if (this.props.checkForNestedForm) {
|
|
||||||
forEach(this.props.section.items, (items) => {
|
|
||||||
forEach(items, (item) => {
|
|
||||||
forEach(item, (input) => {
|
|
||||||
|
|
||||||
if (has(input, 'items')) {
|
|
||||||
// store the name of the input that has a nested form
|
|
||||||
this.setState({ hasNestedInput: true, inputWithNestedForm: input.name });
|
|
||||||
|
|
||||||
// showNestedForm if the selected input has a nested form
|
|
||||||
if (items.value === input.value) {
|
|
||||||
this.setState({ showNestedForm: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderInput = (props, key) => {
|
renderInput = (props, key) => {
|
||||||
const inputs = {
|
const inputs = {
|
||||||
string: InputText,
|
string: InputText,
|
||||||
@ -80,14 +85,14 @@ const WithFormSection = (InnerComponent) => class extends React.Component {
|
|||||||
// retrieve options for the select input
|
// retrieve options for the select input
|
||||||
const selectOptions = props.type === 'enum' || props.type === 'select' ? props.items : [];
|
const selectOptions = props.type === 'enum' || props.type === 'select' ? props.items : [];
|
||||||
|
|
||||||
// check if the input has a nested form so it is display on the entire line
|
// check if the input has a nested form so it is displayed on the entire line
|
||||||
const customBootstrapClass = this.state.hasNestedInput ?
|
const customBootstrapClass = this.state.hasNestedInput ?
|
||||||
// bootstrap class to make the input display on the entire line
|
// bootstrap class to make the input displayed on the entire line
|
||||||
'col-md-6 offset-md-6 pull-md-6' :
|
'col-md-6 offset-md-6 pull-md-6' :
|
||||||
// if the input hasn't a nested form but the config requires him to be displayed differently
|
// if the input hasn't a nested form but the config requires him to be displayed differently
|
||||||
config[props.target] || '';
|
config[props.target] || '';
|
||||||
|
|
||||||
// custom handle change props for nested input form
|
// custom handleChange props for nested input form
|
||||||
const handleChange = this.state.hasNestedInput ? this.handleChange : this.props.handleChange;
|
const handleChange = this.state.hasNestedInput ? this.handleChange : this.props.handleChange;
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
@ -108,6 +113,7 @@ const WithFormSection = (InnerComponent) => class extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<InnerComponent
|
<InnerComponent
|
||||||
{...this.props}
|
{...this.props}
|
||||||
|
showNestedForm={this.state.showNestedForm}
|
||||||
renderInput={this.renderInput}
|
renderInput={this.renderInput}
|
||||||
styles={styles}
|
styles={styles}
|
||||||
/>
|
/>
|
||||||
@ -116,5 +122,3 @@ const WithFormSection = (InnerComponent) => class extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default WithFormSection;
|
export default WithFormSection;
|
||||||
|
|
||||||
// Object {name: "form.security.item.xframe.allow-from", value: "ALLOW-FROM", items: Array(1)}
|
|
||||||
|
|||||||
@ -295,9 +295,6 @@ export class Home extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
// custom rendering for PopUpForm
|
// custom rendering for PopUpForm
|
||||||
const renderPopUpForm = this.props.params.slug === 'languages' ? this.renderPopUpFormLanguage : false;
|
const renderPopUpForm = this.props.params.slug === 'languages' ? this.renderPopUpFormLanguage : false;
|
||||||
|
|
||||||
// TODO remove temporary condition to handle nestedForm rendering
|
|
||||||
const checkForNestedForm = this.props.params.slug !== 'languages'
|
|
||||||
|
|
||||||
let renderRow = false;
|
let renderRow = false;
|
||||||
|
|
||||||
if (this.props.params.slug === 'languages') {
|
if (this.props.params.slug === 'languages') {
|
||||||
@ -324,7 +321,6 @@ export class Home extends React.Component { // eslint-disable-line react/prefer-
|
|||||||
handleListPopUpSubmit={this.addLanguage}
|
handleListPopUpSubmit={this.addLanguage}
|
||||||
selectOptions={selectOptions}
|
selectOptions={selectOptions}
|
||||||
renderPopUpForm={renderPopUpForm}
|
renderPopUpForm={renderPopUpForm}
|
||||||
checkForNestedForm={checkForNestedForm}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ export function* deleteLanguage(action) {
|
|||||||
yield put(languageActiontSucceded());
|
yield put(languageActiontSucceded());
|
||||||
|
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
|
console.log(error);
|
||||||
window.Strapi.notification.error('An Error occured');
|
window.Strapi.notification.error('An Error occured');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,6 +59,7 @@ export function* fetchConfig(action) {
|
|||||||
yield put(configFetchSucceded(data));
|
yield put(configFetchSucceded(data));
|
||||||
|
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
|
console.log(error);
|
||||||
window.Strapi.notification.error('An error occurred ');
|
window.Strapi.notification.error('An error occurred ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,6 +111,7 @@ export function* postLanguage() {
|
|||||||
yield put(languageActiontSucceded());
|
yield put(languageActiontSucceded());
|
||||||
|
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
|
console.log(error);
|
||||||
// TODO handle error i18n
|
// TODO handle error i18n
|
||||||
window.Strapi.notification.error(error);
|
window.Strapi.notification.error(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,7 @@ module.exports = {
|
|||||||
description: 'form.security.description',
|
description: 'form.security.description',
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
name: 'form.security.item.csrf',
|
name: 'form.security.item.session',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
name: 'form.security.item.session.enabled',
|
name: 'form.security.item.session.enabled',
|
||||||
@ -235,13 +235,13 @@ module.exports = {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
name: 'form.security.item.hsts.enabled',
|
name: 'form.security.item.hsts.enabled',
|
||||||
target: 'security.p3p.enabled',
|
target: 'security.hsts.enabled',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: _.get(strapi.config, `environments.${env}.security.hsts.enabled`, null),
|
value: _.get(strapi.config, `environments.${env}.security.hsts.enabled`, null),
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
name: 'form.security.item.p3p.maxAge',
|
name: 'form.security.item.hsts.maxAge',
|
||||||
target: 'security.p3p.maxAge',
|
target: 'security.hsts.maxAge',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
value: _.get(strapi.config, `environments.${env}.security.hsts.maxAge`, null),
|
value: _.get(strapi.config, `environments.${env}.security.hsts.maxAge`, null),
|
||||||
validations: {
|
validations: {
|
||||||
@ -249,15 +249,15 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'form.security.item.p3p.includeSubDomains',
|
name: 'form.security.item.hsts.includeSubDomains',
|
||||||
target: 'security.p3p.includeSubDomains',
|
target: 'security.hsts.includeSubDomains',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: _.get(strapi.config, `environments.${env}.security.hsts.includeSubDomains`, null),
|
value: _.get(strapi.config, `environments.${env}.security.hsts.includeSubDomains`, null),
|
||||||
validations: {}
|
validations: {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'form.security.item.p3p.preload',
|
name: 'form.security.item.hsts.preload',
|
||||||
target: 'security.p3p.preload',
|
target: 'security.hsts.preload',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: _.get(strapi.config, `environments.${env}.security.hsts.preload`, null),
|
value: _.get(strapi.config, `environments.${env}.security.hsts.preload`, null),
|
||||||
validations: {}
|
validations: {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user