Commit 1c435959 authored by Florent Chehab's avatar Florent Chehab
Browse files

Better than ever from poo

New fields
parent ee9a98b3
...@@ -13,7 +13,6 @@ import Slide from '@material-ui/core/Slide'; ...@@ -13,7 +13,6 @@ import Slide from '@material-ui/core/Slide';
import MyComponent from '../../../MyComponent'; import MyComponent from '../../../MyComponent';
import Alert from './Alert'; import Alert from './Alert';
import dateToDateStr from '../../../../utils/dateToDateStr';
import getObjModerationLevel from '../../../../utils/getObjModerationLevels'; import getObjModerationLevel from '../../../../utils/getObjModerationLevels';
import SelectField from './fields/SelectField'; import SelectField from './fields/SelectField';
...@@ -22,8 +21,15 @@ function Transition(props) { ...@@ -22,8 +21,15 @@ function Transition(props) {
} }
class Editor extends MyComponent { class Editor extends MyComponent {
formData = {}; fields = Object();
formError = {};
addField(field, fieldMapping) {
this.fields[fieldMapping] = field;
}
removeField(fieldMapping) {
delete this.fields[fieldMapping];
}
state = { state = {
alert: { alert: {
...@@ -32,6 +38,40 @@ class Editor extends MyComponent { ...@@ -32,6 +38,40 @@ class Editor extends MyComponent {
lastSave: this.props.lastSave, lastSave: this.props.lastSave,
} }
formIsValid() {
// to override if you need to perform some checks at the form level
return true;
}
formFieldsHaveError() {
for (let fieldKey in this.fields) {
const field = this.fields[fieldKey];
if (field.getHasError()) {
return true;
}
}
return false;
}
getDataFromFields() {
let data = Object();
for (let fieldKey in this.fields) {
const field = this.fields[fieldKey];
data[fieldKey] = field.getValue();
}
return data;
}
handleSaveEditor() {
if (this.formIsValid()) {
const tmp = Object.assign({}, this.props.modelData, this.getDataFromFields())
this.props.saveData(tmp);
} else {
console.log("ici")
}
}
myComponentDidUpdate() { myComponentDidUpdate() {
const { savingHasError } = this.props; const { savingHasError } = this.props;
if (savingHasError.status) { if (savingHasError.status) {
...@@ -63,15 +103,6 @@ class Editor extends MyComponent { ...@@ -63,15 +103,6 @@ class Editor extends MyComponent {
}) })
} }
setFormDataAndError(field, data, type = null) {
let correctData = data.data;
if (type == 'date') {
correctData = dateToDateStr(correctData);
}
this.formData[field] = correctData;
this.formError[field] = data.hasError;
}
renderEditor() { renderEditor() {
return (<div>No editor set</div>) return (<div>No editor set</div>)
} }
...@@ -85,8 +116,9 @@ class Editor extends MyComponent { ...@@ -85,8 +116,9 @@ class Editor extends MyComponent {
<SelectField label={"Niveau de modération pour ce module"} <SelectField label={"Niveau de modération pour ce module"}
required={true} required={true}
value={modelData.obj_moderation_level} value={modelData.obj_moderation_level}
fieldMapping={"obj_moderation_level"}
options={possibleObjModeration} options={possibleObjModeration}
onChange={(data) => this.setFormDataAndError('obj_moderation_level', data)} formManager={this}
/> />
) )
} else { } else {
...@@ -136,6 +168,7 @@ Editor.propTypes = { ...@@ -136,6 +168,7 @@ Editor.propTypes = {
classes: PropTypes.object.isRequired, classes: PropTypes.object.isRequired,
clearSaveError: PropTypes.func.isRequired, clearSaveError: PropTypes.func.isRequired,
savingHasError: PropTypes.bool.isRequired, savingHasError: PropTypes.bool.isRequired,
saveData: PropTypes.func.isRequired,
}; };
Editor.defaultProps = { Editor.defaultProps = {
......
...@@ -24,11 +24,7 @@ const styles = theme => ({ ...@@ -24,11 +24,7 @@ const styles = theme => ({
class UniversitySemestersDatesEditor extends Editor { class UniversitySemestersDatesEditor extends Editor {
handleSaveEditor() {
const tmp = Object.assign({}, this.props.modelData, this.formData)
this.props.saveData(tmp);
}
renderEditor() { renderEditor() {
const { modelData } = this.props; const { modelData } = this.props;
...@@ -36,28 +32,34 @@ class UniversitySemestersDatesEditor extends Editor { ...@@ -36,28 +32,34 @@ class UniversitySemestersDatesEditor extends Editor {
<div> <div>
{this.renderObjModerationLevelField()} {this.renderObjModerationLevelField()}
<DateField label={"Date de début du semestre de printemps"} <DateField label={"Date de début du semestre de printemps"}
selectedDate={modelData.spring_begin} value={modelData.spring_begin}
onChange={(data) => this.setFormDataAndError('spring_begin', data, 'date')} formManager={this}
fieldMapping={'spring_begin'}
/> />
<DateField label={"Date de fin du semestre de printemps"} <DateField label={"Date de fin du semestre de printemps"}
selectedDate={modelData.spring_end} value={modelData.spring_end}
onChange={(data) => this.setFormDataAndError('spring_end', data, 'date')} formManager={this}
fieldMapping={'spring_end'}
/> />
<DateField label={"Date de début du semestre d'automne"} <DateField label={"Date de début du semestre d'automne"}
selectedDate={modelData.autumn_begin} value={modelData.autumn_begin}
onChange={(data) => this.setFormDataAndError('autumn_begin', data, 'date')} formManager={this}
fieldMapping={'autumn_begin'}
/> />
<DateField label={"Date de fin du semestre d'automne"} <DateField label={"Date de fin du semestre d'automne"}
selectedDate={modelData.autumn_end} value={modelData.autumn_end}
onChange={(data) => this.setFormDataAndError('autumn_end', data, 'date')} formManager={this}
fieldMapping={'autumn_end'}
/> />
<MarkdownField label={"Éventuel commentaire associé à ces informations"} maxLength={100} <MarkdownField label={"Éventuel commentaire associé à ces informations"} maxLength={100}
value={modelData.comment} value={modelData.comment}
onChange={(data) => this.setFormDataAndError('comment', data)} formManager={this}
fieldMapping={'comment'}
/> />
<UsefulLinksField label={"Lien(s) utile(s) (ex : vers ces informations)"} <UsefulLinksField label={"Lien(s) utile(s) (ex : vers ces informations)"}
value={modelData.UsefulLinksField} value={modelData.useful_links}
onChange={(data) => this.setFormDataAndError('useful_links', data)} formManager={this}
fieldMapping={'useful_links'}
/> />
</div> </div>
) )
......
...@@ -12,6 +12,9 @@ import format from 'date-fns/format'; ...@@ -12,6 +12,9 @@ import format from 'date-fns/format';
import KeyboardArrowLeftIcon from '@material-ui/icons/KeyboardArrowLeft'; import KeyboardArrowLeftIcon from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight'; import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
import FieldWrapper from './FieldWrapper'; import FieldWrapper from './FieldWrapper';
import dateToDateStr from '../../../../../utils/dateToDateStr';
import Field from './Field';
const styles = theme => ({ const styles = theme => ({
}); });
...@@ -23,31 +26,19 @@ class LocalizedUtils extends DateFnsUtils { ...@@ -23,31 +26,19 @@ class LocalizedUtils extends DateFnsUtils {
} }
} }
class DateField extends PureComponent { class DateField extends Field {
hasError(date) {
return this.props.required && !date;
}
state = { getValue() {
selectedDate: this.props.selectedDate, return dateToDateStr(this.state.value);
hasError: this.hasError(this.props.selectedDate)
} }
componentDidMount(){ hasError(date) {
// store the data in formData return this.props.required && !date;
this.handleDateChange(this.props.selectedDate);
} }
handleDateChange = (date) => { handleDateChange = (date) => {
const newState = { this.setState({
selectedDate: date, value: date,
hasError: this.hasError(date)
}
this.setState(newState);
this.props.onChange({
data: newState.selectedDate,
hasError: newState.hasError
}); });
} }
...@@ -64,7 +55,7 @@ class DateField extends PureComponent { ...@@ -64,7 +55,7 @@ class DateField extends PureComponent {
<DatePicker <DatePicker
clearable clearable
format="d MMM YYYY" format="d MMM YYYY"
value={this.state.selectedDate} value={this.state.value}
onChange={this.handleDateChange} onChange={this.handleDateChange}
clearLabel="vider" clearLabel="vider"
cancelLabel="annuler" cancelLabel="annuler"
...@@ -78,15 +69,11 @@ class DateField extends PureComponent { ...@@ -78,15 +69,11 @@ class DateField extends PureComponent {
} }
DateField.defaultProps = { DateField.defaultProps = {
required: false, value: null,
label: 'mon label',
selectedDate: null,
onChange: (date) => console.log('Nouvelle date sélectionnée : ', date),
} }
DateField.propTypes = { DateField.propTypes = {
selectedDate: PropTypes.instanceOf(Date), value: PropTypes.instanceOf(Date),
onChange: PropTypes.func.isRequired,
}; };
......
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
class Field extends PureComponent {
state = {
value: this.props.value,
hasError: this.hasError(this.props.value)
};
setState(newState) {
newState.hasError = this.hasError(newState.value);
super.setState(newState);
}
hasError() {
throw Error('This methods has to be override in sub classes')
}
getValue() {
// function to get the value, ready to send to server
// You might need to override this for weird formats such as Date.
return this.state.value;
}
getHasError() {
return this.state.hasError;
}
componentDidMount() {
this.props.formManager.addField(this, this.props.fieldMapping);
}
componentWillUnmount() {
this.props.formManager.removeField(this.props.fieldMapping);
}
}
Field.defaultProps = {
required: false,
label: 'mon label',
}
Field.propTypes = {
required: PropTypes.bool.isRequired,
label: PropTypes.string,
formManager: PropTypes.object.isRequired,
fieldMapping: PropTypes.string.isRequired
};
export default Field;
...@@ -12,20 +12,12 @@ import Typography from '@material-ui/core/Typography'; ...@@ -12,20 +12,12 @@ import Typography from '@material-ui/core/Typography';
import Markdown from '../../../../shared/Markdown'; import Markdown from '../../../../shared/Markdown';
import LinkText from '../../../../other/TextLink'; import LinkText from '../../../../other/TextLink';
import Field from './Field';
const styles = theme => ({ const styles = theme => ({
}) })
class MarkdownField extends React.Component { class MarkdownField extends Field {
state = {
value: this.props.value,
hasError: this.hasError(this.props.value)
};
componentDidMount() {
// store the data in formData
this.handleChangeValue(this.props.value);
}
hasError(value) { hasError(value) {
if (this.props.required && value == '') { if (this.props.required && value == '') {
...@@ -44,21 +36,12 @@ class MarkdownField extends React.Component { ...@@ -44,21 +36,12 @@ class MarkdownField extends React.Component {
if (maxLength && value.length > maxLength + 1) { if (maxLength && value.length > maxLength + 1) {
value = value.substring(0, maxLength + 1); value = value.substring(0, maxLength + 1);
} }
const newState = { this.setState({ value });
value,
hasError: this.hasError(value)
}
this.setState(newState);
this.props.onChange({
data: newState.value,
hasError: newState.hasError
});
} }
render() { render() {
const { classes } = this.props; const { classes } = this.props;
return ( return (
<FieldWrapper <FieldWrapper
required={this.props.required} required={this.props.required}
...@@ -110,16 +93,12 @@ class MarkdownField extends React.Component { ...@@ -110,16 +93,12 @@ class MarkdownField extends React.Component {
MarkdownField.defaultProps = { MarkdownField.defaultProps = {
required: false,
value: '', value: '',
label: 'mon label',
maxLength: 0, maxLength: 0,
} }
MarkdownField.propTypes = { MarkdownField.propTypes = {
required: PropTypes.bool,
value: PropTypes.string, value: PropTypes.string,
label: PropTypes.string,
maxLength: PropTypes.number maxLength: PropTypes.number
}; };
......
...@@ -11,36 +11,20 @@ import Select from '@material-ui/core/Select'; ...@@ -11,36 +11,20 @@ import Select from '@material-ui/core/Select';
import TextField from '@material-ui/core/TextField'; import TextField from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import Field from './Field';
const styles = theme => ({ const styles = theme => ({
}) })
class SelectField extends React.Component { class SelectField extends Field {
state = {
value: this.props.value,
hasError: this.hasError(this.props.value)
};
hasError(value) { hasError(value) {
if (this.props.required && !value) { return this.props.required && !value;
return true;
} else {
return false;
}
} }
handleChangeValue = (value) => { handleChangeValue = (value) => {
const newState = { this.setState({ value });
value,
hasError: this.hasError(value)
}
this.setState(newState);
this.props.onChange({
data: newState.value,
hasError: newState.hasError
})
} }
render() { render() {
const { classes } = this.props; const { classes } = this.props;
return ( return (
...@@ -68,22 +52,16 @@ class SelectField extends React.Component { ...@@ -68,22 +52,16 @@ class SelectField extends React.Component {
SelectField.defaultProps = { SelectField.defaultProps = {
required: false,
value: null, value: null,
label: 'mon label',
onChange: (data) => console.log('Nouvelle sélection : ', data),
} }
SelectField.propTypes = { SelectField.propTypes = {
required: PropTypes.bool,
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
options: PropTypes.arrayOf(PropTypes.shape({ options: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]), value: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]),
disabled: PropTypes.bool disabled: PropTypes.bool
})), })),
label: PropTypes.string,
onChange: PropTypes.func.isRequired,
}; };
......
...@@ -8,16 +8,12 @@ import FieldWrapper from './FieldWrapper'; ...@@ -8,16 +8,12 @@ import FieldWrapper from './FieldWrapper';
import { TextField as MuiTextField } from '@material-ui/core/TextField'; import { TextField as MuiTextField } from '@material-ui/core/TextField';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import Field from './Field';
const styles = theme => ({ const styles = theme => ({
}) })
class TextField extends React.Component { class TextField extends Field {
state = {
value: this.props.value,
hasError: this.hasError(this.props.value)
};
hasError(value) { hasError(value) {
if (this.props.required && value == '') { if (this.props.required && value == '') {
return true; return true;
...@@ -36,15 +32,7 @@ class TextField extends React.Component { ...@@ -36,15 +32,7 @@ class TextField extends React.Component {
value = value.substring(0, maxLength + 1); value = value.substring(0, maxLength + 1);
} }
const newState = { this.setState({ value });
value,
hasError: this.hasError(value)
}
this.setState(newState);
this.props.onChange({
data: newState.value,
hasError: newState.hasError
})
}