Dynamic form to edit the label description of an either an input or a displayed relation

This commit is contained in:
cyril lopez 2018-07-20 15:23:09 +02:00
parent be3a28ea04
commit f4996b3663
20 changed files with 185 additions and 15 deletions

View File

@ -1,4 +1,15 @@
import { ON_CLICK_EDIT_LIST_ITEM } from './constants'; import {
ON_CLICK_EDIT_FIELD,
ON_CLICK_EDIT_LIST_ITEM,
ON_CLICK_EDIT_RELATION,
} from './constants';
export function onClickEditField(fieldToEdit) {
return {
type: ON_CLICK_EDIT_FIELD,
fieldToEdit,
};
}
export function onClickEditListItem(listItemToEdit) { export function onClickEditListItem(listItemToEdit) {
return { return {
@ -6,3 +17,10 @@ export function onClickEditListItem(listItemToEdit) {
listItemToEdit, listItemToEdit,
}; };
} }
export function onClickEditRelation(relationToEdit) {
return {
type: ON_CLICK_EDIT_RELATION,
relationToEdit,
};
}

View File

@ -1 +1,3 @@
export const ON_CLICK_EDIT_FIELD = 'contentManager/SettingPage/ON_CLICK_EDIT_FIELD';
export const ON_CLICK_EDIT_LIST_ITEM = 'contentManager/SettingPage/ON_CLICK_EDIT_LIST_ITEM'; export const ON_CLICK_EDIT_LIST_ITEM = 'contentManager/SettingPage/ON_CLICK_EDIT_LIST_ITEM';
export const ON_CLICK_EDIT_RELATION = 'contentManager/SettingPage/ON_CLICK_EDIT_RELATION';

View File

@ -105,6 +105,37 @@
"type": "string", "type": "string",
"validations": {} "validations": {}
} }
],
"fieldForm": [
{
"label": { "id": "content-manager.form.Input.label" },
"customBootstrapClass": "col-md-8",
"didCheckErrors": false,
"errors": [],
"name": "label",
"placeholder": "SLUG (URL)",
"type": "string",
"validations": {}
},
{
"label": { "id": "content-manager.form.Input.disabled" },
"customBootstrapClass": "col-md-4",
"didCheckErrors": false,
"errors": [],
"name": "editable",
"type": "toggle",
"validations": {}
},
{
"label": { "id": "content-manager.form.Input.description" },
"customBootstrapClass": "col-md-12",
"didCheckErrors": false,
"errors": [],
"name": "description",
"placeholder": "content-manager.form.Input.description.placeholder",
"type": "string",
"validations": {}
}
] ]
} }
} }

View File

