Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Rex Dri
Rex Dri
Commits
9978774c
Commit
9978774c
authored
Feb 28, 2019
by
Florent Chehab
Browse files
Updated field/form setup to prevent bugs with with styles
Other adaptations with new setup
parent
83ecd677
Changes
4
Hide whitespace changes
Inline
Side-by-side
frontend/src/components/university/shared/Editor.js
View file @
9978774c
...
...
@@ -9,8 +9,6 @@ import Typography from "@material-ui/core/Typography";
import
CloseIcon
from
"
@material-ui/icons/Close
"
;
import
Alert
from
"
./Alert
"
;
// import renderFieldsMixIn from "./editorFunctions/renderFieldsMixIn";
// Form is imported only for type hints
// eslint-disable-next-line no-unused-vars
import
Form
from
"
./Form
"
;
...
...
@@ -114,6 +112,12 @@ class Editor extends Component {
}
/**
* Function to handle close editor request from the user.
* It checks if there is data to save or not.
*
* @memberof Editor
*/
handleCloseEditorRequest
()
{
if
(
this
.
formHasChanges
())
{
this
.
alertChangesNotSaved
();
...
...
@@ -316,8 +320,6 @@ class Editor extends Component {
}
// TODO move this to form and update
// Object.assign(Editor.prototype, renderFieldsMixIn);
Editor
.
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
...
...
frontend/src/components/university/shared/Form.js
View file @
9978774c
...
...
@@ -2,6 +2,7 @@ import React, { Component } from "react";
import
PropTypes
from
"
prop-types
"
;
import
areSameObjects
from
"
../../../utils/areSameObjects
"
;
import
renderFieldsMixIn
from
"
./renderFieldsMixIn
"
;
/**
* React component that should contain `Field` instances.
...
...
@@ -19,24 +20,35 @@ class Form extends Component {
* This method MUST be used on all field inside a `Form` instance.
*
* Function that returns the value corresponding to `fieldMapping` and
* a reference for the field. This reference is stored in the Form class so that
* we can easily access the fields value from the form.
* a reference to the Form so that the fields can subscribe.
*
* @param {string} fieldMapping
* @param {function} [convertValue=v => v] Method applied to the value from the modelData to get "the value"
* @memberof Form
*/
getReferenceAndValue
(
fieldMapping
)
{
const
ref
=
React
.
createRef
();
this
.
fields
[
fieldMapping
]
=
ref
;
// store the reference for later use
return
{
value
:
this
.
props
.
modelData
[
fieldMapping
],
ref
};
getReferenceAndValue
(
fieldMapping
,
convertValue
=
v
=>
v
)
{
// using react ref was to complicated with ref forwarding not working with withStyles.
return
{
value
:
convertValue
(
this
.
props
.
modelData
[
fieldMapping
]),
form
:
this
,
fieldMapping
};
}
/**
* Function to be used in fields so that they subscribe to a form
*
* Using ref to field is not working with withStyles ref forwarding issues.
*
* @param {string} fieldMapping
* @param {Field} field
* @memberof Form
*/
fieldSubscribe
(
fieldMapping
,
field
)
{
this
.
fields
[
fieldMapping
]
=
field
;
}
/**
* Function that returns the fields contained in the form
* as an array of {fieldMapping: string, field: Field}
*
* Works only if the `getReferenceAndValue` was used on the Field props.
* Works only if the `getReferenceAndValue` was used on the Field props
and the field subscribed
.
*
* @returns {Array}
* @memberof Form
...
...
@@ -44,7 +56,7 @@ class Form extends Component {
getFields
()
{
return
Object
.
keys
(
this
.
fields
)
.
map
(
fieldMapping
=>
({
fieldMapping
,
field
:
this
.
fields
[
fieldMapping
]
.
current
})
({
fieldMapping
,
field
:
this
.
fields
[
fieldMapping
]
})
);
}
...
...
@@ -77,6 +89,17 @@ class Form extends Component {
}
/**
* 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.
*
...
...
@@ -130,6 +153,9 @@ class Form extends Component {
}
// Copy all the custom already ready render fields mix in
Object
.
assign
(
Form
.
prototype
,
renderFieldsMixIn
);
Form
.
propTypes
=
{
...
...
frontend/src/components/university/shared/fields/Field.js
View file @
9978774c
import
{
PureComponent
}
from
"
react
"
;
import
PropTypes
from
"
prop-types
"
;
import
Form
from
"
../Form
"
;
class
Field
extends
PureComponent
{
constructor
(
props
)
{
super
(
props
);
// make sure to subscribe ! IMPORTANT
props
.
form
.
fieldSubscribe
(
props
.
fieldMapping
,
this
);
let
{
value
}
=
props
;
if
(
typeof
this
.
defaultNullValue
!==
"
undefined
"
&&
value
===
null
)
{
value
=
this
.
defaultNullValue
;
...
...
@@ -50,6 +54,8 @@ Field.propTypes = {
required
:
PropTypes
.
bool
.
isRequired
,
label
:
PropTypes
.
string
,
value
:
PropTypes
.
isRequired
,
form
:
PropTypes
.
oneOf
([
Form
]).
isRequired
,
fieldMapping
:
PropTypes
.
string
.
isRequired
,
};
export
default
Field
;
frontend/src/components/university/shared/
editorFunctions/
renderFieldsMixIn.js
→
frontend/src/components/university/shared/renderFieldsMixIn.js
View file @
9978774c
import
React
from
"
react
"
;
import
Typography
from
"
@material-ui/core/Typography
"
;
import
getObjModerationLevel
from
"
../../../../utils/getObjModerationLevels
"
;
import
SelectField
from
"
../fields/SelectField
"
;
import
UsefulLinksField
from
"
../fields/UsefulLinksField
"
;
import
MarkdownField
from
"
../fields/MarkdownField
"
;
import
TextField
from
"
../fields/TextField
"
;
import
MultiSelectField
from
"
../fields/MultiSelectField
"
;
import
NumberField
from
"
../fields/NumberField
"
;
import
getObjModerationLevel
from
"
../../../utils/getObjModerationLevels
"
;
import
SelectField
from
"
./fields/SelectField
"
;
import
UsefulLinksField
from
"
./fields/UsefulLinksField
"
;
import
MarkdownField
from
"
./fields/MarkdownField
"
;
import
TextField
from
"
./fields/TextField
"
;
import
MultiSelectField
from
"
./fields/MultiSelectField
"
;
import
NumberField
from
"
./fields/NumberField
"
;
import
store
from
"
../../../store/index
"
;
import
{
getLatestRead
}
from
"
../../../api/utils
"
;
import
__map
from
"
lodash/map
"
;
export
default
{
renderObjModerationLevelField
()
{
const
{
obj_moderation_level
}
=
this
.
props
.
modelData
;
const
possibleObjModeration
=
getObjModerationLevel
(
this
.
getReadData
(
"
userData
"
).
owner_level
,
true
);
/**
* For field mixins that handle custom props, we need to make use of getReferenceAndValue too
*
* @param {object} props
* @returns
*/
customizeProps
(
props
)
{
return
Object
.
assign
(
props
,
{
...
this
.
getReferenceAndValue
(
props
.
fieldMapping
)
});
},
renderObjModerationLevelField
()
{
// hack to access directly the store and get the value we need.
const
userData
=
getLatestRead
(
store
.
getState
().
api
.
userDataSpecific
).
data
,
possibleObjModeration
=
getObjModerationLevel
(
userData
.
owner_level
,
true
);
if
(
possibleObjModeration
.
length
>
1
)
{
return
(
<
div
>
<
Typography
variant
=
'
caption
'
>
Niveau
de
modération
souhaité
(
en
plus
TODO
<
/Typography
>
<
SelectField
label
=
{
"
Niveau de modération pour ce module
"
}
{...
this
.
getReferenceAndValue
(
"
obj_moderation_level
"
)}
required
=
{
true
}
value
=
{
obj_moderation_level
}
fieldMapping
=
{
"
obj_moderation_level
"
}
options
=
{
possibleObjModeration
}
formManager
=
{
this
}
/
>
<
/div
>
);
...
...
@@ -37,8 +48,6 @@ export default {
},
renderImportanceLevelField
()
{
const
{
importance_level
}
=
this
.
props
.
modelData
;
//TODO change below use JSON
const
options
=
[
{
"
label
"
:
"
Normal
"
,
"
value
"
:
"
-
"
},
...
...
@@ -50,23 +59,18 @@ export default {
<
div
>
<
Typography
variant
=
'
caption
'
>
Qualification
de
l
'
importance de l
'
information
présentée
<
/Typography
>
<
SelectField
label
=
{
"
Niveau d'importance
"
}
{...
this
.
getReferenceAndValue
(
"
importance_level
"
)}
required
=
{
true
}
value
=
{
importance_level
}
fieldMapping
=
{
"
importance_level
"
}
options
=
{
options
}
formManager
=
{
this
}
/
>
<
/div
>
);
},
renderUsefulLinksField
()
{
const
{
useful_links
}
=
this
.
props
.
modelData
;
return
(
<
UsefulLinksField
label
=
{
"
Lien(s) utile(s) (ex : vers ces informations)
"
}
value
=
{
useful_links
}
formManager
=
{
this
}
fieldMapping
=
{
"
useful_links
"
}
{...
this
.
getReferenceAndValue
(
"
useful_links
"
)}
/
>
);
},
...
...
@@ -74,83 +78,62 @@ export default {
renderMarkdownField
(
props
)
{
return
(
<
MarkdownField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
{...
this
.
customizeProps
(
props
)}
/
>
);
},
renderCommentField
()
{
const
{
comment
}
=
this
.
props
.
modelData
;
return
this
.
renderMarkdownField
({
label
:
"
Commentaire associé à ces informations
"
,
maxLength
:
500
,
value
:
comment
,
formManager
:
this
,
fieldMapping
:
"
comment
"
,
});
},
addValueToProps
(
props
)
{
if
(
typeof
props
.
value
==
"
undefined
"
)
{
return
Object
.
assign
(
props
,
{
value
:
this
.
props
.
modelData
[
props
.
fieldMapping
]
});
}
else
{
return
props
;
}
},
renderTextField
(
props
)
{
return
(
<
TextField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
{...
this
.
customizeProps
(
props
)}
/
>
);
},
renderTitleField
()
{
const
{
title
}
=
this
.
props
.
modelData
;
return
this
.
renderTextField
({
label
:
"
Titre
"
,
required
:
true
,
value
:
title
,
maxLength
:
150
,
fieldMapping
:
"
title
"
,
});
},
renderUniversitiesField
()
{
const
{
modelData
}
=
this
.
props
;
const
{
outsideData
}
=
this
.
props
;
const
universities
=
__map
(
outsideData
.
universities
,
(
univ
)
=>
{
return
{
label
:
univ
.
name
,
value
:
univ
.
id
,
disabled
:
false
};
}
);
const
{
outsideData
}
=
this
.
props
,
universities
=
__map
(
outsideData
.
universities
,
// TODO __map required ?
(
univ
)
=>
{
return
{
label
:
univ
.
name
,
value
:
univ
.
id
,
disabled
:
false
};
}
);
return
(
<
MultiSelectField
label
=
{
"
Universités concernées
"
}
{...
this
.
getReferenceAndValue
(
"
universities
"
)}
required
=
{
true
}
value
=
{
modelData
.
universities
}
options
=
{
universities
}
formManager
=
{
this
}
fieldMapping
=
{
"
universities
"
}
/
>
);
},
renderCountriesField
()
{
const
{
modelData
}
=
this
.
props
;
const
{
outsideData
}
=
this
.
props
;
const
countries
=
__map
(
outsideData
.
countries
,
(
country
)
=>
{
return
{
label
:
country
.
name
,
value
:
country
.
id
,
disabled
:
false
};
}
);
const
{
outsideData
}
=
this
.
props
,
countries
=
__map
(
outsideData
.
countries
,
// TODO __map required ?
(
country
)
=>
{
return
{
label
:
country
.
name
,
value
:
country
.
id
,
disabled
:
false
};
}
);
return
(
<
MultiSelectField
label
=
{
"
Pays concernés
"
}
{...
this
.
getReferenceAndValue
(
"
countries
"
)}
required
=
{
true
}
value
=
{
modelData
.
countries
}
options
=
{
countries
}
formManager
=
{
this
}
fieldMapping
=
{
"
countries
"
}
/
>
);
},
...
...
@@ -158,8 +141,7 @@ export default {
renderSelectField
(
props
)
{
return
(
<
SelectField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
{...
this
.
customizeProps
(
props
)}
/
>
);
},
...
...
@@ -179,10 +161,9 @@ export default {
renderNumberField
(
props
)
{
return
(
<
NumberField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
{...
this
.
customizeProps
(
props
)}
/
>
);
},
};
\ No newline at end of file
};
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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