diff --git a/.gitignore b/.gitignore index a690686765ab7b22f64eda9c085f2ba3fccd696b..d5cf16df23f3f817ba7274e27d16f4dafde28ac4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ htmlcov .pytest_cache /.idea .vs/ -*/static \ No newline at end of file +/server/app/static/ \ No newline at end of file diff --git a/client/src/Main.tsx b/client/src/Main.tsx index f32aad9fbf044a2fd055fa29e30e0ea830898e5b..bc0a2e85175899a8a06f8c34c4e8ae04be337a56 100644 --- a/client/src/Main.tsx +++ b/client/src/Main.tsx @@ -1,5 +1,7 @@ -import React from 'react' +import React, { useEffect } from 'react' import { BrowserRouter, Route, Switch } from 'react-router-dom' +import { getTypes } from './actions/typesAction' +import { useAppDispatch } from './hooks' import AdminPage from './pages/admin/AdminPage' import LoginPage from './pages/login/LoginPage' import PresentationEditorPage from './pages/presentationEditor/PresentationEditorPage' @@ -11,6 +13,10 @@ import ViewSelectPage from './pages/views/ViewSelectPage' import SecureRoute from './utils/SecureRoute' const Main: React.FC = () => { + const dispatch = useAppDispatch() + useEffect(() => { + dispatch(getTypes()) + }, []) return ( <BrowserRouter> <Switch> diff --git a/client/src/actions/presentation.ts b/client/src/actions/presentation.ts index 9e482d2b4c51d49fdd04dd8f18721a1e74e82d5a..6821aa2c035c099eb4b21b3799b47e50157dc9aa 100644 --- a/client/src/actions/presentation.ts +++ b/client/src/actions/presentation.ts @@ -1,5 +1,5 @@ import axios from 'axios' -import { Slide } from '../interfaces/Slide' +import { Slide } from '../interfaces/ApiModels' import { AppDispatch } from './../store' import Types from './types' diff --git a/client/src/interfaces/ApiModels.ts b/client/src/interfaces/ApiModels.ts index 3c72e99fdacc5a81f5a7dbd461b1d22cc4dd4d14..0053fc1bf3070e346798079bc467eac167aba358 100644 --- a/client/src/interfaces/ApiModels.ts +++ b/client/src/interfaces/ApiModels.ts @@ -32,9 +32,19 @@ export interface User extends NameID { city_id: number } +export interface Slide { + competition_id: number + id: number + order: number + timer: number + title: string +} + export interface Competition extends NameID { + font: string city_id: number year: number + background_image_id: number } export interface Team extends NameID { diff --git a/client/src/interfaces/ApiRichModels.ts b/client/src/interfaces/ApiRichModels.ts index e21ae5fa14f709892b4d98c1685b690cd14e8284..99ee4ec2039320d72ed95a196e5205b7be96dd0b 100644 --- a/client/src/interfaces/ApiRichModels.ts +++ b/client/src/interfaces/ApiRichModels.ts @@ -1,5 +1,4 @@ -import { Component } from 'react' -import { Media, QuestionAlternative, QuestionAnswer, QuestionType } from './ApiModels' +import { Component, QuestionAlternative, QuestionAnswer, QuestionType } from './ApiModels' export interface RichCompetition { name: string @@ -17,7 +16,6 @@ export interface RichSlide { title: string competition_id: number components: Component[] - medias: Media[] questions: RichQuestion[] } diff --git a/client/src/interfaces/Slide.ts b/client/src/interfaces/Slide.ts deleted file mode 100644 index dcdbd366cffa4482c9de7979663c3750bcad2f4d..0000000000000000000000000000000000000000 --- a/client/src/interfaces/Slide.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface Slide { - competition_id: number - id: number - order: number - timer: number - title: string -} diff --git a/client/src/interfaces/Team.ts b/client/src/interfaces/Team.ts deleted file mode 100644 index 10b4350e5c2ffc6068308bd90e12adfaf584ef24..0000000000000000000000000000000000000000 --- a/client/src/interfaces/Team.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Team { - id: number - name: string -} diff --git a/client/src/pages/admin/AdminPage.tsx b/client/src/pages/admin/AdminPage.tsx index 8bbb68fa80ce1a20ea72a2b9d4de49ad18a3bb83..beff5f938a1e003e945f4066c3d29898457153bd 100644 --- a/client/src/pages/admin/AdminPage.tsx +++ b/client/src/pages/admin/AdminPage.tsx @@ -59,11 +59,12 @@ const AdminView: React.FC = () => { const [openIndex, setOpenIndex] = React.useState(0) const { path, url } = useRouteMatch() const currentUser = useAppSelector((state) => state.user.userInfo) - const isAdmin = () => currentUser && currentUser.role.name === 'Admin' + const isAdmin = useAppSelector((state) => Boolean(state.roles.roles.find((x) => x.id === currentUser?.role_id))) const dispatch = useAppDispatch() const handleLogout = () => { dispatch(logoutUser()) } + useEffect(() => { dispatch(getCities()) dispatch(getRoles()) @@ -83,7 +84,7 @@ const AdminView: React.FC = () => { ] const renderItems = () => { - const menuItems = isAdmin() ? menuAdminItems : menuEditorItems + const menuItems = isAdmin ? menuAdminItems : menuEditorItems return menuItems.map((value, index) => ( <ListItem button @@ -105,7 +106,7 @@ const AdminView: React.FC = () => { <AppBar position="fixed" className={classes.appBar}> <Toolbar> <Typography variant="h5" noWrap> - {isAdmin() ? menuAdminItems[openIndex].text : menuEditorItems[openIndex].text} + {isAdmin ? menuAdminItems[openIndex].text : menuEditorItems[openIndex].text} </Typography> </Toolbar> </AppBar> diff --git a/client/src/pages/admin/competitions/AddCompetition.tsx b/client/src/pages/admin/competitions/AddCompetition.tsx index 3d45e629769c642cde13499ba988901a6c71a0d9..e9666770191249f79fb0f2c5295d6fb43875bb04 100644 --- a/client/src/pages/admin/competitions/AddCompetition.tsx +++ b/client/src/pages/admin/competitions/AddCompetition.tsx @@ -31,7 +31,8 @@ const competitionSchema: Yup.SchemaOf<formType> = Yup.object({ const AddCompetition: React.FC = (props: any) => { const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null) const cities = useAppSelector((state) => state.cities.cities) - const userCity = useAppSelector((state) => state.user.userInfo?.city) + const currentUser = useAppSelector((state) => state.user.userInfo) + const userCity = cities.find((city) => city.id === currentUser?.city_id) const [selectedCity, setSelectedCity] = React.useState<City | undefined>(userCity) const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { setAnchorEl(event.currentTarget) diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx index 2993b12b78e9e532e71ab4573248bf1b51bcc4e8..ce09f41d7a1d3b58eb9e0df6051418b679721a23 100644 --- a/client/src/pages/presentationEditor/PresentationEditorPage.tsx +++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx @@ -9,6 +9,7 @@ import React, { useEffect } from 'react' import { useParams } from 'react-router-dom' import { getCities } from '../../actions/cities' import { getEditorCompetition } from '../../actions/editor' +import { getTypes } from '../../actions/typesAction' import { useAppDispatch, useAppSelector } from '../../hooks' import { Content } from '../views/styled' import SettingsPanel from './components/SettingsPanel' @@ -69,6 +70,7 @@ const PresentationEditorPage: React.FC = () => { useEffect(() => { dispatch(getEditorCompetition(id)) dispatch(getCities()) + dispatch(getTypes()) }, []) return ( <PresentationEditorContainer> diff --git a/client/src/reducers/presentationReducer.ts b/client/src/reducers/presentationReducer.ts index b4325680b0c1d87698a0aa798fc013528855f4f6..936f874026aa48bed6c926f660d33a416ef760da 100644 --- a/client/src/reducers/presentationReducer.ts +++ b/client/src/reducers/presentationReducer.ts @@ -1,8 +1,7 @@ import { AnyAction } from 'redux' import Types from '../actions/types' +import { Slide, Team } from '../interfaces/ApiModels' import { RichCompetition } from './../interfaces/ApiRichModels' -import { Slide } from './../interfaces/Slide' -import { Team } from './../interfaces/Team' interface PresentationState { competition: RichCompetition diff --git a/client/src/reducers/userReducer.ts b/client/src/reducers/userReducer.ts index 6064292aa9ce8d325536d5fea5febb0472ecd4e7..91c056d3f0a55383fed0a0e40d0e94240d14a947 100644 --- a/client/src/reducers/userReducer.ts +++ b/client/src/reducers/userReducer.ts @@ -1,12 +1,11 @@ import { AnyAction } from 'redux' import Types from '../actions/types' -import { City, Role } from '../interfaces/ApiModels' interface UserInfo { name: string email: string - role: Role - city: City + role_id: number + city_id: number id: number } diff --git a/server/app/apis/misc.py b/server/app/apis/misc.py index a78c2f8c82ee7b44740226babc0ededd8485b978..a74ac6d1c790198e0e6cda87b4ddb638499802c2 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 admin_required, item_response, list_response from app.core.dto import MiscDTO -from app.database.models import City, ComponentType, MediaType, QuestionType, Role, ViewType +from app.database.models import (City, ComponentType, MediaType, QuestionType, + Role, ViewType) from flask_jwt_extended import jwt_required from flask_restx import Resource, reqparse @@ -22,7 +23,6 @@ name_parser.add_argument("name", type=str, required=True, location="json") @api.route("/types") class TypesList(Resource): - @jwt_required def get(self): result = {} result["media_types"] = media_type_schema.dump(dbc.get.all(MediaType))