From 1bb8a56db9b089f0b921763f4f27ff1af2c4eb09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20Sch=C3=B6nfelder?= <carsc272@student.liu.se> Date: Fri, 23 Apr 2021 10:50:49 +0000 Subject: [PATCH] Resolve "Dashboard api calls" --- client/src/actions/statistics.ts | 15 ++++++++++++ client/src/actions/types.ts | 1 + client/src/pages/admin/AdminPage.tsx | 2 ++ .../components/NumberOfCompetitions.tsx | 21 +++++++--------- .../dashboard/components/NumberOfRegions.tsx | 2 +- .../dashboard/components/NumberOfUsers.tsx | 2 +- client/src/reducers/allReducers.ts | 2 ++ client/src/reducers/statisticsReducer.ts | 24 +++++++++++++++++++ server/app/apis/misc.py | 13 +++++++++- 9 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 client/src/actions/statistics.ts create mode 100644 client/src/reducers/statisticsReducer.ts diff --git a/client/src/actions/statistics.ts b/client/src/actions/statistics.ts new file mode 100644 index 00000000..a32dce35 --- /dev/null +++ b/client/src/actions/statistics.ts @@ -0,0 +1,15 @@ +import axios from 'axios' +import { AppDispatch } from './../store' +import Types from './types' + +export const getStatistics = () => async (dispatch: AppDispatch) => { + await axios + .get('/api/misc/statistics') + .then((res) => { + dispatch({ + type: Types.SET_STATISTICS, + payload: res.data, + }) + }) + .catch((err) => console.log(err)) +} diff --git a/client/src/actions/types.ts b/client/src/actions/types.ts index a417f6af..189bf16c 100644 --- a/client/src/actions/types.ts +++ b/client/src/actions/types.ts @@ -29,4 +29,5 @@ export default { SET_CITIES_TOTAL: 'SET_CITIES_TOTAL', SET_CITIES_COUNT: 'SET_CITIES_COUNT', SET_TYPES: 'SET_TYPES', + SET_STATISTICS: 'SET_STATISTICS', } diff --git a/client/src/pages/admin/AdminPage.tsx b/client/src/pages/admin/AdminPage.tsx index 30cfe656..1b543083 100644 --- a/client/src/pages/admin/AdminPage.tsx +++ b/client/src/pages/admin/AdminPage.tsx @@ -20,6 +20,7 @@ import React, { useEffect } from 'react' import { Link, Route, Switch, useRouteMatch } from 'react-router-dom' import { getCities } from '../../actions/cities' import { getRoles } from '../../actions/roles' +import { getStatistics } from '../../actions/statistics' import { getTypes } from '../../actions/typesAction' import { logoutUser } from '../../actions/user' import { useAppDispatch, useAppSelector } from '../../hooks' @@ -71,6 +72,7 @@ const AdminView: React.FC = () => { dispatch(getCities()) dispatch(getRoles()) dispatch(getTypes()) + dispatch(getStatistics()) }, []) const menuAdminItems = [ diff --git a/client/src/pages/admin/dashboard/components/NumberOfCompetitions.tsx b/client/src/pages/admin/dashboard/components/NumberOfCompetitions.tsx index 87d8272a..eb667ebd 100644 --- a/client/src/pages/admin/dashboard/components/NumberOfCompetitions.tsx +++ b/client/src/pages/admin/dashboard/components/NumberOfCompetitions.tsx @@ -1,24 +1,19 @@ import { Box, Typography } from '@material-ui/core' -import React, { useEffect } from 'react' -import { getCompetitions } from '../../../../actions/competitions' -import { useAppDispatch, useAppSelector } from '../../../../hooks' +import React from 'react' +import { useAppSelector } from '../../../../hooks' const NumberOfCompetitions: React.FC = () => { - const competitions = useAppSelector((state) => state.competitions.competitions) - const dispatch = useAppDispatch() + const competitions = useAppSelector((state) => state.statistics.competitions) const handleCount = () => { - if (competitions.length >= 1000000) { - ;<div>{competitions.length / 1000000 + 'M'}</div> - } else if (competitions.length >= 1000) { - ;<div>{competitions.length / 1000 + 'K'}</div> + if (competitions >= 1000000) { + ;<div>{competitions / 1000000 + 'M'}</div> + } else if (competitions >= 1000) { + ;<div>{competitions / 1000 + 'K'}</div> } - return <div>{competitions.length}</div> + return <div>{competitions}</div> } - useEffect(() => { - dispatch(getCompetitions()) - }, []) return ( <div> <Box width="100%" height="100%"> diff --git a/client/src/pages/admin/dashboard/components/NumberOfRegions.tsx b/client/src/pages/admin/dashboard/components/NumberOfRegions.tsx index 360b3663..f3195f4c 100644 --- a/client/src/pages/admin/dashboard/components/NumberOfRegions.tsx +++ b/client/src/pages/admin/dashboard/components/NumberOfRegions.tsx @@ -4,7 +4,7 @@ import { getCities } from '../../../../actions/cities' import { useAppDispatch, useAppSelector } from '../../../../hooks' const NumberOfRegions: React.FC = () => { - const regions = useAppSelector((state) => state.cities.total) + const regions = useAppSelector((state) => state.statistics.regions) const dispatch = useAppDispatch() const handleCount = () => { diff --git a/client/src/pages/admin/dashboard/components/NumberOfUsers.tsx b/client/src/pages/admin/dashboard/components/NumberOfUsers.tsx index af0f9767..0e75cf1b 100644 --- a/client/src/pages/admin/dashboard/components/NumberOfUsers.tsx +++ b/client/src/pages/admin/dashboard/components/NumberOfUsers.tsx @@ -4,7 +4,7 @@ import { getSearchUsers } from '../../../../actions/searchUser' import { useAppDispatch, useAppSelector } from '../../../../hooks' const NumberOfUsers: React.FC = () => { - const usersTotal = useAppSelector((state) => state.searchUsers.total) + const usersTotal = useAppSelector((state) => state.statistics.users) const dispatch = useAppDispatch() const handleCount = () => { diff --git a/client/src/reducers/allReducers.ts b/client/src/reducers/allReducers.ts index 2aee4697..c23384c2 100644 --- a/client/src/reducers/allReducers.ts +++ b/client/src/reducers/allReducers.ts @@ -7,6 +7,7 @@ import editorReducer from './editorReducer' import presentationReducer from './presentationReducer' import rolesReducer from './rolesReducer' import searchUserReducer from './searchUserReducer' +import statisticsReducer from './statisticsReducer' import typesReducer from './typesReducer' import uiReducer from './uiReducer' import userReducer from './userReducer' @@ -22,5 +23,6 @@ const allReducers = combineReducers({ roles: rolesReducer, searchUsers: searchUserReducer, types: typesReducer, + statistics: statisticsReducer, }) export default allReducers diff --git a/client/src/reducers/statisticsReducer.ts b/client/src/reducers/statisticsReducer.ts new file mode 100644 index 00000000..78a06e11 --- /dev/null +++ b/client/src/reducers/statisticsReducer.ts @@ -0,0 +1,24 @@ +import { AnyAction } from 'redux' +import Types from '../actions/types' + +interface StatisticsState { + users: number + competitions: number + regions: number +} + +const initialState: StatisticsState = { + users: 0, + competitions: 0, + regions: 0, +} + +export default function (state = initialState, action: AnyAction) { + switch (action.type) { + case Types.SET_STATISTICS: + state = action.payload as StatisticsState + return state + default: + return state + } +} diff --git a/server/app/apis/misc.py b/server/app/apis/misc.py index 5364a5e4..8b3bd5e5 100644 --- a/server/app/apis/misc.py +++ b/server/app/apis/misc.py @@ -1,7 +1,8 @@ import app.database.controller as dbc from app.apis import check_jwt, item_response, list_response +from app.core import http_codes from app.core.dto import MiscDTO -from app.database.models import City, ComponentType, MediaType, QuestionType, Role, ViewType +from app.database.models import City, Competition, ComponentType, MediaType, QuestionType, Role, User, ViewType from flask_jwt_extended import jwt_required from flask_restx import Resource, reqparse @@ -72,3 +73,13 @@ class Cities(Resource): dbc.delete.default(item) items = dbc.get.all(City) return list_response(city_schema.dump(items)) + + +@api.route("/statistics") +class Statistics(Resource): + @check_jwt(editor=True) + def get(self): + user_count = User.query.count() + competition_count = Competition.query.count() + region_count = City.query.count() + return {"users": user_count, "competitions": competition_count, "regions": region_count}, http_codes.OK -- GitLab