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
ae856352
Commit
ae856352
authored
Sep 15, 2018
by
Florent Chehab
Browse files
Tweaks and university DRI display and edit ok
parent
35b8ea0f
Changes
12
Hide whitespace changes
Inline
Side-by-side
frontend/generate/templates/actions.tpl
View file @
ae856352
...
...
@@ -36,7 +36,7 @@ function _FetchData(pk, api_end_point, _IsLoading, _FetchDataSuccess, _Invalidat
throw "pk shouldn't be empty when requesting a specific element";
}
if (pk != ""){
api_end_point += pk;
api_end_point += pk
+ '/'
;
}
return (dispatch) => {
dispatch(_IsLoading(true));
...
...
@@ -71,11 +71,16 @@ function _ElSaveData(data, api_end_point, _ElIsSaving, _ElFetchDataSuccess, _ElS
method = "PUT";
pk = data.id + '/';
}
let __apiAttr = '';
if ('__apiAttr' in data
&&
data.__apiAttr != '' ){
__apiAttr = data.__apiAttr + '/';
}
let errorStatusText = '';
dispatch(_ElIsSaving(true));
let token = Cookies.get('csrftoken');
let f = fetch(api_end_point+pk, {
let f = fetch(api_end_point+
__apiAttr+
pk, {
method: method,
credentials: 'same-origin',
headers: {
...
...
frontend/src/components/MyComponent.js
View file @
ae856352
...
...
@@ -3,7 +3,11 @@ import Loading from './other/Loading';
class
MyComponent
extends
Component
{
customErrorHandlers
=
{}
idToUse
=
null
;
// __apiAttr should be an object
// mapping the prop that needs to fetched with extra api attributes
// mapping should be : props_key => other_props_that contains the attribute to use
__apiAttr
=
null
;
ignoreInvalidation
=
false
;
getFetchedData
(
prop
)
{
return
this
.
props
[
prop
].
fetched
.
data
;
...
...
@@ -92,12 +96,12 @@ class MyComponent extends Component {
for
(
let
prop_key
in
props
)
{
let
prop
=
props
[
prop_key
];
if
(
prop
===
Object
(
prop
)
&&
'
fetched
'
in
prop
)
{
if
((
!
prop
.
fetched
.
fetchedAt
)
||
prop
.
invalidated
)
{
if
((
!
prop
.
fetched
.
fetchedAt
)
||
(
!
this
.
ignoreInvalidation
&&
prop
.
invalidated
)
)
{
propsLoaded
=
false
;
if
(
!
dontFetch
)
{
if
(
!
prop
.
isLoading
)
{
if
(
this
.
idToUse
)
{
props
.
fetchData
[
prop_key
](
this
.
props
[
this
.
idToUse
]);
if
(
this
.
__apiAttr
&&
this
.
__apiAttr
[
prop_key
]
)
{
props
.
fetchData
[
prop_key
](
this
.
props
[
this
.
__apiAttr
[
prop_key
]
]);
}
else
{
props
.
fetchData
[
prop_key
]();
}
...
...
frontend/src/components/university/editors/UniversityDriEditor.js
0 → 100644
View file @
ae856352
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
withStyles
from
'
@material-ui/core/styles/withStyles
'
;
import
compose
from
'
recompose/compose
'
;
import
{
connect
}
from
"
react-redux
"
;
import
Editor
from
'
../shared/Editor
'
;
import
editorStyle
from
'
../shared/editorStyle
'
;
import
MultiSelectField
from
'
../shared/fields/MultiSelectField
'
;
import
__map
from
'
lodash/map
'
;
import
getMapStateToPropsForEditor
from
'
../shared/editorFunctions/getMapStateToPropsForEditor
'
;
import
getMapDispatchToPropsForEditor
from
'
../shared/editorFunctions/getMapDispatchToPropsForEditor
'
;
import
{
universityDriElSaveData
,
universityDriElSavingHasError
}
from
'
../../../generated/actions
'
;
const
styles
=
theme
=>
({
...
editorStyle
(
theme
)
});
class
UniversityDriEditor
extends
Editor
{
renderEditor
()
{
const
{
modelData
}
=
this
.
props
;
const
{
outsideData
}
=
this
.
props
;
const
universities
=
__map
(
outsideData
.
universities
,
(
univ
)
=>
{
return
{
label
:
univ
.
name
,
value
:
univ
.
id
,
disabled
:
false
}
}
)
return
(
<
div
>
{
this
.
renderTitleField
()}
{
this
.
renderImportanceLevelField
()}
<
MultiSelectField
label
=
{
"
Universités concernées
"
}
required
=
{
true
}
value
=
{
modelData
.
universities
}
options
=
{
universities
}
formManager
=
{
this
}
fieldMapping
=
{
'
universities
'
}
/
>
{
this
.
renderCommentField
()}
{
this
.
renderUsefulLinksField
()}
<
/div
>
)
}
}
UniversityDriEditor
.
propTypes
=
{
modelData
:
PropTypes
.
object
.
isRequired
,
};
export
default
compose
(
withStyles
(
styles
,
{
withTheme
:
true
}),
connect
(
getMapStateToPropsForEditor
(
'
universityDriEl
'
),
getMapDispatchToPropsForEditor
(
universityDriElSaveData
,
universityDriElSavingHasError
)
)
)(
UniversityDriEditor
);
\ No newline at end of file
frontend/src/components/university/editors/UniversitySemestersDatesEditor.js
View file @
ae856352
...
...
@@ -79,16 +79,8 @@ class UniversitySemestersDatesEditor extends Editor {
formManager
=
{
this
}
fieldMapping
=
{
'
autumn_end
'
}
/
>
<
MarkdownField
label
=
{
"
Éventuel commentaire associé à ces informations
"
}
maxLength
=
{
100
}
value
=
{
modelData
.
comment
}
formManager
=
{
this
}
fieldMapping
=
{
'
comment
'
}
/
>
<
UsefulLinksField
label
=
{
"
Lien(s) utile(s) (ex : vers ces informations)
"
}
value
=
{
modelData
.
useful_links
}
formManager
=
{
this
}
fieldMapping
=
{
'
useful_links
'
}
/
>
{
this
.
renderCommentField
()}
{
this
.
renderUsefulLinksField
()}
<
/div
>
)
}
...
...
frontend/src/components/university/modules/UniversityDri.js
View file @
ae856352
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
withStyles
from
'
@material-ui/core/styles/withStyles
'
;
import
Paper
from
'
@material-ui/core/Paper
'
;
import
GenericModule
from
'
../shared/GenericModule
'
;
import
compose
from
'
recompose/compose
'
;
import
{
connect
}
from
"
react-redux
"
;
import
__pick
from
'
lodash/pick
'
;
import
Markdown
from
'
../../shared/Markdown
'
;
import
MyComponent
from
'
../../MyComponent
'
;
import
GenericModule
from
'
../shared/GenericModule
'
;
import
GenericGroupModule
from
'
../shared/GenericGroupModule
'
;
import
UniversityDriEditor
from
'
../editors/UniversityDriEditor
'
;
const
styles
=
theme
=>
({
import
{
universitiesFetchData
,
universityDriFetchData
,
universityDriInvalidated
,
}
from
'
../../../generated/actions
'
;
const
styles
=
theme
=>
({
});
function
renderCore
(
rawModelData
,
classes
,
outsideData
)
{
const
univDri
=
rawModelData
;
const
{
comment
}
=
univDri
;
return
(
<
Markdown
source
=
{
comment
}
/
>
)
}
function
parseRawModelData
(
rawModelData
)
{
// reverse serialization
const
univInfos
=
rawModelData
;
const
modelData
=
__pick
(
univInfos
,
[
"
id
"
,
"
title
"
,
"
importance_level
"
,
"
universities
"
,
"
comment
"
,
"
useful_links
"
,
// "obj_moderation_level",
]);
return
modelData
;
}
class
UniversityDri
extends
MyComponent
{
ignoreInvalidation
=
true
;
componentWillUnmount
()
{
this
.
props
.
invalidateData
();
}
myComponentDidUpdate
()
{
if
(
this
.
props
.
universityDri
.
invalidated
&&
!
this
.
props
.
universityDri
.
isLoading
)
{
this
.
props
.
fetchData
.
universityDri
(
this
.
props
.
univId
);
}
}
myRender
()
{
const
univDriItems
=
this
.
getFetchedData
(
'
universityDri
'
);
const
universities
=
this
.
getFetchedData
(
'
universities
'
)
const
{
classes
}
=
this
.
props
;
const
outsideData
=
{
universities
}
class
UniversityDri
extends
React
.
Component
{
render
()
{
const
{
classes
,
theme
}
=
this
.
props
;
return
(
<
GenericGroupModule
groupTitle
=
{
"
Informations émanant de la DRI
"
}
>
<
GenericModule
title
=
{
"
DRI
"
}
importanceLevel
=
{
'
IMPORTANT
'
}
/
>
{
univDriItems
.
map
((
rawModelData
)
=>
(
<
GenericModule
visible
=
{
this
.
props
.
visible
}
buildTitle
=
{(
modelData
)
=>
modelData
.
title
}
rawModelData
=
{
rawModelData
}
parseRawModelData
=
{
parseRawModelData
}
editor
=
{
UniversityDriEditor
}
renderCore
=
{
renderCore
}
coreClasses
=
{
classes
}
outsideData
=
{
outsideData
}
moduleInGroupInfos
=
{{
isInGroup
:
true
,
invalidateGroup
:
()
=>
this
.
props
.
invalidateData
()
}}
__apiAttr
=
{
this
.
props
.
univId
}
/
>
))
}
<
/GenericGroupModule
>
)
}
__apiAttr
=
{
universityDri
:
"
univId
"
};
}
export
default
withStyles
(
styles
,
{
withTheme
:
true
})(
UniversityDri
);
UniversityDri
.
propTypes
=
{
classes
:
PropTypes
.
object
.
isRequired
,
theme
:
PropTypes
.
object
.
isRequired
,
univId
:
PropTypes
.
string
.
isRequired
};
const
mapStateToProps
=
(
state
)
=>
{
return
{
universityDri
:
state
.
universityDri
,
universities
:
state
.
universities
,
};
};
const
mapDispatchToProps
=
(
dispatch
)
=>
{
return
{
fetchData
:
{
universityDri
:
(
univId
)
=>
dispatch
(
universityDriFetchData
(
univId
)),
universities
:
()
=>
dispatch
(
universitiesFetchData
()),
},
invalidateData
:
()
=>
dispatch
(
universityDriInvalidated
(
true
))
};
};
export
default
compose
(
withStyles
(
styles
,
{
withTheme
:
true
}),
connect
(
mapStateToProps
,
mapDispatchToProps
)
)(
UniversityDri
);
\ No newline at end of file
frontend/src/components/university/modules/UniversityGeneral.js
View file @
ae856352
...
...
@@ -88,8 +88,6 @@ function parseRawModelData(rawModelData) {
class
UniversityGeneral
extends
MyComponent
{
idToUse
=
"
univId
"
;
componentWillUnmount
()
{
this
.
props
.
invalidateData
();
}
...
...
@@ -120,6 +118,8 @@ class UniversityGeneral extends MyComponent {
/
>
)
}
__apiAttr
=
{
universitiesEl
:
"
univId
"
};
}
UniversityGeneral
.
propTypes
=
{
...
...
frontend/src/components/university/modules/UniversitySemestersDates.js
View file @
ae856352
...
...
@@ -127,7 +127,6 @@ function parseRawModelData(rawModelData) {
class
UniversitySemestersDates
extends
MyComponent
{
idToUse
=
"
univId
"
;
componentWillUnmount
()
{
this
.
props
.
invalidateData
();
...
...
@@ -147,6 +146,8 @@ class UniversitySemestersDates extends MyComponent {
/
>
)
}
__apiAttr
=
{
universitiesSemestersDatesEl
:
"
univId
"
};
}
...
...
frontend/src/components/university/shared/Editor.js
View file @
ae856352
...
...
@@ -15,6 +15,9 @@ import Alert from './Alert';
import
Notification
from
'
./Notification
'
;
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
'
;
function
Transition
(
props
)
{
return
<
Slide
direction
=
"
up
"
{...
props
}
/>
;
...
...
@@ -96,7 +99,8 @@ class Editor extends MyComponent {
duration
:
null
}
})
this
.
props
.
saveData
(
data
);
this
.
props
.
saveData
(
Object
.
assign
({
__apiAttr
:
this
.
props
.
__apiAttr
},
data
));
}
handleSaveEditor
()
{
...
...
@@ -183,7 +187,7 @@ class Editor extends MyComponent {
preventClickAway
:
false
}
})
this
.
props
.
handleCloseEditor
();
this
.
props
.
handleCloseEditor
(
true
);
}
};
...
...
@@ -232,7 +236,7 @@ class Editor extends MyComponent {
}
renderObjModerationLevelField
()
{
const
{
modelData
}
=
this
.
props
;
const
{
obj_moderation_level
}
=
this
.
props
.
modelData
;
const
possibleObjModeration
=
getObjModerationLevel
(
this
.
getFetchedData
(
'
userData
'
).
owner_level
,
true
);
if
(
possibleObjModeration
.
length
>
1
)
{
...
...
@@ -241,7 +245,7 @@ class Editor extends MyComponent {
<
Typography
variant
=
'
caption
'
>
Niveau
de
modération
souhaité
(
en
plus
TODO
<
/Typography
>
<
SelectField
label
=
{
"
Niveau de modération pour ce module
"
}
required
=
{
true
}
value
=
{
modelData
.
obj_moderation_level
}
value
=
{
obj_moderation_level
}
fieldMapping
=
{
"
obj_moderation_level
"
}
options
=
{
possibleObjModeration
}
formManager
=
{
this
}
...
...
@@ -255,6 +259,66 @@ class Editor extends MyComponent {
}
}
renderImportanceLevelField
()
{
const
{
importance_level
}
=
this
.
props
.
modelData
;
//TODO change below use JSON
const
options
=
[
{
'
label
'
:
'
Normal
'
,
'
value
'
:
'
-
'
},
{
'
label
'
:
'
Important
'
,
'
value
'
:
'
+
'
},
{
'
label
'
:
'
Très important
'
,
'
value
'
:
'
++
'
},
]
return
(
<
div
>
<
Typography
variant
=
'
caption
'
>
Qualification
de
l
'
importance de l
'
information
présentée
<
/Typography
>
<
SelectField
label
=
{
"
Niveau d'importance
"
}
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
'
}
/
>
)
}
renderCommentField
()
{
const
{
comment
}
=
this
.
props
.
modelData
;
return
(
<
MarkdownField
label
=
{
"
Commentaire associé à ces informations
"
}
maxLength
=
{
100
}
value
=
{
comment
}
formManager
=
{
this
}
fieldMapping
=
{
'
comment
'
}
/
>
)
}
renderTitleField
()
{
const
{
title
}
=
this
.
props
.
modelData
;
return
(
<
TextField
label
=
{
"
Titre
"
}
required
=
{
true
}
value
=
{
title
}
maxLength
=
{
150
}
formManager
=
{
this
}
fieldMapping
=
{
'
title
'
}
/
>
)
}
myRender
()
{
const
{
classes
}
=
this
.
props
;
return
(
...
...
@@ -300,12 +364,17 @@ Editor.propTypes = {
savingHasError
:
PropTypes
.
object
.
isRequired
,
saveData
:
PropTypes
.
func
.
isRequired
,
lastUpdateTime
:
PropTypes
.
string
,
forceSave
:
PropTypes
.
bool
.
isRequired
forceSave
:
PropTypes
.
bool
.
isRequired
,
outsideData
:
PropTypes
.
object
,
saveShouldInvalidate
:
PropTypes
.
bool
.
isRequired
,
__apiAttr
:
PropTypes
.
oneOf
([
PropTypes
.
number
,
PropTypes
.
string
]),
};
Editor
.
defaultProps
=
{
open
:
false
,
forceSave
:
false
,
saveShouldInvalidate
:
false
,
__apiAttr
:
''
,
handleCloseEditor
:
()
=>
console
.
log
(
"
Dev forgot something...
"
)
};
...
...
frontend/src/components/university/shared/GenericModule.js
View file @
ae856352
...
...
@@ -112,8 +112,11 @@ class GenericModule extends MyComponent {
};
handleCloseEditor
=
()
=>
{
handleCloseEditor
=
(
somethingWasSaved
=
false
)
=>
{
this
.
setState
({
editorOpen
:
false
,
dataToSave
:
null
});
if
(
somethingWasSaved
&&
this
.
props
.
moduleInGroupInfos
.
isInGroup
)
{
this
.
props
.
moduleInGroupInfos
.
invalidateGroup
();
}
};
handleCloseAlert
=
()
=>
{
...
...
@@ -209,9 +212,11 @@ class GenericModule extends MyComponent {
open
=
{
this
.
state
.
editorOpen
}
handleCloseEditor
=
{
this
.
handleCloseEditor
}
modelData
=
{
this
.
props
.
parseRawModelData
(
this
.
state
.
rawModelDataForEditor
)}
outsideData
=
{
this
.
props
.
outsideData
}
userData
=
{
this
.
props
.
userDataEl
}
forceSave
=
{
this
.
state
.
forceSave
}
dataToSave
=
{
this
.
state
.
dataToSave
}
__apiAttr
=
{
this
.
props
.
__apiAttr
}
/
>
<
History
factory
=
{
this
}
...
...
@@ -239,6 +244,8 @@ class GenericModule extends MyComponent {
GenericModule
.
defaultProps
=
{
buildTitle
:
()
=>
null
,
moduleInGroupInfos
:
{
isInGroup
:
false
,
invalidateGroup
:
()
=>
null
},
__apiAttr
:
''
,
};
GenericModule
.
propTypes
=
{
...
...
@@ -250,6 +257,8 @@ GenericModule.propTypes = {
parseRawModelData
:
PropTypes
.
func
.
isRequired
,
coreClasses
:
PropTypes
.
object
.
isRequired
,
outsideData
:
PropTypes
.
object
,
__apiAttr
:
PropTypes
.
oneOfType
([
PropTypes
.
number
,
PropTypes
.
string
]),
moduleInGroupInfos
:
PropTypes
.
shape
({
isInGroup
:
PropTypes
.
bool
.
isRequired
,
invalidateGroup
:
PropTypes
.
func
}).
isRequired
,
};
...
...
frontend/src/components/university/tabs/GeneralInfoTab.js
View file @
ae856352
...
...
@@ -42,7 +42,7 @@ class GeneralInfoTab extends MyComponent {
<
UniversityGeneral
visible
=
{
this
.
props
.
visible
}
univId
=
{
this
.
props
.
univId
}
/
>
<
/Grid
>
<
Grid
item
xs
>
{
/*
<UniversityDri visible={this.props.visible} univId={this.props.univId} />
*/
}
<
UniversityDri
visible
=
{
this
.
props
.
visible
}
univId
=
{
this
.
props
.
univId
}
/
>
<
/Grid
>
<
/Grid
>
<
/div
>
...
...
@@ -69,7 +69,7 @@ class GeneralInfoTab extends MyComponent {
<
UniversityGeneral
visible
=
{
this
.
props
.
visible
}
univId
=
{
this
.
props
.
univId
}
/
>
<
/Grid
>
<
Grid
item
xs
=
{
12
}
>
{
/*
<UniversityDri visible={this.props.visible} univId={this.props.univId} />
*/
}
<
UniversityDri
visible
=
{
this
.
props
.
visible
}
univId
=
{
this
.
props
.
univId
}
/
>
<
/Grid
>
<
Grid
item
xs
=
{
12
}
>
<
UniversitySemestersDates
visible
=
{
this
.
props
.
visible
}
univId
=
{
this
.
props
.
univId
}
/
>
...
...
frontend/src/reducers/index.js
View file @
ae856352
...
...
@@ -10,9 +10,11 @@ import {
citiesReducers
,
userDataElReducers
,
universitiesInfoElReducers
,
universityDriReducers
,
universityDriElReducers
,
universitiesSemestersDatesElReducers
,
serverModerationStatusReducers
,
versionsReducers
versionsReducers
,
}
from
'
../generated/combinedReducers
'
;
import
{
saveMainMapPosition
}
from
'
./map
'
;
...
...
@@ -39,6 +41,8 @@ const rootReducer = combineReducers({
universitiesEl
:
universitiesElReducers
,
universitiesInfoEl
:
universitiesInfoElReducers
,
universitiesSemestersDatesEl
:
universitiesSemestersDatesElReducers
,
universityDri
:
universityDriReducers
,
universityDriEl
:
universityDriElReducers
,
currencies
:
currenciesReducers
,
mainCampuses
:
mainCampusesReducers
,
userDataEl
:
userDataElReducers
,
...
...
frontend/src/utils/isModerationRequired.js
View file @
ae856352
...
...
@@ -14,7 +14,7 @@ export default function isModerationRequired(
objModerationLevel
,
userLevel
)
{
const
{
modelModerationLevel
}
=
modelConfig
;
const
modelModerationLevel
=
modelConfig
.
moderation_level
;
const
key
=
'
enforce_moderation_user_level
'
;
if
(
key
in
modelConfig
&&
userLevel
<
modelConfig
[
key
])
{
...
...
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