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
d569450d
Commit
d569450d
authored
Sep 01, 2018
by
Florent Chehab
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
API generation for frontend and more standardized js processes
parent
34db017b
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
107 additions
and
120 deletions
+107
-120
Makefile
Makefile
+3
-0
frontend/generate/generate_frontend_files.py
frontend/generate/generate_frontend_files.py
+15
-15
frontend/generate/templates/actions.tpl
frontend/generate/templates/actions.tpl
+10
-10
frontend/generate/templates/reducers.tpl
frontend/generate/templates/reducers.tpl
+6
-6
frontend/src/components/App.js
frontend/src/components/App.js
+9
-31
frontend/src/components/MyComponent.js
frontend/src/components/MyComponent.js
+45
-1
frontend/src/components/map/UnivMakers.js
frontend/src/components/map/UnivMakers.js
+4
-13
frontend/src/components/map/UnivMap.js
frontend/src/components/map/UnivMap.js
+7
-36
frontend/src/reducers/index.js
frontend/src/reducers/index.js
+8
-8
No files found.
Makefile
View file @
d569450d
...
...
@@ -7,6 +7,9 @@ install_backend:
generate_backend
:
python ./backend/generate/generate_all.py
generate_frontend
:
python ./frontend/generate/generate_frontend_files.py
test_backend
:
generate_backend
pytest
...
...
frontend/generate/generate_frontend_files.py
View file @
d569450d
#####
# This python file is used to generate js files for redux
import
os
from
os.path
import
join
from
django
import
template
import
re
import
yaml
############
# Need to do this first so that Django template engine is working
...
...
@@ -35,21 +37,19 @@ templates = [
'combinedReducers'
]
API_BASE
=
"http://127.0.0.1:8000/api/"
contexts
=
[
{
'name'
:
'universities'
,
'api_url'
:
API_BASE
+
"university/"
,
},
{
'name'
:
'countries'
,
'api_url'
:
API_BASE
+
"country/"
},
{
'name'
:
'mainCampus'
,
'api_url'
:
API_BASE
+
"main_campus/"
,
'read_only'
:
True
}
]
API_BASE
=
"/api/"
with
open
(
join
(
current_dir
,
'../../backend/generate/api_config.yml'
),
'r'
)
as
f
:
data
=
f
.
read
()
api_config
=
yaml
.
load
(
data
)
contexts
=
[]
for
api
in
api_config
:
name
=
api
[
'viewset'
].
split
(
'ViewSet'
)[
0
]
name
=
name
[
0
].
lower
()
+
name
[
1
:]
contexts
.
append
({
"name"
:
name
,
"api_end_point"
:
API_BASE
+
api
[
"api_end_point"
]
+
'/'
})
def
read_file
(
file
):
...
...
frontend/generate/templates/actions.tpl
View file @
d569450d
...
...
@@ -29,25 +29,25 @@ import {
//////////////////////////////////
// generic function definitions
function _FetchData(pk, api_
url
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError, pk_required=false) {
function _FetchData(pk, api_
end_point
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError, pk_required=false) {
if (pk_required
&&
pk == ""){
throw "pk shouldn't be empty when requesting a specific element";
}
return (dispatch) => {
dispatch(_IsLoading(true));
fetch(api_
url
)
let token = Cookies.get('csrftoken');
fetch(api_
end_point,
{
credentials
:
'same-origin'
,
headers
:
{
'X-CSRFToken'
:
token
}}
)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
dispatch(_IsLoading(false));
return response;
})
.then((response) => response.json())
.then((obj) => {
dispatch(_Invalidated(false));
dispatch(_FetchDataSuccess(obj));
dispatch(_IsLoading(false));
})
.catch(() => dispatch(_HasError(true)));
};
...
...
@@ -55,7 +55,7 @@ function _FetchData(pk, api_url, _IsLoading, _FetchDataSuccess, _Invalidated, _H
function _ElSaveData(data, api_
url
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError) {
function _ElSaveData(data, api_
end_point
, _IsLoading, _FetchDataSuccess, _Invalidated, _HasError) {
return (dispatch) => {
let method = "POST";
let pk = "";
...
...
@@ -66,7 +66,7 @@ function _ElSaveData(data, api_url, _IsLoading, _FetchDataSuccess, _Invalidated,
dispatch(_ElIsSaving(true));
let token = Cookies.get('csrftoken');
fetch(api_
url
+pk, {
fetch(api_
end_point
+pk, {
method: method,
credentials: 'same-origin',
headers: {
...
...
@@ -81,13 +81,13 @@ function _ElSaveData(data, api_url, _IsLoading, _FetchDataSuccess, _Invalidated,
throw Error(response.statusText);
}
dispatch(_ElIsSaving(false));
return response;
})
.then((response) => response.json())
.then((_El) => {
dispatch(_ElInvalidated(false));
dispatch(_ElSaveDataSuccess(_El));
dispatch(_ElIsSaving(false));
})
.catch(() => dispatch(_ElHasError(true)));
};
...
...
@@ -131,7 +131,7 @@ export function {{obj.name}}FetchDataSuccess({{obj.name}}) {
export function {
{
obj
.
name
}
}FetchData() {
return _FetchData(
"",
"{
{
obj
.
api_
url
}
}",
"{
{
obj
.
api_
end_point
}
}",
{
{
obj
.
name
}
}IsLoading,
{
{
obj
.
name
}
}FetchDataSuccess,
{
{
obj
.
name
}
}Invalidated,
...
...
@@ -176,7 +176,7 @@ export function {{obj.name}}ElFetchDataSuccess({{obj.name}}El) {
export function {
{
obj
.
name
}
}ElFetchData(pk) {
return _FetchData(
pk,
"{
{
obj
.
api_
url
}
}",
"{
{
obj
.
api_
end_point
}
}",
{
{
obj
.
name
}
}ElIsLoading,
{
{
obj
.
name
}
}ElFetchDataSuccess,
{
{
obj
.
name
}
}ElInvalidated,
...
...
@@ -207,7 +207,7 @@ export function {{obj.name}}ElSaveDataSuccess({{obj.name}}El) {
}
export function {
{
obj
.
name
}
}ElSaveData(data) {
return _ElSaveData(data, "{
{
obj
.
api_
url
}
}", {
{
obj
.
name
}
}ElIsLoading, {
{
obj
.
name
}
}ElFetchDataSuccess, {
{
obj
.
name
}
}ElInvalidated, {
{
obj
.
name
}
}ElHasError)
return _ElSaveData(data, "{
{
obj
.
api_
end_point
}
}", {
{
obj
.
name
}
}ElIsLoading, {
{
obj
.
name
}
}ElFetchDataSuccess, {
{
obj
.
name
}
}ElInvalidated, {
{
obj
.
name
}
}ElHasError)
}
{% endif %}
...
...
frontend/generate/templates/reducers.tpl
View file @
d569450d
...
...
@@ -65,11 +65,11 @@ export function {{obj.name}}ElIsLoading(state = false, action) {
}
}
export function {
{
obj
.
name
}
}Fetched(state = {
{
{
obj
.
name
}
}: [], {
{
obj
.
name
}
}F
etchedAt: null }, action) {
export function {
{
obj
.
name
}
}Fetched(state = {
data: Object(), f
etchedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS:
return {
{
{
obj
.
name
}
}
: action.{
{
obj
.
name
}
},
data
: action.{
{
obj
.
name
}
},
fetchedAt: action.{
{
obj
.
name
}
}FetchedAt
}
...
...
@@ -100,11 +100,11 @@ export function {{obj.name}}ElInvalidated(state = false, action) {
}
}
export function {
{
obj
.
name
}
}ElFetched(state = {
{
{
obj
.
name
}
}El: [], {
{
obj
.
name
}
}ElF
etchedAt: null }, action) {
export function {
{
obj
.
name
}
}ElFetched(state = {
data: Object(), f
etchedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS:
return {
{
{
obj
.
name
}
}El
: action.{
{
obj
.
name
}
}El,
data
: action.{
{
obj
.
name
}
}El,
fetchedAt: action.{
{
obj
.
name
}
}ElFetchedAt
}
...
...
@@ -128,11 +128,11 @@ export function {{obj.name}}ElIsSaving(state = false, action) {
}
}
export function {
{
obj
.
name
}
}ElSaved(state = {
{
{
obj
.
name
}
}El: [], {
{
obj
.
name
}
}ElS
avedAt: null }, action) {
export function {
{
obj
.
name
}
}ElSaved(state = {
data: Object(), s
avedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_SAVING_DATA_SUCCESS:
return {
{
{
obj
.
name
}
}El
: action.{
{
obj
.
name
}
}El,
data
: action.{
{
obj
.
name
}
}El,
fetchedAt: action.{
{
obj
.
name
}
}ElSavedAt
}
...
...
frontend/src/components/App.js
View file @
d569450d
...
...
@@ -17,7 +17,7 @@ import SchoolIcon from '@material-ui/icons/School';
import
{
mainListItems
,
secondaryListItems
}
from
'
./template/listItems
'
;
import
{
connect
}
from
"
react-redux
"
;
import
Loading
from
'
./other/Loading
'
;
import
MyComponent
from
'
./MyComponent
'
// import route Components here
...
...
@@ -27,7 +27,7 @@ import {
}
from
'
react-router-dom
'
;
import
{
countr
ies
FetchData
,
countr
y
FetchData
,
}
from
'
../generated/actions
'
;
...
...
@@ -97,10 +97,10 @@ const styles = theme => ({
myPaper
:
{
padding
:
16
},
null
:{}
null
:
{}
});
class
App
extends
React
.
Component
{
class
App
extends
My
Component
{
state
=
{
open
:
true
,
};
...
...
@@ -113,31 +113,7 @@ class App extends React.Component {
this
.
setState
({
open
:
false
});
};
componentDidMount
()
{
if
(
this
.
props
.
countries
.
fetched
.
countries
.
length
==
0
||
this
.
props
.
invalidated
)
{
this
.
props
.
fetchData
();
}
}
componentDidUpdate
()
{
// TODO ajouter expire date
if
(
this
.
props
.
countries
.
invalidated
)
{
this
.
props
.
countries
.
fetchData
();
}
}
componentWillUnmount
()
{
}
render
()
{
if
(
this
.
props
.
countries
.
hasError
)
{
return
<
p
>
Sorry
!
There
was
an
error
loading
the
items
<
/p>
;
}
if
(
this
.
props
.
countries
.
isLoading
||
this
.
props
.
countries
.
invalidated
)
{
return
<
Loading
/>
;
}
myRender
()
{
const
{
classes
}
=
this
.
props
;
...
...
@@ -204,7 +180,9 @@ const mapStateToProps = (state) => {
const
mapDispatchToProps
=
(
dispatch
)
=>
{
return
{
fetchData
:
()
=>
dispatch
(
countriesFetchData
()),
fetchData
:
{
countries
:
()
=>
dispatch
(
countryFetchData
())
}
};
};
...
...
frontend/src/components/MyComponent.js
View file @
d569450d
import
React
,
{
Component
}
from
'
react
'
;
import
Loading
from
'
./other/Loading
'
;
class
MyComponent
extends
Component
{
checkProps
(
val
)
{
for
(
let
el
in
this
.
props
)
{
let
prop
=
this
.
props
[
el
];
if
(
val
in
prop
&&
prop
[
val
])
{
if
(
prop
&&
val
in
prop
&&
prop
[
val
])
{
return
true
;
}
}
return
false
;
}
checkPropsHasError
()
{
return
this
.
checkProps
(
'
hasError
'
);
}
...
...
@@ -18,6 +20,48 @@ class MyComponent extends Component {
checkPropsIsLoading
()
{
return
this
.
checkProps
(
'
isLoading
'
);
}
checkPropsInvalidated
()
{
return
this
.
checkProps
(
'
invalidated
'
);
}
loadPropsIfNeeded
(){
for
(
let
prop_key
in
this
.
props
)
{
let
prop
=
this
.
props
[
prop_key
];
if
(
prop
&&
'
fetched
'
in
prop
){
if
(
(
!
prop
.
fetched
.
fetchedAt
)
||
prop
.
invalidated
){
if
(
!
prop
.
isLoading
){
this
.
props
.
fetchData
[
prop_key
]();
}
}
}
}
}
componentDidMount
()
{
this
.
loadPropsIfNeeded
();
this
.
myComponentDidMount
();
}
myComponentDidMount
(){};
componentDidUpdate
()
{
// TODO ajouter expire date
this
.
loadPropsIfNeeded
();
this
.
myComponentDidMount
();
}
myComponentDidMount
(){};
render
()
{
if
(
this
.
checkPropsHasError
())
{
return
<
p
>
Sorry
!
There
was
an
error
loading
the
items
<
/p>
;
}
if
(
this
.
checkPropsIsLoading
()
||
this
.
checkPropsInvalidated
())
{
return
<
Loading
/>
;
}
return
this
.
myRender
();
}
}
...
...
frontend/src/components/map/UnivMakers.js
View file @
d569450d
...
...
@@ -17,8 +17,8 @@ class UnivMarkers extends Component {
render
()
{
let
universities
=
this
.
props
.
universities
;
let
mainCampus
=
this
.
props
.
mainCampus
;
let
universities
=
this
.
props
.
universities
.
fetched
.
data
;
let
mainCampus
=
this
.
props
.
mainCampus
.
fetched
.
data
;
let
selected_main_campus
=
[];
for
(
let
main_campus_pk
in
mainCampus
)
{
...
...
@@ -50,17 +50,8 @@ class UnivMarkers extends Component {
const
mapStateToProps
=
(
state
)
=>
{
return
{
universities
:
state
.
universities
.
fetched
.
universities
,
universitiesFetchedAt
:
state
.
universities
.
fetched
.
fetchedAt
,
universitiesHasError
:
state
.
universities
.
hasError
,
universitiesIsLoading
:
state
.
universities
.
isLoading
,
universitiesInvalidated
:
state
.
universities
.
invalidated
,
mainCampus
:
state
.
mainCampus
.
fetched
.
mainCampus
,
mainCampusFetchedAt
:
state
.
mainCampus
.
fetched
.
fetchedAt
,
mainCampusHasError
:
state
.
mainCampus
.
hasError
,
mainCampusIsLoading
:
state
.
mainCampus
.
isLoading
,
mainCampusInvalidated
:
state
.
mainCampus
.
invalidated
,
universities
:
state
.
universities
,
mainCampus
:
state
.
mainCampus
};
};
...
...
frontend/src/components/map/UnivMap.js
View file @
d569450d
...
...
@@ -5,7 +5,7 @@ import Loading from '../other/Loading';
import
{
Map
,
TileLayer
,
Marker
,
Popup
,
LayersControl
,
FeatureGroup
,
Circle
,
LayerGroup
}
from
'
react-leaflet
'
;
// import MarkerClusterGroup from 'react-leaflet-markercluster';
import
{
universit
ies
FetchData
,
universit
y
FetchData
,
mainCampusFetchData
,
}
from
'
../../generated/actions
'
;
import
UnivMarkers
from
'
./UnivMakers
'
;
...
...
@@ -20,30 +20,6 @@ class UnivMap extends MyComponent {
};
}
componentDidMount
()
{
let
univ_data
=
this
.
props
.
universities
.
fetched
.
universities
;
if
(
univ_data
.
length
==
0
||
this
.
props
.
universities
.
invalidated
)
{
this
.
props
.
fetchUniversities
();
}
let
main_campus_data
=
this
.
props
.
mainCampus
.
fetched
.
mainCampus
;
if
(
main_campus_data
.
length
==
0
||
this
.
props
.
mainCampus
.
invalidated
)
{
this
.
props
.
fetchMainCampus
();
}
}
componentDidUpdate
()
{
// TODO ajouter expire date
if
(
this
.
props
.
universities
.
invalidated
)
{
this
.
props
.
fetchUniversities
();
}
if
(
this
.
props
.
mainCampus
.
invalidated
)
{
this
.
props
.
fetchMainCampus
();
}
}
componentWillUnmount
()
{
let
l
=
this
.
state
.
leaflet_instance
;
...
...
@@ -76,14 +52,7 @@ class UnivMap extends MyComponent {
}))
}
render
()
{
if
(
this
.
checkPropsHasError
())
{
return
<
p
>
Sorry
!
There
was
an
error
loading
the
items
<
/p>
;
}
if
(
this
.
checkPropsIsLoading
())
{
return
<
Loading
/>
;
}
myRender
()
{
let
stamen_name
=
"
Stamen Watercolor
"
;
let
osm_fr_name
=
"
OpenStreetMap France
"
;
let
esri_name
=
"
Esri WorldImagery
"
;
...
...
@@ -145,8 +114,10 @@ const mapStateToProps = (state) => {
const
mapDispatchToProps
=
(
dispatch
)
=>
{
return
{
fetchUniversities
:
()
=>
dispatch
(
universitiesFetchData
()),
fetchMainCampus
:
()
=>
dispatch
(
mainCampusFetchData
()),
fetchData
:
{
universities
:
()
=>
dispatch
(
universityFetchData
()),
mainCampus
:
()
=>
dispatch
(
mainCampusFetchData
())
},
saveMainMap
:
(
pos
)
=>
dispatch
(
saveMainMapPosition
(
pos
)),
};
};
...
...
frontend/src/reducers/index.js
View file @
d569450d
import
{
combineReducers
}
from
'
redux
'
;
import
{
universit
ies
Reducers
,
universit
y
Reducers
,
mainCampusReducers
,
countr
ies
Reducers
,
countr
ies
ElReducers
,
universit
ies
ElReducers
countr
y
Reducers
,
countr
y
ElReducers
,
universit
y
ElReducers
}
from
'
../generated/combinedReducers
'
;
import
{
...
...
@@ -17,10 +17,10 @@ const appReducers = combineReducers({
})
const
rootReducer
=
combineReducers
({
countries
:
countr
ies
Reducers
,
countr
iesEl
:
countries
ElReducers
,
universities
:
universit
ies
Reducers
,
universit
iesEl
:
universities
ElReducers
,
countries
:
countr
y
Reducers
,
countr
yEl
:
country
ElReducers
,
universities
:
universit
y
Reducers
,
universit
yEl
:
university
ElReducers
,
mainCampus
:
mainCampusReducers
,
app
:
appReducers
})
...
...
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