Commit a3cf92a7 authored by Florent Chehab's avatar Florent Chehab

Automatic generation of actions and reducers for Redux

parent adc1d2fe
let swig = require('swig');
let fs = require('fs');
let path = require('path');
let saving_dir = path.normalize(path.dirname(__filename) + "/../src/generated/")
if (!fs.existsSync(saving_dir)){
fs.mkdirSync(saving_dir);
}
let templates_dir = path.dirname(__filename) + '/templates/';
let templates = [
'action-types',
'actions',
'reducers'
]
let config = [
{
NAME: 'UNIVERSITIES',
name: 'universities'
}, {
NAME: 'COUNTRIES',
name: 'countries'
}
]
templates.forEach(function (filename) {
let template = swig.compileFile(templates_dir + filename + '.tpl');
let output = "";
config.forEach(function (obj) {
output += template(obj) + "\n\n";
})
fs.writeFile(saving_dir + filename + ".js", output, function (err) {
if (err) {
return console.log(err);
};
});
});
export const {{NAME}}_HAS_ERROR = '{{NAME}}_HAS_ERROR'
export const {{NAME}}_IS_LOADING = '{{NAME}}_IS_LOADING'
export const {{NAME}}_FETCH_DATA_SUCCESS = '{{NAME}}_FETCH_DATA_SUCCESS'
export const {{NAME}}_INVALIDATED = '{{NAME}}_INVALIDATED'
import {
COUNTRIES_HAS_ERROR,
COUNTRIES_IS_LOADING,
COUNTRIES_FETCH_DATA_SUCCESS,
COUNTRIES_INVALIDATED
} from "../constants/action-types";
{{NAME}}_HAS_ERROR,
{{NAME}}_IS_LOADING,
{{NAME}}_FETCH_DATA_SUCCESS,
{{NAME}}_INVALIDATED
} from "./action-types";
export function countriesHasError(bool) {
export function {{name}}HasError(bool) {
return {
type: COUNTRIES_HAS_ERROR,
type: {{NAME}}_HAS_ERROR,
hasError: bool
};
}
export function countriesIsLoading(bool) {
export function {{name}}IsLoading(bool) {
return {
type: COUNTRIES_IS_LOADING,
type: {{NAME}}_IS_LOADING,
isLoading: bool
};
}
export function countriesInvalidated(bool) {
export function {{name}}Invalidated(bool) {
return {
type: COUNTRIES_INVALIDATED,
type: {{NAME}}_INVALIDATED,
invalidated: bool
};
}
export function countriesFetchDataSuccess(countries) {
countriesInvalidated(false)
export function {{name}}FetchDataSuccess({{name}}) {
{{name}}Invalidated(false)
return {
type: COUNTRIES_FETCH_DATA_SUCCESS,
countries,
countriesFetchedAt: Date.now()
type: {{NAME}}_FETCH_DATA_SUCCESS,
{{name}},
{{name}}FetchedAt: Date.now()
};
}
export function countriesFetchData(url) {
export function {{name}}FetchData(url) {
return (dispatch) => {
dispatch(countriesIsLoading(true));
dispatch({{name}}IsLoading(true));
fetch(url)
.then((response) => {
......@@ -48,15 +48,15 @@ export function countriesFetchData(url) {
throw Error(response.statusText);
}
dispatch(countriesIsLoading(false));
dispatch({{name}}IsLoading(false));
return response;
})
.then((response) => response.json())
.then((countries) => {
dispatch(countriesInvalidated(false));
dispatch(countriesFetchDataSuccess(countries));
.then(({{name}}) => {
dispatch({{name}}Invalidated(false));
dispatch({{name}}FetchDataSuccess({{name}}));
})
.catch(() => dispatch(countriesHasError(true)));
.catch(() => dispatch({{name}}HasError(true)));
};
}
\ No newline at end of file
import {
COUNTRIES_HAS_ERROR,
COUNTRIES_IS_LOADING,
COUNTRIES_FETCH_DATA_SUCCESS,
COUNTRIES_INVALIDATED
} from "../constants/action-types";
{{NAME}}_HAS_ERROR,
{{NAME}}_IS_LOADING,
{{NAME}}_FETCH_DATA_SUCCESS,
{{NAME}}_INVALIDATED
} from "./action-types";
export function countriesHasError(state = false, action) {
export function {{name}}HasError(state = false, action) {
switch (action.type) {
case COUNTRIES_HAS_ERROR:
case {{NAME}}_HAS_ERROR:
return action.hasError;
default:
......@@ -16,9 +16,9 @@ export function countriesHasError(state = false, action) {
}
}
export function countriesIsLoading(state = false, action) {
export function {{name}}IsLoading(state = false, action) {
switch (action.type) {
case COUNTRIES_IS_LOADING:
case {{NAME}}_IS_LOADING:
return action.isLoading;
default:
......@@ -26,9 +26,9 @@ export function countriesIsLoading(state = false, action) {
}
}
export function countriesInvalidated(state = false, action) {
export function {{name}}Invalidated(state = false, action) {
switch (action.type) {
case COUNTRIES_INVALIDATED:
case {{NAME}}_INVALIDATED:
return action.invalidated;
default:
......@@ -36,12 +36,12 @@ export function countriesInvalidated(state = false, action) {
}
}
export function countriesFetched(state = { countries: [], countriesFetchedAt: null }, action) {
export function {{name}}Fetched(state = { {{name}}: [], {{name}}FetchedAt: null }, action) {
switch (action.type) {
case COUNTRIES_FETCH_DATA_SUCCESS:
case {{NAME}}_FETCH_DATA_SUCCESS:
return {
countries: action.countries,
fetchedAt: action.countriesFetchedAt
{{name}}: action.{{name}},
fetchedAt: action.{{name}}FetchedAt
}
default:
......
generated
\ No newline at end of file
import {
UNIVERSITIES_HAS_ERROR,
UNIVERSITIES_IS_LOADING,
UNIVERSITIES_FETCH_DATA_SUCCESS,
UNIVERSITIES_INVALIDATED
} from "../constants/action-types";
export function universitiesHasError(bool) {
return {
type: UNIVERSITIES_HAS_ERROR,
hasError: bool
};
}
export function universitiesIsLoading(bool) {
return {
type: UNIVERSITIES_IS_LOADING,
isLoading: bool
};
}
export function universitiesInvalidated(bool) {
return {
type: UNIVERSITIES_INVALIDATED,
invalidated: bool
};
}
export function universitiesFetchDataSuccess(universities) {
universitiesInvalidated(false)
return {
type: UNIVERSITIES_FETCH_DATA_SUCCESS,
universities,
universitiesFetchedAt: Date.now()
};
}
export function universitiesFetchData(url) {
return (dispatch) => {
dispatch(universitiesIsLoading(true));
fetch(url)
.then((response) => {
if (!response.ok) {
throw Error(response.statusText);
}
dispatch(universitiesIsLoading(false));
return response;
})
.then((response) => response.json())
.then((universities) => {
dispatch(universitiesInvalidated(false));
dispatch(universitiesFetchDataSuccess(universities));
})
.catch(() => dispatch(universitiesHasError(true)));
};
}
\ No newline at end of file
......@@ -28,7 +28,7 @@ import {
import {
countriesFetchData,
} from '../actions/countries';
} from '../generated/actions';
import PageMap from './pages/PageMap';
......
......@@ -6,7 +6,7 @@ import { Map, TileLayer, Marker, Popup, LayersControl, FeatureGroup, Circle, Lay
import {
universitiesFetchData,
universitiesInvalidated
} from '../../actions/universities';
} from '../../generated/actions';
......
......@@ -6,7 +6,7 @@ import { withStyles } from '@material-ui/core/styles';
import {
universitiesInvalidated
} from '../../actions/universities';
} from '../../generated/actions';
const styles = theme => ({
......
export const UNIVERSITIES_HAS_ERROR = 'UNIVERSITIES_HAS_ERROR'
export const UNIVERSITIES_IS_LOADING = 'UNIVERSITIES_IS_LOADING'
export const UNIVERSITIES_FETCH_DATA_SUCCESS = 'UNIVERSITIES_FETCH_DATA_SUCCESS'
export const UNIVERSITIES_INVALIDATED = 'UNIVERSITIES_INVALIDATED'
export const COUNTRIES_HAS_ERROR = 'COUNTRIES_HAS_ERROR'
export const COUNTRIES_IS_LOADING = 'COUNTRIES_IS_LOADING'
export const COUNTRIES_FETCH_DATA_SUCCESS = 'COUNTRIES_FETCH_DATA_SUCCESS'
export const COUNTRIES_INVALIDATED = 'COUNTRIES_INVALIDATED'
import { combineReducers } from 'redux';
import {
universitiesFetched,
universitiesHasError,
universitiesIsLoading,
universitiesInvalidated
} from './universities';
import {
universitiesInvalidated,
countriesFetched,
countriesHasError,
countriesIsLoading,
countriesInvalidated
} from './countries';
} from '../generated/reducers';
const rootReducer = combineReducers({
......
import {
UNIVERSITIES_HAS_ERROR,
UNIVERSITIES_IS_LOADING,
UNIVERSITIES_FETCH_DATA_SUCCESS,
UNIVERSITIES_INVALIDATED
} from "../constants/action-types";
export function universitiesHasError(state = false, action) {
switch (action.type) {
case UNIVERSITIES_HAS_ERROR:
return action.hasError;
default:
return state;
}
}
export function universitiesIsLoading(state = false, action) {
switch (action.type) {
case UNIVERSITIES_IS_LOADING:
return action.isLoading;
default:
return state;
}
}
export function universitiesInvalidated(state = false, action) {
switch (action.type) {
case UNIVERSITIES_INVALIDATED:
return action.invalidated;
default:
return state;
}
}
export function universitiesFetched(state = { universities: [], universitiesFetchedAt: null }, action) {
switch (action.type) {
case UNIVERSITIES_FETCH_DATA_SUCCESS:
return {
universities: action.universities,
fetchedAt: action.universitiesFetchedAt
}
default:
return state;
}
}
\ No newline at end of file
......@@ -339,6 +339,12 @@
"integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=",
"dev": true
},
"amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"dev": true
},
"ansi-escapes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
......@@ -479,6 +485,12 @@
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
"dev": true
},
"async": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
"dev": true
},
"async-each": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
......@@ -4928,6 +4940,24 @@
"mimic-fn": "^1.0.0"
}
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"dev": true,
"requires": {
"minimist": "~0.0.1",
"wordwrap": "~0.0.2"
},
"dependencies": {
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
"dev": true
}
}
},
"optionator": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
......@@ -6347,6 +6377,69 @@
"has-flag": "^3.0.0"
}
},
"swig": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/swig/-/swig-1.4.2.tgz",
"integrity": "sha1-QIXKBFM2kQS11IPihBs5t64aq6U=",
"dev": true,
"requires": {
"optimist": "~0.6",
"uglify-js": "~2.4"
},
"dependencies": {
"camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
"dev": true
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
"source-map": {
"version": "0.1.34",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz",
"integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=",
"dev": true,
"requires": {
"amdefine": ">=0.0.4"
}
},
"uglify-js": {
"version": "2.4.24",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz",
"integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=",
"dev": true,
"requires": {
"async": "~0.2.6",
"source-map": "0.1.34",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.5.4"
}
},
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
"dev": true
},
"yargs": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz",
"integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=",
"dev": true,
"requires": {
"camelcase": "^1.0.2",
"decamelize": "^1.0.0",
"window-size": "0.1.0",
"wordwrap": "0.0.2"
}
}
}
},
"symbol-observable": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
......@@ -6536,6 +6629,12 @@
}
}
},
"uglify-to-browserify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
"dev": true
},
"uglifyjs-webpack-plugin": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz",
......@@ -6851,6 +6950,12 @@
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
"dev": true
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
......
......@@ -4,8 +4,9 @@
"description": "[![build](/../badges/master/build.svg)](https://gitlab.utc.fr/chehabfl/outgoing_rex/pipelines) [![coverage](/../badges/master/coverage.svg)](https://chehabfl.gitlab.utc.fr/outgoing_rex/) [![License](https://img.shields.io/badge/License-BSD%202--Clause-green.svg)](https://opensource.org/licenses/BSD-2-Clause)",
"main": "manage.py",
"scripts": {
"dev": "webpack --mode development ./frontend/src/index.js --output ./frontend/static/frontend/main.js",
"build": "webpack --mode production ./frontend/src/index.js --output ./frontend/static/frontend/main.js",
"gen": "node ./frontend/generate/generate_frontend_files.js",
"dev": "npm run gen && webpack --mode development ./frontend/src/index.js --output ./frontend/static/frontend/main.js",
"build": "npm run gen && webpack --mode production ./frontend/src/index.js --output ./frontend/static/frontend/main.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
......@@ -45,6 +46,7 @@
"react-script": "^2.0.5",
"recharts": "^1.1.0",
"redux-devtools": "^3.4.1",
"swig": "^1.4.2",
"weak-key": "^1.0.1",
"webpack": "^4.17.0",
"webpack-cli": "^3.1.0"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment