From feaca508fcf4b45504ee04f86a6c210f9ea41a41 Mon Sep 17 00:00:00 2001 From: Sebastian Karlsson <sebka991@student.liu.se> Date: Wed, 28 Apr 2021 15:10:34 +0000 Subject: [PATCH] Add monospace font to competition codes, clean up --- .../admin/competitions/CompetitionManager.tsx | 176 +++++++++++++++++- server/populate.py | 6 +- 2 files changed, 177 insertions(+), 5 deletions(-) diff --git a/client/src/pages/admin/competitions/CompetitionManager.tsx b/client/src/pages/admin/competitions/CompetitionManager.tsx index 8ec3ee29..35dbd3b6 100644 --- a/client/src/pages/admin/competitions/CompetitionManager.tsx +++ b/client/src/pages/admin/competitions/CompetitionManager.tsx @@ -1,4 +1,18 @@ -import { Button, Menu, TablePagination, TextField, Typography } from '@material-ui/core' +import { + Button, + Menu, + ListItem, + TablePagination, + TextField, + Typography, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + ListItemText, + Tooltip, + Box, +} from '@material-ui/core' import FormControl from '@material-ui/core/FormControl' import InputLabel from '@material-ui/core/InputLabel' import MenuItem from '@material-ui/core/MenuItem' @@ -17,9 +31,12 @@ import React, { useEffect } from 'react' import { Link, useHistory } from 'react-router-dom' import { getCompetitions, setFilterParams } from '../../../actions/competitions' import { useAppDispatch, useAppSelector } from '../../../hooks' +import { Team } from '../../../interfaces/ApiModels' import { CompetitionFilterParams } from '../../../interfaces/FilterParams' import { FilterContainer, RemoveMenuItem, TopBar, YearFilterTextField } from '../styledComp' import AddCompetition from './AddCompetition' +import FileCopyIcon from '@material-ui/icons/FileCopy' +import RefreshIcon from '@material-ui/icons/Refresh' /** * Component description: @@ -36,13 +53,31 @@ const useStyles = makeStyles((theme: Theme) => margin: { margin: theme.spacing(1), }, + paper: { + backgroundColor: theme.palette.background.paper, + boxShadow: theme.shadows[5], + padding: 4, + outline: 'none', + }, }) ) +interface Code { + id: number + code: string + view_type_id: number + competition_id: number + team_id: number +} + const CompetitionManager: React.FC = (props: any) => { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null) const [activeId, setActiveId] = React.useState<number | undefined>(undefined) const [timerHandle, setTimerHandle] = React.useState<number | undefined>(undefined) + const [dialogIsOpen, setDialogIsOpen] = React.useState(false) + const [codes, setCodes] = React.useState<Code[]>([]) + const [teams, setTeams] = React.useState<Team[]>([]) + const [competitionName, setCompetitionName] = React.useState<string | undefined>(undefined) const loading = useAppSelector((state) => state.user.userInfo === null) const competitions = useAppSelector((state) => state.competitions.competitions) const filterParams = useAppSelector((state) => state.competitions.filterParams) @@ -95,7 +130,79 @@ const CompetitionManager: React.FC = (props: any) => { const handleStartCompetition = () => { history.push(`/operator/id=${activeId}&code=123123`) - console.log('GLHF!') + } + + const getCodes = async () => { + await axios + .get(`/api/competitions/${activeId}/codes`) + .then((response) => { + console.log(response.data) + setCodes(response.data.items) + }) + .catch(console.log) + } + + const getTeams = async () => { + await axios + .get(`/api/competitions/${activeId}/teams`) + .then((response) => { + console.log(response.data.items) + setTeams(response.data.items) + }) + .catch((err) => { + console.log(err) + }) + } + + const getCompetitionName = async () => { + await axios + .get(`/api/competitions/${activeId}`) + .then((response) => { + console.log(response.data.name) + setCompetitionName(response.data.name) + }) + .catch((err) => { + console.log(err) + }) + } + + const getTypeName = (code: Code) => { + let typeName = '' + switch (code.view_type_id) { + case 1: + const team = teams.find((team) => team.id === code.team_id) + if (team) { + typeName = team.name + } else { + typeName = 'Lagnamn hittades ej' + } + break + case 2: + typeName = 'Domare' + break + case 3: + typeName = 'Publik' + break + case 4: + typeName = 'Tävlingsoperator' + break + default: + typeName = 'Typ hittades ej' + break + } + return typeName + } + + const handleOpenDialog = async () => { + await getCodes() + await getTeams() + await getCompetitionName() + setDialogIsOpen(true) + } + + const handleCloseDialog = () => { + setDialogIsOpen(false) + setAnchorEl(null) } const handleDuplicateCompetition = async () => { @@ -117,6 +224,18 @@ const CompetitionManager: React.FC = (props: any) => { dispatch(getCompetitions()) } + const refreshCode = async (code: Code) => { + await axios + .put(`/api/competitions/${activeId}/codes/${code.id}`) + .then(() => { + getCodes() + dispatch(getCompetitions()) + }) + .catch(({ response }) => { + console.warn(response.data) + }) + } + return ( <div> <TopBar> @@ -207,9 +326,62 @@ const CompetitionManager: React.FC = (props: any) => { /> <Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}> <MenuItem onClick={handleStartCompetition}>Starta</MenuItem> + <MenuItem onClick={handleOpenDialog}>Visa koder</MenuItem> <MenuItem onClick={handleDuplicateCompetition}>Duplicera</MenuItem> <RemoveMenuItem onClick={handleDeleteCompetition}>Ta bort</RemoveMenuItem> </Menu> + <Dialog + open={dialogIsOpen} + onClose={handleCloseDialog} + aria-labelledby="max-width-dialog-title" + maxWidth="xl" + fullWidth={false} + fullScreen={false} + > + <DialogTitle id="max-width-dialog-title" className={classes.paper}> + Koder för {competitionName} + </DialogTitle> + <DialogContent> + {/* <DialogContentText>Här visas tävlingskoderna till den valda tävlingen.</DialogContentText> */} + {codes.map((code) => ( + <ListItem key={code.id} style={{ display: 'flex' }}> + <ListItemText primary={`${getTypeName(code)}: `} /> + <Typography component="div"> + <ListItemText style={{ textAlign: 'right', marginLeft: '10px' }}> + <Box fontFamily="Monospace" fontWeight="fontWeightBold"> + {code.code} + </Box> + </ListItemText> + </Typography> + <Tooltip title="Generera ny kod" arrow> + <Button + margin-right="0px" + onClick={() => { + refreshCode(code) + }} + > + <RefreshIcon fontSize="small" /> + </Button> + </Tooltip> + <Tooltip title="Kopiera kod" arrow> + <Button + margin-right="0px" + onClick={() => { + navigator.clipboard.writeText(code.code) + }} + > + <FileCopyIcon fontSize="small" /> + </Button> + </Tooltip> + </ListItem> + ))} + </DialogContent> + <DialogActions> + <Button onClick={handleCloseDialog} color="primary"> + Stäng + </Button> + </DialogActions> + </Dialog> </div> ) } diff --git a/server/populate.py b/server/populate.py index e0bb0bd9..92183b6c 100644 --- a/server/populate.py +++ b/server/populate.py @@ -17,7 +17,7 @@ def _add_items(): roles = ["Admin", "Editor"] cities = ["Linköping", "Stockholm", "Norrköping", "Örkelljunga"] - teams = ["Gymnasieskola A", "Gymnasieskola B", "Gymnasieskola C"] + teams = ["Högstadie A", "Högstadie B", "Högstadie C"] for name in media_types: dbc.add.mediaType(name) @@ -76,8 +76,8 @@ def _add_items(): ) """ - for i in range(3): - dbc.add.question_alternative(f"Alternative {i}", 0, item_slide.questions[0].id) + for k in range(3): + dbc.add.question_alternative(f"Alternative {k}", 0, item_slide.questions[0].id) # Add text components # TODO: Add images as components -- GitLab