Skip to content
GitLab
Menu
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
6dfa5edc
Commit
6dfa5edc
authored
Sep 16, 2018
by
Florent Chehab
Browse files
UniversityScholarship editor ok
parent
7aeec929
Pipeline
#27360
passed with stages
in 2 minutes and 54 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
backend/migrations/0003_auto_20180916_1624.py
0 → 100644
View file @
6dfa5edc
# Generated by Django 2.0.3 on 2018-09-16 14:24
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'backend'
,
'0002_auto_20180916_1555'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'countryscholarship'
,
name
=
'frequency'
,
field
=
models
.
CharField
(
blank
=
True
,
choices
=
[(
'w'
,
'week'
),
(
'm'
,
'month'
),
(
's'
,
'semester'
),
(
'y'
,
'year'
),
(
'o'
,
'one_shot'
)],
default
=
'm'
,
max_length
=
1
,
null
=
True
),
),
migrations
.
AlterField
(
model_name
=
'universityscholarship'
,
name
=
'frequency'
,
field
=
models
.
CharField
(
blank
=
True
,
choices
=
[(
'w'
,
'week'
),
(
'm'
,
'month'
),
(
's'
,
'semester'
),
(
'y'
,
'year'
),
(
'o'
,
'one_shot'
)],
default
=
'm'
,
max_length
=
1
,
null
=
True
),
),
]
backend/models/abstract/scholarship/scholarship.py
View file @
6dfa5edc
...
...
@@ -17,12 +17,15 @@ class Scholarship(BasicModule):
type
=
models
.
CharField
(
max_length
=
200
)
currency
=
models
.
ForeignKey
(
Currency
,
null
=
True
,
on_delete
=
models
.
PROTECT
)
other_advantages
=
models
.
CharField
(
default
=
''
,
blank
=
True
,
max_length
=
5000
)
other_advantages
=
models
.
CharField
(
default
=
''
,
blank
=
True
,
max_length
=
5000
)
frequency
=
models
.
CharField
(
max_length
=
1
,
choices
=
SCHOLARSHIP_FREQUENCIES
,
default
=
'm'
,
null
=
True
,
blank
=
True
,
)
amount_min
=
models
.
DecimalField
(
...
...
frontend/src/components/shared/Markdown.js
View file @
6dfa5edc
...
...
@@ -12,7 +12,7 @@ import TableRow from '@material-ui/core/TableRow';
import
Paper
from
'
@material-ui/core/Paper
'
;
import
{
lighten
,
darken
}
from
'
@material-ui/core/styles/colorManipulator
'
;
import
{
Divider
}
from
'
@material-ui/core
'
;
import
Divider
from
'
@material-ui/core
/Divider
'
;
import
LinkText
from
'
../other/TextLink
'
;
const
styles
=
(
theme
)
=>
{
...
...
frontend/src/components/university/editors/UniversityScholarshipsEditor.js
View file @
6dfa5edc
...
...
@@ -20,17 +20,60 @@ const styles = theme => ({
...
editorStyle
(
theme
)
});
const
frequencyOptions
=
[
{
value
:
'
w
'
,
label
:
"
Il s'agit du montant hebdomadaire
"
},
{
value
:
'
m
'
,
label
:
"
Il s'agit du montant mensuel
"
},
{
value
:
'
s
'
,
label
:
"
Il s'agit du montant semestriel
"
},
{
value
:
'
y
'
,
label
:
"
Il s'agit du montant annuel
"
},
{
value
:
'
o
'
,
label
:
"
Il s'agit d'un montant donné une seule fois
"
}
]
class
UniversityScholarshipsEditor
extends
Editor
{
formHasError
()
{
let
messages
=
Array
();
const
formData
=
this
.
getDataFromFields
();
const
{
amount_min
,
amount_max
}
=
formData
;
console
.
log
(
formData
);
if
(
amount_min
!==
null
&&
amount_max
!==
null
&&
amount_max
<
amount_min
)
{
messages
.
push
(
"
La logique voudrait que la borne supérieure de la bourse soit... supérieure à la borne inférieure.
"
)
}
return
this
.
buildError
(
messages
);
}
renderEditor
()
{
const
{
modelData
}
=
this
.
props
;
return
(
<
div
>
{
this
.
renderObjModerationLevelField
()}
{
this
.
renderTitleField
()}
{
this
.
renderUniversitiesField
()}
{
this
.
renderTextField
({
required
:
true
,
label
:
"
Présentation succincte
"
,
maxLength
:
200
,
fieldMapping
:
'
type
'
,
})}
{
this
.
renderCurrencyField
({
label
:
"
Devise
"
,
required
:
false
,
fieldMapping
:
'
currency
'
})}
{
this
.
renderNumberField
({
label
:
"
Borne inférieure du montant de la bourse
"
,
minValue
:
0
,
fieldMapping
:
'
amount_min
'
,
})}
{
this
.
renderNumberField
({
label
:
"
Borne supérieure du montant de la bourse
"
,
minValue
:
0
,
fieldMapping
:
'
amount_max
'
,
})}
{
this
.
renderSelectField
({
label
:
"
Fréquence de la bourse
"
,
options
:
frequencyOptions
,
fieldMapping
:
'
frequency
'
,
})}
{
this
.
renderMarkdownField
({
label
:
"
Autres avantages
"
,
maxLength
:
500
,
formManager
:
this
,
fieldMapping
:
'
other_advantages
'
,
})}
{
this
.
renderCommentField
()}
{
this
.
renderUsefulLinksField
()}
<
/div
>
...
...
frontend/src/components/university/modules/UniversityScholarships.js
View file @
6dfa5edc
...
...
@@ -94,7 +94,7 @@ class UniversityScholarships extends MyComponent {
editor
=
{
UniversityScholarshipsEditor
}
invalidateGroup
=
{
this
.
props
.
invalidateData
}
propsForEditor
=
{{
modelData
:
{
universities
:
[
this
.
props
.
univId
],
importance_level
:
'
-
'
},
modelData
:
{
universities
:
[
this
.
props
.
univId
],
importance_level
:
'
-
'
,
currency
:
'
EUR
'
,
obj_moderation_level
:
0
},
parseRawModelData
:
parseRawModelData
,
outsideData
:
outsideData
,
__apiAttr
:
this
.
props
.
univId
,
...
...
frontend/src/components/university/shared/Editor.js
View file @
6dfa5edc
...
...
@@ -19,6 +19,7 @@ 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
__map
from
'
lodash/map
'
;
...
...
@@ -297,31 +298,54 @@ class Editor extends MyComponent {
)
}
renderCommentField
()
{
const
{
comment
}
=
this
.
props
.
modelData
;
renderMarkdownField
(
props
)
{
return
(
<
MarkdownField
label
=
{
"
Commentaire associé à ces informations
"
}
maxLength
=
{
100
}
value
=
{
comment
}
<
MarkdownField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
fieldMapping
=
{
'
comment
'
}
/
>
)
}
renderTitleField
()
{
const
{
title
}
=
this
.
props
.
modelData
;
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
label
=
{
"
Titre
"
}
required
=
{
true
}
value
=
{
title
}
maxLength
=
{
150
}
<
TextField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
fieldMapping
=
{
'
title
'
}
/
>
)
}
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
;
...
...
@@ -358,6 +382,36 @@ class Editor extends MyComponent {
)
}
renderSelectField
(
props
)
{
return
(
<
SelectField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
/
>
)
}
renderCurrencyField
(
props
)
{
const
{
outsideData
}
=
this
.
props
;
const
currencies
=
__map
(
outsideData
.
currencies
,
(
c
)
=>
{
return
{
label
:
c
.
code
,
value
:
c
.
code
,
disabled
:
false
}
}
)
return
this
.
renderSelectField
({
...
props
,
options
:
currencies
,
})
}
renderNumberField
(
props
)
{
return
(
<
NumberField
{...
this
.
addValueToProps
(
props
)}
formManager
=
{
this
}
/
>
)
}
myRender
()
{
const
{
classes
}
=
this
.
props
;
return
(
...
...
frontend/src/components/university/shared/Scholarship.js
View file @
6dfa5edc
...
...
@@ -119,7 +119,7 @@ class Scholarship extends React.Component {
<
div
>
<
Typography
className
=
{
classes
.
item
}
variant
=
'
headline
'
>
Autre
(
s
)
avantage
(
s
)
:
<
/Typography
>
{
otherAdvantages
!=
''
?
otherAdvantages
!=
''
&&
otherAdvantages
!==
null
?
<
Markdown
source
=
{
otherAdvantages
}
/
>
:
<
Typography
variant
=
'
caption
'
><
em
>
Aucun
autre
avantage
a
été
notifié
.
<
/em></
Typography
>
...
...
@@ -147,10 +147,10 @@ Scholarship.propTypes = {
classes
:
PropTypes
.
object
.
isRequired
,
theme
:
PropTypes
.
object
.
isRequired
,
currency
:
PropTypes
.
string
.
isRequired
,
frequency
:
PropTypes
.
string
.
isRequired
,
frequency
:
PropTypes
.
string
,
type
:
PropTypes
.
string
.
isRequired
,
comment
:
PropTypes
.
string
.
isRequired
,
otherAdvantages
:
PropTypes
.
string
.
isRequired
,
otherAdvantages
:
PropTypes
.
string
,
amountMin
:
PropTypes
.
string
,
amountMax
:
PropTypes
.
string
,
};
...
...
frontend/src/components/university/shared/fields/Field.js
View file @
6dfa5edc
...
...
@@ -2,10 +2,19 @@ import React, { PureComponent } from 'react';
import
PropTypes
from
'
prop-types
'
;
class
Field
extends
PureComponent
{
state
=
{
value
:
this
.
props
.
value
,
error
:
this
.
hasError
(
this
.
props
.
value
)
};
constructor
(
props
)
{
super
(
props
);
let
{
value
}
=
props
;
if
(
typeof
this
.
defaultNullValue
!==
'
undefined
'
&&
value
===
null
)
{
value
=
this
.
defaultNullValue
;
}
this
.
state
=
{
value
:
value
,
error
:
this
.
hasError
(
value
)
};
}
setState
(
newState
)
{
newState
.
error
=
this
.
hasError
(
newState
.
value
);
...
...
frontend/src/components/university/shared/fields/MarkdownField.js
View file @
6dfa5edc
...
...
@@ -18,6 +18,7 @@ const styles = theme => ({
})
class
MarkdownField
extends
Field
{
defaultNullValue
=
''
;
hasError
(
value
)
{
let
messages
=
Array
();
...
...
frontend/src/components/university/shared/fields/NumberField.js
0 → 100644
View file @
6dfa5edc
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
withStyles
from
'
@material-ui/core/styles/withStyles
'
;
import
compose
from
'
recompose/compose
'
;
import
FieldWrapper
from
'
./FieldWrapper
'
;
import
TextField
from
'
@material-ui/core/TextField
'
;
import
Typography
from
'
@material-ui/core/Typography
'
;
import
Field
from
'
./Field
'
;
const
styles
=
theme
=>
({
})
class
NumberField
extends
Field
{
defaultNullValue
=
''
;
getValue
()
{
const
{
value
}
=
this
.
state
;
if
(
value
===
''
)
{
return
null
;
}
else
{
return
value
;
}
}
hasError
(
value
)
{
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
value
==
''
)
{
messages
.
push
(
"
Ce champ est requis mais il est vide.
"
);
}
if
(
this
.
props
.
maxValue
&&
value
>
this
.
props
.
maxValue
)
{
messages
.
push
(
"
Le nombre inscrit est trop grand.
"
);
}
if
(
this
.
props
.
minValue
&&
value
<
this
.
props
.
minValue
)
{
messages
.
push
(
"
Le nombre inscrit est trop petit.
"
);
}
return
this
.
buildError
(
messages
)
}
handleChangeValue
=
(
val
)
=>
{
var
regex
=
/
[^\d\.]
*/gi
;
const
value
=
val
.
replace
(
regex
,
''
);
this
.
setState
({
value
});
}
renderInfo
()
{
const
{
minValue
,
maxValue
}
=
this
.
props
;
if
(
maxValue
!==
null
&&
minValue
!==
null
)
{
return
<
Typography
variant
=
'
caption
'
>
Un
nombre
compris
entre
{
minValue
}
et
{
maxValue
}
est
attendu
.
<
/Typography
>
}
else
if
(
minValue
!==
null
)
{
return
<
Typography
variant
=
'
caption
'
>
Un
nombre
supérieur
ou
égale
à
{
minValue
}
est
attendu
.
<
/Typography
>
}
else
if
(
maxValue
!==
null
)
{
return
<
Typography
variant
=
'
caption
'
>
Un
nombre
inférieur
ou
égale
à
{
maxValue
}
est
attendu
.
<
/Typography
>
}
else
{
return
<
div
><
/div
>
}
}
render
()
{
const
{
classes
}
=
this
.
props
;
return
(
<
FieldWrapper
required
=
{
this
.
props
.
required
}
hasError
=
{
this
.
state
.
error
.
status
}
errors
=
{
this
.
state
.
error
.
messages
}
label
=
{
this
.
props
.
label
}
>
{
this
.
renderInfo
()}
<
TextField
placeholder
=
{
"
Le champ est vide
"
}
fullWidth
=
{
true
}
multiline
=
{
false
}
value
=
{
this
.
state
.
value
}
onChange
=
{(
e
)
=>
this
.
handleChangeValue
(
e
.
target
.
value
)}
/
>
<
/FieldWrapper
>
)
}
}
NumberField
.
defaultProps
=
{
value
:
''
,
maxValue
:
null
,
minValue
:
null
,
}
NumberField
.
propTypes
=
{
value
:
PropTypes
.
string
,
maxValue
:
PropTypes
.
number
,
minValue
:
PropTypes
.
number
,
};
export
default
compose
(
withStyles
(
styles
,
{
withTheme
:
true
}),
)(
NumberField
);
\ No newline at end of file
frontend/src/components/university/shared/fields/TextField.js
View file @
6dfa5edc
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
withStyles
from
'
@material-ui/core/styles/withStyles
'
;
import
Grid
from
'
@material-ui/core/Grid
'
;
import
compose
from
'
recompose/compose
'
;
import
FieldWrapper
from
'
./FieldWrapper
'
;
import
{
TextField
as
MuiTextField
}
from
'
@material-ui/core
'
;
import
MuiTextField
from
'
@material-ui/core
/TextField
'
;
import
Typography
from
'
@material-ui/core/Typography
'
;
import
Markdown
from
'
../../../shared/Markdown
'
;
import
LinkText
from
'
../../../other/TextLink
'
;
import
Field
from
'
./Field
'
;
import
isUrl
from
'
../../../../utils/isUrl
'
;
import
stringHasExtension
from
'
../../../../utils/stringHasExtension
'
;
...
...
@@ -20,13 +16,14 @@ const styles = theme => ({
})
class
TextField
extends
Field
{
defaultNullValue
=
''
;
hasError
(
value
)
{
let
messages
=
Array
();
if
(
this
.
props
.
required
&&
value
==
''
)
{
messages
.
push
(
"
Ce champ est requis mais il est vide.
"
);
}
if
(
this
.
props
.
maxLength
&&
value
.
length
>
this
.
props
.
maxLength
)
{
if
(
this
.
props
.
maxLength
&&
value
!==
null
&&
value
.
length
>
this
.
props
.
maxLength
)
{
messages
.
push
(
"
L'URL est trop long.
"
);
}
if
(
this
.
props
.
isUrl
&&
value
!=
''
&&
!
isUrl
(
value
))
{
...
...
Write
Preview
Supports
Markdown
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