@ -7,7 +7,7 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux'; import { bindActionCreators, compose } from 'redux';
import { createStructuredSelector } from 'reselect'; import { createStructuredSelector } from 'reselect';
import { findIndex, get, upperFirst } from 'lodash'; import { findIndex, get, isEmpty, upperFirst } from 'lodash';
import cn from 'classnames'; import cn from 'classnames';
import HTML5Backend from 'react-dnd-html5-backend'; import HTML5Backend from 'react-dnd-html5-backend';
import { DragDropContext } from 'react-dnd'; import { DragDropContext } from 'react-dnd';
@ -41,7 +41,7 @@ import VariableDraggableAttr from 'components/VariableDraggableAttr';
import injectReducer from 'utils/injectReducer'; import injectReducer from 'utils/injectReducer';
import injectSaga from 'utils/injectSaga'; import injectSaga from 'utils/injectSaga';
import { onClickEditListItem } from './actions'; import { onClickEditField, onClickEditListItem, onClickEditRelation } from './actions';
import forms from './forms.json'; import forms from './forms.json';
import reducer from './reducer'; import reducer from './reducer';
@ -61,6 +61,15 @@ class SettingPage extends React.PureComponent {
componentDidMount() { componentDidMount() {
this.handleClickEditAttr(0); this.handleClickEditAttr(0);
const fields = this.getEditPageDisplayedFields();
const relations = this.getEditPageDisplayedRelations();
if (fields.length === 0) {
this.handleClickEditField(0);
} else if (relations.length > 0) {
this.handleClickEditRelation(0);
}
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
@ -208,11 +217,25 @@ class SettingPage extends React.PureComponent {
} }
} }
handleClickEditAttr = (index) => { handleClickEditAttr = index => {
const attrToEdit = get(this.props.schema, ['models'].concat(this.getPath().split('.')).concat(['listDisplay', index]), {}); const attrToEdit = get(this.props.schema, ['models'].concat(this.getPath().split('.')).concat(['listDisplay', index]), {});
this.props.onClickEditListItem(attrToEdit); this.props.onClickEditListItem(attrToEdit);
} }
handleClickEditField = index => {
const fieldToEditName = get(this.props.schema, ['models', ...this.getPath().split('.'), 'editDisplay', 'fields', index], '');
const fieldToEdit = get(this.props.schema, ['models', ...this.getPath().split('.'), 'editDisplay', 'availableFields', fieldToEditName], {});
return this.props.onClickEditField(fieldToEdit);
}
handleClickEditRelation = index => {
const relationToEditName = get(this.getEditPageDisplayedRelations(), index, '');
const relationToEdit = get(this.props.schema, ['models', ...this.getPath().split('.'), 'relations', relationToEditName]);
return this.props.onClickEditRelation(relationToEdit);
}
handleConfirmReset = () => { handleConfirmReset = () => {
this.props.onReset(); this.props.onReset();
this.toggleWarningCancel(); this.toggleWarningCancel();
@ -348,13 +371,49 @@ class SettingPage extends React.PureComponent {
renderDropDownP = msg => <p>{msg}</p>; renderDropDownP = msg => <p>{msg}</p>;
renderFormEditSettingsRelation = (input, i) => { renderForm = () => {
const { settingPage: { fieldToEdit, relationToEdit } } = this.props;
if (isEmpty(fieldToEdit)) {
return forms.editView.relationForm.map(this.renderFormEditSettingsRelation);
}
if (isEmpty(relationToEdit)) {
return forms.editView.fieldForm.map(this.renderFormEditSettingsField);
}
return null;
}
renderFormEditSettingsField = (input, i) => {
const { onChangeSettings, schema, settingPage: { fieldToEdit: { name } } } = this.props;
const path = [...this.getPath().split('.'), 'editDisplay', 'availableFields', name, input.name];
const value = get(schema, ['models', ...path], '');
return ( return (
<Input <Input
key={i} key={i}
onChange={() => {}} onChange={onChangeSettings}
value="" value={value}
{...input} {...input}
name={path.join('.')}
/>
);
}
renderFormEditSettingsRelation = (input, i) => {
const { onChangeSettings, schema, settingPage: { relationToEdit: { alias } } } = this.props;
const path = [...this.getPath().split('.'), 'relations', alias, input.name];
const value = get(schema, ['models', ...path], '');
return (
<Input
key={i}
onChange={onChangeSettings}
value={value}
{...input}
name={path.join('.')}
/> />
); );
} }
@ -404,7 +463,6 @@ class SettingPage extends React.PureComponent {
const { const {
onSubmit, onSubmit,
} = this.props; } = this.props;
return ( return (
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<BackHeader onClick={this.handleGoBack} /> <BackHeader onClick={this.handleGoBack} />
@ -547,7 +605,7 @@ class SettingPage extends React.PureComponent {
<div className={styles.editWrapper}> <div className={styles.editWrapper}>
<div className="row"> <div className="row">
{forms.editView.relationForm.map(this.renderFormEditSettingsRelation)} {this.renderForm()}
</div> </div>
</div> </div>
@ -572,7 +630,9 @@ SettingPage.propTypes = {
moveVariableAttrEditView: PropTypes.func.isRequired, moveVariableAttrEditView: PropTypes.func.isRequired,
onChangeSettings: PropTypes.func.isRequired, onChangeSettings: PropTypes.func.isRequired,
onClickAddAttr: PropTypes.func.isRequired, onClickAddAttr: PropTypes.func.isRequired,
onClickEditField: PropTypes.func.isRequired,
onClickEditListItem: PropTypes.func.isRequired, onClickEditListItem: PropTypes.func.isRequired,
onClickEditRelation: PropTypes.func.isRequired,
onRemove: PropTypes.func.isRequired, onRemove: PropTypes.func.isRequired,
onRemoveEditViewAttr: PropTypes.func.isRequired, onRemoveEditViewAttr: PropTypes.func.isRequired,
onRemoveEditViewFieldAttr: PropTypes.func.isRequired, onRemoveEditViewFieldAttr: PropTypes.func.isRequired,
@ -591,7 +651,9 @@ const mapDispatchToProps = (dispatch) => (
moveVariableAttrEditView, moveVariableAttrEditView,
onChangeSettings, onChangeSettings,
onClickAddAttr, onClickAddAttr,
onClickEditField,
onClickEditListItem, onClickEditListItem,
onClickEditRelation,
onRemove, onRemove,
onRemoveEditViewAttr, onRemoveEditViewAttr,
onRemoveEditViewFieldAttr, onRemoveEditViewFieldAttr,

View File

@ -4,18 +4,31 @@
*/ */
import { fromJS } from 'immutable'; import { fromJS } from 'immutable';
import { ON_CLICK_EDIT_LIST_ITEM } from './constants'; import {
ON_CLICK_EDIT_FIELD,
ON_CLICK_EDIT_LIST_ITEM,
ON_CLICK_EDIT_RELATION,
} from './constants';
const initialState = fromJS({ const initialState = fromJS({
fieldToEdit: fromJS({}),
indexListItemToEdit: 0, // NOTE: need to check if this used in the code...
listItemToEdit: fromJS({}), listItemToEdit: fromJS({}),
indexListItemToEdit: 0, relationToEdit: fromJS({}),
}); });
function settingPageReducer(state = initialState, action) { function settingPageReducer(state = initialState, action) {
switch (action.type) { switch (action.type) {
case ON_CLICK_EDIT_LIST_ITEM: case ON_CLICK_EDIT_FIELD:
return state return state
.update('listItemToEdit', () => fromJS(action.listItemToEdit)); .update('fieldToEdit', () => fromJS(action.fieldToEdit))
.update('relationToEdit', () => fromJS({})); // Both these object will be used to set the form so in order to know which form to display we set an empty object
case ON_CLICK_EDIT_LIST_ITEM:
return state.update('listItemToEdit', () => fromJS(action.listItemToEdit));
case ON_CLICK_EDIT_RELATION:
return state
.update('fieldToEdit', () => fromJS({}))
.update('relationToEdit', () => fromJS(action.relationToEdit));
default: default:
return state; return state;
} }

View File

@ -46,6 +46,7 @@
"error.attribute.sameKeyAndName": "لا تتطابق", "error.attribute.sameKeyAndName": "لا تتطابق",
"error.validation.minSupMax": "لا يمكن أن تكون متفوقة", "error.validation.minSupMax": "لا يمكن أن تكون متفوقة",
"form.Input.disabled": "Editable field",
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",

View File

@ -46,6 +46,7 @@
"error.attribute.sameKeyAndName": "Darf nicht gleich sein", "error.attribute.sameKeyAndName": "Darf nicht gleich sein",
"error.validation.minSupMax": "Darf nicht höher sein", "error.validation.minSupMax": "Darf nicht höher sein",
"form.Input.disabled": "Editable field",
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",

View File

@ -93,6 +93,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"form.Input.label.inputDescription": "This value overrides the label displayed in the table's head", "form.Input.label.inputDescription": "This value overrides the label displayed in the table's head",
"form.Input.label": "Label", "form.Input.label": "Label",
"form.Input.search": "Enable search", "form.Input.search": "Enable search",

View File

@ -92,6 +92,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "N'oubliez pas de mettre l'URL complète!", "form.Input.description.placeholder": "N'oubliez pas de mettre l'URL complète!",
"form.Input.disabled": "Champ editable",
"form.Input.label": "Label", "form.Input.label": "Label",
"form.Input.label.inputDescription": "Cette valeur modifie celle du champs de la table", "form.Input.label.inputDescription": "Cette valeur modifie celle du champs de la table",
"form.Input.search": "Autoriser la search", "form.Input.search": "Autoriser la search",

View File

@ -76,6 +76,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "Si è verificato un errore durante il rapporto di recupero.", "notification.error.relationship.fetch": "Si è verificato un errore durante il rapporto di recupero.",

View File

@ -78,6 +78,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "데이터 관계를 가져오는 도중 에러가 발생했습니다.", "notification.error.relationship.fetch": "데이터 관계를 가져오는 도중 에러가 발생했습니다.",

View File

@ -77,6 +77,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "Wystąpił błąd podczas pobierania relacji.", "notification.error.relationship.fetch": "Wystąpił błąd podczas pobierania relacji.",

View File

@ -78,6 +78,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "Ocorreu um erro durante a busca da relação.", "notification.error.relationship.fetch": "Ocorreu um erro durante a busca da relação.",

View File

@ -78,6 +78,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "Ocorreu um erro durante a busca da relação.", "notification.error.relationship.fetch": "Ocorreu um erro durante a busca da relação.",

View File

@ -48,6 +48,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "Возникла ошибка при получении связей.", "notification.error.relationship.fetch": "Возникла ошибка при получении связей.",

View File

@ -76,6 +76,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "İlişki getirme sırasında bir hata oluştu.", "notification.error.relationship.fetch": "İlişki getirme sırasında bir hata oluştu.",

View File

@ -48,6 +48,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "获取关联数据时发生错误", "notification.error.relationship.fetch": "获取关联数据时发生错误",

View File

@ -49,6 +49,7 @@
"form.Input.description": "Description", "form.Input.description": "Description",
"form.Input.description.placeholder": "Please don't forget to fill the full URL!", "form.Input.description.placeholder": "Please don't forget to fill the full URL!",
"form.Input.disabled": "Editable field",
"notification.error.relationship.fetch": "讀取關聯資料時發生錯誤", "notification.error.relationship.fetch": "讀取關聯資料時發生錯誤",

View File

@ -65,6 +65,7 @@ module.exports = async cb => {
label: _.upperFirst(attribute), label: _.upperFirst(attribute),
description: '', description: '',
type: value.type || 'string', type: value.type || 'string',
disabled: false,
})); }));
schemaModel.fields = fields; schemaModel.fields = fields;
@ -109,7 +110,8 @@ module.exports = async cb => {
if (model.associations) { if (model.associations) {
// Model relations // Model relations
schemaModel.relations = model.associations.reduce((acc, current) => { schemaModel.relations = model.associations.reduce((acc, current) => {
const displayedAttribute = current.plugin ? const label = _.upperFirst(current.alias);
const displayedAttribute = current.plugin ? // Value to modified to custom what's displayed in the react-select
_.get(pluginsModel, [current.plugin, 'models', current.model || current.collection, 'info', 'mainField']) || _.get(pluginsModel, [current.plugin, 'models', current.model || current.collection, 'info', 'mainField']) ||
_.findKey(_.get(pluginsModel, [current.plugin, 'models', current.model || current.collection, 'attributes']), { type : 'string'}) || _.findKey(_.get(pluginsModel, [current.plugin, 'models', current.model || current.collection, 'attributes']), { type : 'string'}) ||
'id' : 'id' :
@ -120,6 +122,7 @@ module.exports = async cb => {
acc[current.alias] = { acc[current.alias] = {
...current, ...current,
description: '', description: '',
label,
displayedAttribute, displayedAttribute,
}; };
@ -144,6 +147,7 @@ module.exports = async cb => {
name: current, name: current,
placeholder: '', placeholder: '',
type: 'file', type: 'file',
disabled: false,
}; };
} }

View File

@ -27,6 +27,33 @@
}, },
"date": { "date": {
"appearance": "" "appearance": ""
},
"bool1": {
"appearance": ""
},
"bool2": {
"appearance": ""
},
"number": {
"appearance": ""
},
"enum": {
"appearance": ""
},
"json": {
"appearance": ""
},
"bool3": {
"appearance": ""
},
"bool4": {
"appearance": ""
},
"bool5": {
"appearance": ""
},
"bool6": {
"appearance": ""
} }
} }
}, },