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
Julien Jerphanion
Rex Dri
Commits
53dc786d
Commit
53dc786d
authored
Feb 07, 2019
by
Florent Chehab
Browse files
Fixed frontend genereation.
Removed nasty automatic file generation. #39 #25
parent
fa8052f4
Changes
59
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
53dc786d
...
...
@@ -4,28 +4,19 @@
install_backend
:
pip
install
-r
requirements.txt
--quiet
generate_backend
:
export
PYTHONPATH
=
$$
PWD
;
python ./backend/generate/generate_backend_files.py
generate_frontend_files
:
export
PYTHONPATH
=
$$
PWD
;
python ./frontend/generate/generate_frontend_files.py
generate_frontend
:
generate_frontend_files
npm run dev
build_frontend
:
generate_frontend_files
build_frontend
:
npm run build
test_backend
:
generate_backend
test_backend
:
pytest general/ frontend/ backend/
test_backend_server
:
pytest
-n
4 general/ frontend/ backend/
--cov-report
html
check_backend
:
generate_backend
check_backend
:
./manage.py check
run_backend
:
generate_backend
run_backend
:
./manage.py runserver
...
...
frontend/generate/generate_frontend_files.py
deleted
100644 → 0
View file @
fa8052f4
#####
# This python file is used to generate js files for redux
from
os
import
makedirs
from
os.path
import
join
,
dirname
,
realpath
,
exists
from
django
import
template
import
re
from
general.api
import
get_api_config
############
# Need to do this first so that Django template engine is working
import
django
from
django.conf
import
settings
settings
.
configure
(
TEMPLATES
=
[
{
'BACKEND'
:
'django.template.backends.django.DjangoTemplates'
,
'DIRS'
:
[
'.'
],
# if you want the templates from a file
'APP_DIRS'
:
False
,
# we have no apps
},
])
django
.
setup
()
##########
current_dir
=
dirname
(
realpath
(
__file__
))
templates_dir
=
current_dir
+
'/templates/'
saving_dir
=
realpath
(
current_dir
+
"/../src/generated/"
)
if
not
exists
(
saving_dir
):
makedirs
(
saving_dir
)
templates
=
[
'action-types'
,
'actions'
,
'reducers'
,
'combinedReducers'
]
api_config
=
get_api_config
()
API_BASE
=
"/api/"
contexts
=
[]
for
api
in
api_config
:
if
"requires_testing"
in
api
and
api
[
"requires_testing"
]:
continue
name
=
api
[
'viewset'
].
split
(
'ViewSet'
)[
0
]
name
=
name
[
0
].
lower
()
+
name
[
1
:]
contexts
.
append
({
"name"
:
api
[
"api_end_point"
],
"api_end_point"
:
API_BASE
+
api
[
"api_end_point"
]
+
'/'
,
})
# API outside rest framework here
contexts
.
append
({
"name"
:
'serverModerationStatus'
,
"api_end_point"
:
API_BASE
+
'serverModerationStatus'
+
'/'
,
})
def
convert
(
name
):
s1
=
re
.
sub
(
'(.)([A-Z][a-z]+)'
,
r
'\1_\2'
,
name
)
return
re
.
sub
(
'([a-z0-9])([A-Z])'
,
r
'\1_\2'
,
s1
).
upper
()
for
c
in
contexts
:
c
[
'NAME'
]
=
convert
(
c
[
'name'
])
for
filename
in
templates
:
template_path
=
join
(
templates_dir
,
filename
+
'.tpl'
)
with
open
(
template_path
,
"r"
)
as
f
:
t
=
f
.
read
()
t
=
template
.
Template
(
t
)
c
=
template
.
Context
({
'data'
:
contexts
})
output
=
t
.
render
(
c
)
output_path
=
join
(
saving_dir
,
filename
+
'.js'
)
with
open
(
output_path
,
'w'
)
as
f
:
f
.
write
(
output
)
frontend/generate/templates/action-types.tpl
deleted
100644 → 0
View file @
fa8052f4
// WARNING
// THIS FILE HAS BEEN AUTOMATICALLY GENERATED
// WITH /frontend/generate/generate_frontend_files.js
// MODIFY THE FILE ABOVE IF YOUR NOT SATISFIED
// THIS WARNING DOESN'T APPLY TO .tpl FILES...
{% for obj in data %}
////////////////
// {
{
obj
.
NAME
}
}
////////////////
export const {
{
obj
.
NAME
}
}_FETCH_HAS_ERROR = '{
{
obj
.
NAME
}
}_FETCH_HAS_ERROR';
export const {
{
obj
.
NAME
}
}_IS_LOADING = '{
{
obj
.
NAME
}
}_IS_LOADING';
export const {
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS = '{
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS';
export const {
{
obj
.
NAME
}
}_INVALIDATED = '{
{
obj
.
NAME
}
}_INVALIDATED';
export const {
{
obj
.
NAME
}
}_EL_FETCH_HAS_ERROR = '{
{
obj
.
NAME
}
}_EL_FETCH_HAS_ERROR';
export const {
{
obj
.
NAME
}
}_EL_INVALIDATED = '{
{
obj
.
NAME
}
}_EL_INVALIDATED';
export const {
{
obj
.
NAME
}
}_EL_IS_LOADING = '{
{
obj
.
NAME
}
}_EL_IS_LOADING';
export const {
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS = '{
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS';
{% if not obj.read_only %}
export const {
{
obj
.
NAME
}
}_EL_IS_SAVING = '{
{
obj
.
NAME
}
}_EL_IS_SAVING';
export const {
{
obj
.
NAME
}
}_EL_SHARE_SAVED_TIME = '{
{
obj
.
NAME
}
}_EL_SHARE_SAVED_TIME';
export const {
{
obj
.
NAME
}
}_EL_SAVING_HAS_ERROR = '{
{
obj
.
NAME
}
}_EL_SAVING_HAS_ERROR';
{% endif %}
{% endfor %}
frontend/generate/templates/actions.tpl
deleted
100644 → 0
View file @
fa8052f4
// WARNING
// THIS FILE HAS BEEN AUTOMATICALLY GENERATED
// WITH /frontend/generate/generate_frontend_files.js
// MODIFY THE FILE ABOVE IF YOUR NOT SATISFIED
// THIS WARNING DOESN'T APPLY TO .tpl FILES...
import SmartActions from '../actions/SmartActions';
import {
{% for obj in data %}
{
{
obj
.
NAME
}
}_FETCH_HAS_ERROR,
{
{
obj
.
NAME
}
}_IS_LOADING,
{
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS,
{
{
obj
.
NAME
}
}_INVALIDATED,
{
{
obj
.
NAME
}
}_EL_INVALIDATED,
{
{
obj
.
NAME
}
}_EL_FETCH_HAS_ERROR,
{
{
obj
.
NAME
}
}_EL_IS_LOADING,
{
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS,
{% if not obj.read_only %}
{
{
obj
.
NAME
}
}_EL_IS_SAVING,
{
{
obj
.
NAME
}
}_EL_SAVING_HAS_ERROR,
{
{
obj
.
NAME
}
}_EL_SHARE_SAVED_TIME,
{% endif %}
{% endfor %}
} from "./action-types";
//////////////////////////////////
// generic function definitions
const smartActions = new SmartActions();
/////////////////////////////////
{% for obj in data %}
export function {
{
obj
.
name
}
}FetchHasError(bool, error=null) {
return {
type: {
{
obj
.
NAME
}
}_FETCH_HAS_ERROR,
hasError: bool,
error
};
}
export function {
{
obj
.
name
}
}IsLoading(bool) {
return {
type: {
{
obj
.
NAME
}
}_IS_LOADING,
isLoading: bool
};
}
export function {
{
obj
.
name
}
}Invalidated(bool) {
return {
type: {
{
obj
.
NAME
}
}_INVALIDATED,
invalidated: bool
};
}
export function {
{
obj
.
name
}
}FetchDataSuccess({
{
obj
.
name
}
}, setInvalidateFalse=true) {
let time = null;
if (setInvalidateFalse){
{
{
obj
.
name
}
}Invalidated(false)
time = Date.now();
}
return {
type: {
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS,
{
{
obj
.
name
}
},
{
{
obj
.
name
}
}FetchedAt: time
};
}
export function {
{
obj
.
name
}
}FetchData(pk="") {
return smartActions._FetchData(
pk,
"{
{
obj
.
api_end_point
}
}",
{
{
obj
.
name
}
}IsLoading,
{
{
obj
.
name
}
}FetchDataSuccess,
{
{
obj
.
name
}
}Invalidated,
{
{
obj
.
name
}
}FetchHasError
)
}
export function {
{
obj
.
name
}
}ElFetchHasError(bool, error) {
return {
type: {
{
obj
.
NAME
}
}_EL_FETCH_HAS_ERROR,
hasError: bool,
error
};
}
export function {
{
obj
.
name
}
}ElInvalidated(bool) {
return {
type: {
{
obj
.
NAME
}
}_EL_INVALIDATED,
invalidated: bool
};
}
export function {
{
obj
.
name
}
}ElIsLoading(bool) {
return {
type: {
{
obj
.
NAME
}
}_EL_IS_LOADING,
isLoading: bool
};
}
export function {
{
obj
.
name
}
}ElFetchDataSuccess({
{
obj
.
name
}
}El, setInvalidateFalse=true) {
let time = null;
if (setInvalidateFalse){
{
{
obj
.
name
}
}ElInvalidated(false);
time = Date.now();
}
return {
type: {
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS,
{
{
obj
.
name
}
}El,
{
{
obj
.
name
}
}ElFetchedAt: time
};
}
export function {
{
obj
.
name
}
}ElFetchData(pk) {
return smartActions._FetchData(
pk,
"{
{
obj
.
api_end_point
}
}",
{
{
obj
.
name
}
}ElIsLoading,
{
{
obj
.
name
}
}ElFetchDataSuccess,
{
{
obj
.
name
}
}ElInvalidated,
{
{
obj
.
name
}
}ElFetchHasError,
true
)
}
{% if not obj.read_only %}
export function {
{
obj
.
name
}
}ElIsSaving(bool) {
return {
type: {
{
obj
.
NAME
}
}_EL_IS_SAVING,
isSaving: bool
};
}
export function {
{
obj
.
name
}
}ElSavingHasError(b, error=null) {
return {
type: {
{
obj
.
NAME
}
}_EL_SAVING_HAS_ERROR,
hasError: b,
error
};
}
export function {
{
obj
.
name
}
}ElShareSavedTime() {
return {
type: {
{
obj
.
NAME
}
}_EL_SHARE_SAVED_TIME,
time: Date.now()
};
}
export function {
{
obj
.
name
}
}ElSaveData(data) {
return smartActions._ElSaveData(data, "{
{
obj
.
api_end_point
}
}", {
{
obj
.
name
}
}ElIsSaving, {
{
obj
.
name
}
}ElFetchDataSuccess, {
{
obj
.
name
}
}ElShareSavedTime, {
{
obj
.
name
}
}ElInvalidated, {
{
obj
.
name
}
}ElSavingHasError)
}
{% endif %}
{% endfor %}
\ No newline at end of file
frontend/generate/templates/combinedReducers.tpl
deleted
100644 → 0
View file @
fa8052f4
// WARNING
// THIS FILE HAS BEEN AUTOMATICALLY GENERATED
// WITH /frontend/generate/generate_frontend_files.js
// MODIFY THE FILE ABOVE IF YOUR NOT SATISFIED
// THIS WARNING DOESN'T APPLY TO .tpl FILES...
import { combineReducers } from 'redux';
import {
{% for obj in data %}
{
{
obj
.
name
}
}Invalidated,
{
{
obj
.
name
}
}FetchHasError,
{
{
obj
.
name
}
}IsLoading,
{
{
obj
.
name
}
}Fetched,
{
{
obj
.
name
}
}ElInvalidated,
{
{
obj
.
name
}
}ElFetchHasError,
{
{
obj
.
name
}
}ElIsLoading,
{
{
obj
.
name
}
}ElFetched,
{% if not obj.read_only %}
{
{
obj
.
name
}
}ElIsSaving,
{
{
obj
.
name
}
}ElShareSavedTime,
{
{
obj
.
name
}
}ElSavingHasError,
{% endif %}
{% endfor %}
} from './reducers';
{% for obj in data %}
export const {
{
obj
.
name
}
}Reducers = combineReducers({
invalidated: {
{
obj
.
name
}
}Invalidated,
fetchHasError: {
{
obj
.
name
}
}FetchHasError,
isLoading: {
{
obj
.
name
}
}IsLoading,
fetched: {
{
obj
.
name
}
}Fetched,
})
export const {
{
obj
.
name
}
}ElReducers = combineReducers({
invalidated: {
{
obj
.
name
}
}ElInvalidated,
fetchHasError: {
{
obj
.
name
}
}ElFetchHasError,
isLoading: {
{
obj
.
name
}
}ElIsLoading,
fetched: {
{
obj
.
name
}
}ElFetched,
{% if not obj.read_only %}
isSaving: {
{
obj
.
name
}
}ElIsSaving,
savedAt: {
{
obj
.
name
}
}ElShareSavedTime,
savingHasError: {
{
obj
.
name
}
}ElSavingHasError,
{% endif %}
})
{% endfor %}
frontend/generate/templates/reducers.tpl
deleted
100644 → 0
View file @
fa8052f4
// WARNING
// THIS FILE HAS BEEN AUTOMATICALLY GENERATED
// WITH /frontend/generate/generate_frontend_files.js
// MODIFY THE FILE ABOVE IF YOUR NOT SATISFIED
// THIS WARNING DOESN'T APPLY TO .tpl FILES...
import {
{% for obj in data %}
{
{
obj
.
NAME
}
}_INVALIDATED,
{
{
obj
.
NAME
}
}_FETCH_HAS_ERROR,
{
{
obj
.
NAME
}
}_IS_LOADING,
{
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS,
{
{
obj
.
NAME
}
}_EL_INVALIDATED,
{
{
obj
.
NAME
}
}_EL_FETCH_HAS_ERROR,
{
{
obj
.
NAME
}
}_EL_IS_LOADING,
{
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS,
{% if not obj.read_only %}
{
{
obj
.
NAME
}
}_EL_IS_SAVING,
{
{
obj
.
NAME
}
}_EL_SAVING_HAS_ERROR,
{
{
obj
.
NAME
}
}_EL_SHARE_SAVED_TIME,
{
{
obj
.
NAME
}
}_EL_SAVING_DATA_SUCCESS,
{% endif %}
{% endfor %}
} from "./action-types";
{% for obj in data %}
export function {
{
obj
.
name
}
}FetchHasError(state =
{
status
:
false
,
error
:
null
}
, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_FETCH_HAS_ERROR:
return {
status: action.hasError,
error: action.error
}
default:
return state;
}
}
export function {
{
obj
.
name
}
}IsLoading(state = false, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_IS_LOADING:
return action.isLoading;
default:
return state;
}
}
export function {
{
obj
.
name
}
}Invalidated(state = false, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_INVALIDATED:
return action.invalidated;
default:
return state;
}
}
export function {
{
obj
.
name
}
}ElIsLoading(state = false, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_IS_LOADING:
return action.isLoading;
default:
return state;
}
}
export function {
{
obj
.
name
}
}Fetched(state = { data: Object(), fetchedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_FETCH_DATA_SUCCESS:
return {
data: action.{
{
obj
.
name
}
},
fetchedAt: action.{
{
obj
.
name
}
}FetchedAt
}
default:
return state;
}
}
export function {
{
obj
.
name
}
}ElFetchHasError(state =
{
status
:
false
,
error
:
null
}
, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_FETCH_HAS_ERROR:
return {
status: action.hasError,
error: action.error
}
default:
return state;
}
}
export function {
{
obj
.
name
}
}ElInvalidated(state = false, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_INVALIDATED:
return action.invalidated;
default:
return state;
}
}
export function {
{
obj
.
name
}
}ElFetched(state = { data: Object(), fetchedAt: null }, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_FETCH_DATA_SUCCESS:
return {
data: action.{
{
obj
.
name
}
}El,
fetchedAt: action.{
{
obj
.
name
}
}ElFetchedAt
}
default:
return state;
}
}
{% if not obj.read_only %}
// Handling POST and PUT
export function {
{
obj
.
name
}
}ElIsSaving(state = false, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_IS_SAVING:
return action.isSaving;
default:
return state;
}
}
export function {
{
obj
.
name
}
}ElShareSavedTime(state = null, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_SHARE_SAVED_TIME:
return action.time;
default:
return state;
}
}
export function {
{
obj
.
name
}
}ElSavingHasError(state =
{
status
:
false
,
error
:
null
}
, action) {
switch (action.type) {
case {
{
obj
.
NAME
}
}_EL_SAVING_HAS_ERROR:
return {
status: action.hasError,
error: action.error
}
default:
return state;
}
}
{% endif %}
{% endfor %}
\ No newline at end of file
frontend/src/.gitignore
deleted
100644 → 0
View file @
fa8052f4
generated
\ No newline at end of file
frontend/src/api/CrudActions.js
0 → 100644
View file @
53dc786d
import
SmartActions
from
"
./SmartActions
"
;
import
getCrudActionTypes
from
"
./getCrudActionTypes
"
;
// TODO : Lacks delete actions
// Read generic functions
function
_isReading
(
status
,
type
)
{
return
{
type
,
status
}
}
function
_readFailed
(
failed
,
error
,
type
)
{
return
{
type
,
failed
,
error
}
}
function
_readSucceeded
(
data
,
type
)
{
return
{
type
,
data
,
};
}
/**
* Class that contains all actions related to API handling
*
* @export
* @class CrudActions
*/
export
default
class
CrudActions
{
/**
* Creates an instance of CrudActions.
* @param {object} apiInfo
* @memberof CrudActions
*/
constructor
(
apiInfo
)
{
this
.
name
=
apiInfo
.
name
;
this
.
apiEndPoint
=
apiInfo
.
apiEndPoint
;
this
.
readOnly
=
apiInfo
.
readOnly
===
true
;
this
.
smartActions
=
new
SmartActions
();
this
.
types
=
getCrudActionTypes
(
this
.
name
);
}
// read all
/**
* Tells redux to read the root of the api endpoint
*
* @returns {function}
* @memberof CrudActions
*/
readAll
()
{
const
self
=
this
;
function
isReadingAll
(
isReadingAll
)
{
return
_isReading
(
isReadingAll
,
self
.
types
.
isReadingAll
);
}
function
readAllSucceeded
(
data
)
{
return
_readSucceeded
(
data
,
self
.
types
.
readAllSucceeded
);
}
function
readAllFailed
(
bool
,
error
=
null
)
{
return
_readFailed
(
bool
,
error
,
self
.
types
.
readAllFailed
);
}
return
this
.
smartActions
.
_FetchData
(
""
,
this
.
apiEndPoint
,
isReadingAll
,
readAllSucceeded
,
this
.
setInvalidatedAll
.
bind
(
this
),