Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
{
"presets": [[
"@babel/preset-env",
{
"targets": {
"node": "10"
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "10"
}
}
}
], "@babel/preset-react"],
],
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator"
]
}


1 change: 1 addition & 0 deletions .env-sample → .env-example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
REACT_APP_BACKEND_URL = backend_url;
URL="https://url"
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ debug.log*

.coveralls.yml
.env

.dccache
18 changes: 9 additions & 9 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
module.exports = {
snapshotSerializers: ['enzyme-to-json/serializer'],
setupFilesAfterEnv: ['./src/setupTest.js'],
snapshotSerializers: ["enzyme-to-json/serializer"],
setupFilesAfterEnv: ["./src/setupTest.js"],
verbose: true,
coverageDirectory: './coverage',
coverageDirectory: "./coverage",
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/src/tests/__mocks__/fileMock.js',
"\\.(css|less|scss)$": "identity-obj-proxy",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/src/tests/__mocks__/fileMock.js",
},
setupFiles: ['./src/setupTest.js'],
testPathIgnorePatterns: ['redux'],
coveragePathIgnorePatterns: ['redux'],
setupFiles: ["./src/setupTest.js"],
testPathIgnorePatterns: ["redux"],
coveragePathIgnorePatterns: ["redux"],
};
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@
"dependencies": {
"@babel/core": "7.5.4",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
"@babel/plugin-syntax-class-properties": "^7.12.1",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "7.5.4",
"@babel/preset-react": "7.0.0",
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-brands-svg-icons": "^5.15.1",
"@fortawesome/free-regular-svg-icons": "^5.15.1",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/react-fontawesome": "^0.1.12",
"axios": "^0.21.0",
"babel-loader": "8.0.6",
"babel-plugin-transform-class-properties": "^6.24.1",
Expand Down Expand Up @@ -61,6 +68,7 @@
"@storybook/addon-essentials": "^6.0.28",
"@storybook/addon-links": "^6.0.28",
"@storybook/react": "^6.0.28",
"@testing-library/react-hooks": "^3.4.2",
"babel-jest": "^26.6.3",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
Expand All @@ -69,6 +77,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"moxios": "^0.4.0",
"jest-enzyme": "^7.1.2",
"node-sass": "^5.0.0",
"react-is": "^17.0.1",
"react-test-renderer": "16.8.6",
Expand Down
7 changes: 7 additions & 0 deletions redux/actions/alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { SET_ERROR, SET_SUCCESS } from "./types";

export const success = (payload) => (dispatch) =>
dispatch({ type: SET_SUCCESS, payload });

export const resError = (payload) => (dispatch) =>
dispatch({ type: SET_ERROR, payload });
67 changes: 67 additions & 0 deletions redux/actions/roles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { GET_ROLES, CREATE_ROLE, DELETE_ROLE, UPDATE_ROLE } from "./types";
import { creating, updating, deleting, resolved } from "./statuses";
import { success, resError } from "./alerts";
import axiosBase from "../axiosBase";

export const getRoles = () => async (dispatch) => {
try {
const res = await axiosBase.get("/role");
dispatch({
type: GET_ROLES,
payload: res.data,
});
dispatch(success({ message: res.data.message }));
} catch (error) {
const { data } = error.response;
dispatch(resError({ error: data.error || data.message || data.msg }));
}
};

export const createRole = (role) => async (dispatch) => {
dispatch(creating());
try {
const res = await axiosBase.post("/role/register", role);
dispatch({
type: CREATE_ROLE,
payload: res.data,
});
dispatch(resolved());
dispatch(success({ message: res.data.msg }));
} catch (error) {
dispatch(resolved());
dispatch(resError({ error: error.response.data.error }));
}
};

export const updateRole = (id, role) => async (dispatch) => {
dispatch(updating());
try {
const res = await axiosBase.patch(`/role/${id}`, role);
dispatch({
type: UPDATE_ROLE,
payload: res.data,
});
dispatch(resolved());
dispatch(success({ message: res.data.message }));
} catch (error) {
dispatch(resolved());
dispatch(resError({ error: error.response.data.error }));
}
};

export const deleteRole = (role) => async (dispatch) => {
dispatch(deleting());
try {
const res = await axiosBase.delete(`/role/${role.id}`);
dispatch({
type: DELETE_ROLE,
payload: res.data,
id: role.id,
});
dispatch(resolved());
dispatch(success({ message: res.data.message }));
} catch (error) {
dispatch(resolved());
dispatch(resError({ error: error.response.data.error }));
}
};
17 changes: 17 additions & 0 deletions redux/actions/statuses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {
CREATING_ROLE,
ASSIGNING_ROLE,
DELETING_ROLE,
UPDATING_ROLE,
SET_RESOLVED,
} from "./types";

export const creating = () => (dispatch) => dispatch({ type: CREATING_ROLE });

export const updating = () => (dispatch) => dispatch({ type: UPDATING_ROLE });

export const assigning = () => (dispatch) => dispatch({ type: ASSIGNING_ROLE });

export const deleting = () => (dispatch) => dispatch({ type: DELETING_ROLE });

export const resolved = () => (dispatch) => dispatch({ type: SET_RESOLVED });
15 changes: 15 additions & 0 deletions redux/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,18 @@ export const SET_LOADING = "SET_LOADING";
export const SET_RESPONSE = "SET_RESPONSE";
export const SET_TOKEN = "SET_TOKEN";
export const SET_AUTH_STATUS = "SET_AUTH_STATUS";

export const GET_ROLES = "GET_ROLES";
export const CREATE_ROLE = "CREATE_ROLE";
export const UPDATE_ROLE = "UPDATE_ROLE";
export const DELETE_ROLE = "DELETE_ROLE";
export const ASSIGN_ROLE = "ASSIGN_ROLE";
export const GET_USERS = "GET_USERS";

export const CREATING_ROLE = "CREATING_ROLE";
export const UPDATING_ROLE = "UPDATING_ROLE";
export const DELETING_ROLE = "DELETING_ROLE";
export const ASSIGNING_ROLE = "ASSIGNING_ROLE";
export const SET_RESOLVED = "SET_RESOLVED";

export const SET_SUCCESS = "SET_SUCCESS";
38 changes: 38 additions & 0 deletions redux/actions/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { GET_USERS, ASSIGN_ROLE, SET_ERROR } from "./types";
import { assigning, resolved } from "./statuses";
import { success, resError } from "./alerts";
import axiosBase from "../axiosBase";

export const getUsers = () => async (dispatch) => {
try {
const res = await axiosBase.get("/users");
dispatch({
type: GET_USERS,
payload: res.data,
});
} catch (error) {
const { data } = error.response;
dispatch(resError({ error: data.error || data.message || data.msg }));
}
};

export const assignRole = ({ userRole, email }) => async (dispatch) => {
dispatch(assigning());
try {
const res = await axiosBase.post("/role/assign", {
userRole,
email,
});
const usersRes = await axiosBase.get("/users");

dispatch({
type: ASSIGN_ROLE,
payload: { users: usersRes.data.users, msg: res.data.message },
});
dispatch(success({ message: res.data.msg }));
dispatch(resolved());
} catch (error) {
dispatch(resError({ error: error.response.data?.error }));
dispatch(resolved());
}
};
14 changes: 14 additions & 0 deletions redux/axiosBase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import axios from "axios";

const url = process.env.URL;
const token = localStorage.getItem("token");

const axiosBase = axios.create({
baseURL: url,
headers: {
"x-auth-token": token,
"Content-Type": "application/json",
},
});

export default axiosBase;
17 changes: 17 additions & 0 deletions redux/reducers/alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { SET_ERROR, SET_SUCCESS } from "../actions/types";

const initialState = {
message: "",
color: "",
};

export default (state = initialState, action) => {
switch (action.type) {
case SET_SUCCESS:
return { ...state, message: action.payload.message, color: "success" };
case SET_ERROR:
return { ...state, message: action.payload.error, color: "danger" };
default:
return state;
}
};
21 changes: 15 additions & 6 deletions redux/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { combineReducers } from 'redux';
import auth from './auth';
import signup from './signup';
import profile from './profile';
import profileErrors from './profile/errors';
import linemanager from './profile/linemanager';
import { combineReducers } from "redux";
import auth from "./auth";
import signup from "./signup";
import profile from "./profile";
import profileErrors from "./profile/errors";
import linemanager from "./profile/linemanager";
import roles from "./roles";
import users from "./users";
import statuses from "./statuses";
import alerts from "./alerts";

// function that contains all reducer objects.
const allReducers = combineReducers({
Expand All @@ -12,6 +16,11 @@ const allReducers = combineReducers({
profile,
profileErrors,
linemanager,
roles,
statuses,
users,
alerts,
signup,
});

export default allReducers;
51 changes: 51 additions & 0 deletions redux/reducers/roles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
GET_ROLES,
CREATE_ROLE,
DELETE_ROLE,
UPDATE_ROLE,
} from "../actions/types";

const initialState = {
roles: [],
msg: "",
};

export default (state = initialState, action) => {
switch (action.type) {
case GET_ROLES:
return {
...state,
roles: action.payload.roles,
msg: action.payload.message,
};

case CREATE_ROLE:
return {
...state,
roles: [...state.roles, action.payload.role],
msg: action.payload.message,
};

case UPDATE_ROLE:
const { id } = action.payload.role;
const updated = state.roles.map((role) => {
if (role.id === id) {
return { ...action.payload.role };
} else return role;
});

return {
roles: updated,
msg: action.payload.message,
};

case DELETE_ROLE:
const remains = state.roles.filter((role) => role.id !== action.id);
return {
roles: remains,
msg: action.payload.message,
};
default:
return state;
}
};
31 changes: 31 additions & 0 deletions redux/reducers/statuses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
CREATING_ROLE,
ASSIGNING_ROLE,
DELETING_ROLE,
UPDATING_ROLE,
SET_RESOLVED,
} from "../actions/types";

const initialState = {
creating: false,
updating: false,
assigning: false,
deleting: false,
};

export default (state = initialState, action) => {
switch (action.type) {
case CREATING_ROLE:
return { ...state, creating: true };
case ASSIGNING_ROLE:
return { ...state, assigning: true };
case DELETING_ROLE:
return { ...state, deleting: true };
case UPDATING_ROLE:
return { ...state, updating: true };
case SET_RESOLVED:
return initialState;
default:
return state;
}
};
Loading