Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Rex Dri
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
32
Issues
32
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Rex Dri
Rex Dri
Commits
16553345
Commit
16553345
authored
Mar 01, 2019
by
Florent Chehab
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated error handling in the app
Fixed
#69
parent
3b11b824
Pipeline
#35739
failed with stages
in 0 seconds
Changes
14
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
98 additions
and
70 deletions
+98
-70
frontend/src/components/university/editors/UniversitySemestersDatesEditor.js
...ents/university/editors/UniversitySemestersDatesEditor.js
+2
-1
frontend/src/components/university/shared/Editor.js
frontend/src/components/university/shared/Editor.js
+5
-5
frontend/src/components/university/shared/Form.js
frontend/src/components/university/shared/Form.js
+10
-32
frontend/src/components/university/shared/ScholarshipForm.js
frontend/src/components/university/shared/ScholarshipForm.js
+2
-1
frontend/src/components/university/shared/fields/DateField.js
...tend/src/components/university/shared/fields/DateField.js
+4
-3
frontend/src/components/university/shared/fields/Field.js
frontend/src/components/university/shared/fields/Field.js
+9
-7
frontend/src/components/university/shared/fields/FieldWrapper.js
...d/src/components/university/shared/fields/FieldWrapper.js
+16
-9
frontend/src/components/university/shared/fields/MarkdownField.js
.../src/components/university/shared/fields/MarkdownField.js
+5
-2
frontend/src/components/university/shared/fields/MultiSelectField.js
...c/components/university/shared/fields/MultiSelectField.js
+3
-2
frontend/src/components/university/shared/fields/NumberField.js
...nd/src/components/university/shared/fields/NumberField.js
+3
-2
frontend/src/components/university/shared/fields/SelectField.js
...nd/src/components/university/shared/fields/SelectField.js
+3
-2
frontend/src/components/university/shared/fields/TextField.js
...tend/src/components/university/shared/fields/TextField.js
+3
-2
frontend/src/components/university/shared/fields/UsefulLinksField.js
...c/components/university/shared/fields/UsefulLinksField.js
+3
-2
frontend/src/utils/CustomError.js
frontend/src/utils/CustomError.js
+30
-0
No files found.
frontend/src/components/university/editors/UniversitySemestersDatesEditor.js
View file @
16553345
...
...
@@ -15,6 +15,7 @@ import getMapDispatchToPropsForEditor from "../shared/editorFunctions/getMapDisp
import
Form
from
"
../shared/Form
"
;
import
{
withSnackbar
}
from
"
notistack
"
;
import
CustomError
from
"
../../../utils/CustomError
"
;
const
styles
=
theme
=>
({
...
...
@@ -44,7 +45,7 @@ class UniversitySemestersDatesForm extends Form {
messages
.
push
(
"
Le début du semestre de printemps doit être antérieur à sa fin...
"
);
}
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
render
()
{
...
...
frontend/src/components/university/shared/Editor.js
View file @
16553345
...
...
@@ -57,8 +57,8 @@ class Editor extends Component {
/////////
// Shortcut functions to those of the form instance
formHas
Error
()
{
return
this
.
getForm
().
has
Error
();
getForm
Error
()
{
return
this
.
getForm
().
get
Error
();
}
getFormData
()
{
...
...
@@ -79,8 +79,8 @@ class Editor extends Component {
* @memberof Editor
*/
handleSaveEditorRequest
()
{
const
formHasError
=
this
.
formHas
Error
();
if
(
!
formHas
Error
.
status
)
{
// no error, we can save if necessary
const
getFormError
=
this
.
getForm
Error
();
if
(
!
getForm
Error
.
status
)
{
// no error, we can save if necessary
if
(
this
.
props
.
forceSave
||
this
.
formHasChanges
())
{
// Copy the model data and copy above the data from the form
// So that we don't forget anything.
...
...
@@ -93,7 +93,7 @@ class Editor extends Component {
}
}
else
{
this
.
notifyFormHasErrors
(
formHas
Error
.
messages
);
this
.
notifyFormHasErrors
(
getForm
Error
.
messages
);
}
}
...
...
frontend/src/components/university/shared/Form.js
View file @
16553345
...
...
@@ -3,6 +3,7 @@ import PropTypes from "prop-types";
import
areSameObjects
from
"
../../../utils/areSameObjects
"
;
import
renderFieldsMixIn
from
"
./renderFieldsMixIn
"
;
import
CustomError
from
"
../../../utils/CustomError
"
;
/**
* React component that should contain `Field` instances.
...
...
@@ -77,40 +78,19 @@ class Form extends Component {
}
/**
* Function to build a generic way of handling field errors
*
* @param {Array} messages
* @returns
* @memberof Form
*/
buildError
(
messages
)
{
return
{
status
:
messages
.
length
>
0
,
messages
};
}
/**
* Combine errors constructed with buildError
*
* @param {array} arrayOfErrors
* @returns
* @memberof Form
*/
combineErrors
(
arrayOfErrors
)
{
return
this
.
buildError
(
arrayOfErrors
.
flatMap
(
error
=>
error
.
messages
));
}
/**
* Function to build all the errors from the fields of the form.
*
* TODO change setup with new custom error
*
* @returns
* @memberof Form
*/
fieldsHaveError
()
{
const
messages
=
this
.
getFields
()
.
map
(({
field
})
=>
field
.
has
Error
().
messages
)
.
map
(({
field
})
=>
field
.
get
Error
().
messages
)
.
filter
(
messages
=>
messages
.
length
>
0
);
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
/**
...
...
@@ -122,11 +102,9 @@ class Form extends Component {
* @returns
* @memberof Form
*/
hasError
()
{
return
this
.
combineErrors
([
this
.
fieldsHaveError
(),
this
.
hasFormLevelErrors
()
]);
getError
()
{
return
this
.
fieldsHaveError
()
.
combine
(
this
.
hasFormLevelErrors
());
}
/**
...
...
@@ -134,11 +112,11 @@ class Form extends Component {
*
* Can be override in sub classes
*
* @returns
object built with this.buildError
* @returns
{CustomError}
* @memberof Form
*/
hasFormLevelErrors
()
{
return
this
.
fieldsHaveError
();
return
CustomError
([]);
// default: no errors
}
...
...
frontend/src/components/university/shared/ScholarshipForm.js
View file @
16553345
...
...
@@ -2,6 +2,7 @@ import React from "react";
import
PropTypes
from
"
prop-types
"
;
import
Form
from
"
./Form
"
;
import
CustomError
from
"
../../../utils/CustomError
"
;
const
frequencyOptions
=
[
{
value
:
"
w
"
,
label
:
"
Il s'agit du montant hebdomadaire
"
},
...
...
@@ -21,7 +22,7 @@ class ScholarshipForm extends Form {
messages
.
push
(
"
La logique voudrait que la borne supérieure de la bourse soit... supérieure à la borne inférieure.
"
);
}
return
this
.
build
Error
(
messages
);
return
Custom
Error
(
messages
);
}
render
()
{
...
...
frontend/src/components/university/shared/fields/DateField.js
View file @
16553345
...
...
@@ -12,7 +12,7 @@ import KeyboardArrowRightIcon from "@material-ui/icons/KeyboardArrowRight";
import
dateToDateStr
from
"
../../../../utils/dateToDateStr
"
;
import
Field
from
"
./Field
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
/**
* Class to customize the header of the date selection box
...
...
@@ -32,13 +32,14 @@ class DateField extends Field {
return
dateToDateStr
(
this
.
state
.
value
);
}
has
Error
()
{
get
Error
()
{
const
date
=
this
.
state
.
value
;
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
!
date
)
{
messages
.
push
(
"
Date requise !
"
);
}
return
this
.
buildError
(
messages
);
return
new
CustomError
(
messages
);
}
handleDateChange
=
(
date
)
=>
{
...
...
frontend/src/components/university/shared/fields/Field.js
View file @
16553345
...
...
@@ -3,6 +3,8 @@ import { PureComponent } from "react";
import
PropTypes
from
"
prop-types
"
;
import
Form
from
"
../Form
"
;
import
FieldWrapper
from
"
./FieldWrapper
"
;
// eslint-disable-next-line no-unused-vars
import
CustomError
from
"
../../../../utils/CustomError
"
;
/**
* Class that handle fields logic
...
...
@@ -43,13 +45,14 @@ class Field extends PureComponent {
super
.
setState
(
newState
);
}
hasError
()
{
/**
* @returns {CustomError}
* @memberof Field
*/
getError
()
{
throw
Error
(
"
This methods has to be override in sub classes
"
);
}
buildError
(
messages
)
{
return
{
status
:
messages
.
length
>
0
,
messages
};
}
/**
* function to get serialize the value from the field, to get it ready to send to server
...
...
@@ -58,7 +61,7 @@ class Field extends PureComponent {
* @returns
* @memberof Field
*/
serializeFromField
(){
serializeFromField
()
{
return
this
.
state
.
value
;
}
...
...
@@ -87,8 +90,7 @@ class Field extends PureComponent {
return
(
<
FieldWrapper
required
=
{
this
.
props
.
required
}
hasError
=
{
this
.
hasError
().
status
}
errors
=
{
this
.
hasError
().
messages
}
errorObj
=
{
this
.
getError
()}
label
=
{
this
.
props
.
label
}
>
{
this
.
renderField
()}
...
...
frontend/src/components/university/shared/fields/FieldWrapper.js
View file @
16553345
...
...
@@ -7,21 +7,28 @@ import compose from "recompose/compose";
import
FormControl
from
"
@material-ui/core/FormControl
"
;
import
FormLabel
from
"
@material-ui/core/FormLabel
"
;
import
FormHelperText
from
"
@material-ui/core/FormHelperText
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
/**
* Wrapper for fields in form to handle labels and visual feedback
*
* @class FieldWrapper
* @extends {PureComponent}
*/
class
FieldWrapper
extends
PureComponent
{
render
()
{
const
{
props
}
=
thi
s
;
const
{
classes
,
required
,
errorObj
,
label
,
children
}
=
this
.
prop
s
;
return
(
<
FormControl
className
=
{
props
.
classes
.
formElement
}
required
=
{
props
.
required
}
error
=
{
props
.
hasError
}
fullWidth
=
{
true
}
>
<
FormLabel
>
{
props
.
label
}
<
/FormLabel
>
<
FormControl
className
=
{
classes
.
formElement
}
required
=
{
required
}
error
=
{
errorObj
.
status
}
fullWidth
=
{
true
}
>
<
FormLabel
>
{
label
}
<
/FormLabel
>
{
props
.
error
s
.
map
((
error
,
idx
)
=>
(
errorObj
.
message
s
.
map
((
error
,
idx
)
=>
(
<
FormHelperText
key
=
{
idx
}
>
{
error
}
<
/FormHelperText
>
))
}
{
props
.
children
}
{
children
}
<
/FormControl
>
);
}
...
...
@@ -30,15 +37,15 @@ class FieldWrapper extends PureComponent {
FieldWrapper
.
defaultProps
=
{
label
:
"
LABEL
"
,
required
:
false
,
hasError
:
false
,
errors
:
[]
errorObj
:
new
CustomError
(),
};
FieldWrapper
.
propTypes
=
{
label
:
PropTypes
.
string
.
isRequired
,
errorObj
:
PropTypes
.
instanceOf
(
CustomError
).
isRequired
,
classes
:
PropTypes
.
object
.
isRequired
,
required
:
PropTypes
.
bool
.
isRequired
,
hasError
:
PropTypes
.
bool
.
isRequired
,
errors
:
PropTypes
.
arrayOf
(
PropTypes
.
string
.
isRequired
).
isRequired
,
children
:
PropTypes
.
node
.
isRequired
,
};
...
...
frontend/src/components/university/shared/fields/MarkdownField.js
View file @
16553345
...
...
@@ -10,11 +10,13 @@ import Markdown from "../../../shared/Markdown";
import
LinkText
from
"
../../../other/TextLink
"
;
import
Field
from
"
./Field
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
class
MarkdownField
extends
Field
{
defaultNullValue
=
""
;
has
Error
()
{
get
Error
()
{
const
{
value
}
=
this
.
state
;
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
value
==
""
)
{
...
...
@@ -23,7 +25,8 @@ class MarkdownField extends Field {
if
(
this
.
props
.
maxLength
&&
value
.
length
>
this
.
props
.
maxLength
)
{
messages
.
push
(
"
Le texte est trop long.
"
);
}
return
this
.
buildError
(
messages
);
return
new
CustomError
(
messages
);
}
handleChangeValue
=
(
val
)
=>
{
...
...
frontend/src/components/university/shared/fields/MultiSelectField.js
View file @
16553345
...
...
@@ -8,6 +8,7 @@ import Select from "@material-ui/core/Select";
import
Checkbox
from
"
@material-ui/core/Checkbox
"
;
import
Field
from
"
./Field
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
class
MultiSelectField
extends
Field
{
...
...
@@ -18,13 +19,13 @@ class MultiSelectField extends Field {
props
.
options
.
map
((
opt
)
=>
this
.
optionsByValue
[
opt
.
value
]
=
opt
.
label
);
}
has
Error
()
{
get
Error
()
{
const
{
value
}
=
this
.
state
;
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
value
.
length
===
0
)
{
messages
.
push
(
"
Ce champ est requis.
"
);
}
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
handleChangeValue
=
(
value
)
=>
{
...
...
frontend/src/components/university/shared/fields/NumberField.js
View file @
16553345
...
...
@@ -5,12 +5,13 @@ import TextField from "@material-ui/core/TextField";
import
Typography
from
"
@material-ui/core/Typography
"
;
import
Field
from
"
./Field
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
class
NumberField
extends
Field
{
defaultNullValue
=
""
;
has
Error
()
{
get
Error
()
{
const
{
value
}
=
this
.
state
;
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
value
==
""
)
{
...
...
@@ -22,7 +23,7 @@ class NumberField extends Field {
if
(
this
.
props
.
minValue
&&
value
<
this
.
props
.
minValue
)
{
messages
.
push
(
"
Le nombre inscrit est trop petit.
"
);
}
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
handleChangeValue
=
(
val
)
=>
{
...
...
frontend/src/components/university/shared/fields/SelectField.js
View file @
16553345
...
...
@@ -6,6 +6,7 @@ import MenuItem from "@material-ui/core/MenuItem";
import
Select
from
"
@material-ui/core/Select
"
;
import
Field
from
"
./Field
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
import
withStyles
from
"
@material-ui/core/styles/withStyles
"
;
...
...
@@ -40,14 +41,14 @@ class SelectField extends Field {
super
(
props
,
customStateAttrs
);
}
has
Error
()
{
get
Error
()
{
const
{
value
}
=
this
.
state
;
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
(
value
===
null
))
{
messages
.
push
(
"
Ce champ est requis.
"
);
}
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
handleChangeValue
=
(
value
)
=>
{
...
...
frontend/src/components/university/shared/fields/TextField.js
View file @
16553345
...
...
@@ -7,12 +7,13 @@ import Typography from "@material-ui/core/Typography";
import
Field
from
"
./Field
"
;
import
isUrl
from
"
../../../../utils/isUrl
"
;
import
stringHasExtension
from
"
../../../../utils/stringHasExtension
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
class
TextField
extends
Field
{
defaultNullValue
=
""
;
has
Error
()
{
get
Error
()
{
const
{
value
}
=
this
.
state
;
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
value
==
""
)
{
...
...
@@ -29,7 +30,7 @@ class TextField extends Field {
messages
.
push
(
"
Extension de l'URL non conforme
"
);
}
}
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
handleChangeValue
=
(
val
)
=>
{
...
...
frontend/src/components/university/shared/fields/UsefulLinksField.js
View file @
16553345
...
...
@@ -16,12 +16,13 @@ import Field from "./Field";
import
Typography
from
"
@material-ui/core/Typography
"
;
import
isUrl
from
"
../../../../utils/isUrl
"
;
import
CustomError
from
"
../../../../utils/CustomError
"
;
class
UsefulLinksField
extends
Field
{
has
Error
()
{
get
Error
()
{
const
usefulLinks
=
this
.
state
.
value
;
let
messages
=
Array
();
...
...
@@ -58,7 +59,7 @@ class UsefulLinksField extends Field {
});
if
(
!
lengthOk
)
{
messages
.
push
(
"
Un url ou une description est trop longue.
"
);
}
return
this
.
build
Error
(
messages
);
return
new
Custom
Error
(
messages
);
}
serializeFromField
()
{
...
...
frontend/src/utils/CustomError.js
0 → 100644
View file @
16553345
/**
* Class to handle app errors (such as form errors) in a nice wrapped way
* It's for non fatal errors.
*
* @export
* @class CustomError
*/
export
default
class
CustomError
{
/**
*Creates an instance of CustomError.
*
* @param {Array[string] = []} messages
* @memberof CustomError
*/
constructor
(
messages
=
[])
{
this
.
messages
=
messages
;
this
.
status
=
messages
.
length
>
0
;
}
/**
* Method to combine to error class
*
* @param {CustomError} other
* @returns {CustomError}
* @memberof CustomError
*/
combine
(
other
)
{
return
new
CustomError
(
Array
.
prototype
.
concat
(
this
.
messages
,
other
.
messages
));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment