diff --git a/client/public/t8-circled.png b/client/public/t8-circled.png new file mode 100644 index 0000000000000000000000000000000000000000..b9a56df2c7bde99bb37a42176bccdd2728499e83 Binary files /dev/null and b/client/public/t8-circled.png differ diff --git a/client/src/actions/editor.ts b/client/src/actions/editor.ts index ac26dbdbba7e2a5c4564d7cf359ab189e6275783..903dfa7bda973511d3eb5b13e31ac02a8f7bc2ee 100644 --- a/client/src/actions/editor.ts +++ b/client/src/actions/editor.ts @@ -1,8 +1,8 @@ import axios from 'axios' -import { AppDispatch } from './../store' +import { AppDispatch, RootState } from './../store' import Types from './types' -export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch) => { +export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch, getState: () => RootState) => { await axios .get(`/competitions/${id}`) .then((res) => { @@ -10,6 +10,9 @@ export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch type: Types.SET_EDITOR_COMPETITION, payload: res.data, }) + if (getState().editor.activeSlideId === -1 && res.data.slides[0]) { + setEditorSlideId(res.data.slides[0].id)(dispatch) + } }) .catch((err) => { console.log(err) diff --git a/client/src/interfaces/ApiModels.ts b/client/src/interfaces/ApiModels.ts index 14d7bf5b79afc4bb4eaff8afcf3096827e35bca0..650814f11fe4bd135822dcdb97855c430dd750ca 100644 --- a/client/src/interfaces/ApiModels.ts +++ b/client/src/interfaces/ApiModels.ts @@ -61,7 +61,7 @@ export interface Question extends NameID { export interface QuestionAlternative { id: number text: string - value: boolean + value: number question_id: number } export interface QuestionAnswer { diff --git a/client/src/interfaces/ApiRichModels.ts b/client/src/interfaces/ApiRichModels.ts index 99ee4ec2039320d72ed95a196e5205b7be96dd0b..ebc2f885fb15251dee86cc1c2d0c33e86166af8c 100644 --- a/client/src/interfaces/ApiRichModels.ts +++ b/client/src/interfaces/ApiRichModels.ts @@ -34,5 +34,5 @@ export interface RichQuestion { total_score: number question_type: QuestionType type_id: number - question_alternatives: QuestionAlternative[] + alternatives: QuestionAlternative[] } diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx index bd854980903ff890a0e58a75c6cbbf15611c03eb..09ef5181b566f919365cb499202ce6ec2e114c24 100644 --- a/client/src/pages/presentationEditor/PresentationEditorPage.tsx +++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx @@ -1,16 +1,17 @@ -import { Button, CircularProgress, Divider, Menu, MenuItem, Typography } from '@material-ui/core' +import { Button, Checkbox, CircularProgress, Divider, Menu, MenuItem, Typography } from '@material-ui/core' import AppBar from '@material-ui/core/AppBar' +import { CheckboxProps } from '@material-ui/core/Checkbox' import CssBaseline from '@material-ui/core/CssBaseline' import Drawer from '@material-ui/core/Drawer' import ListItemText from '@material-ui/core/ListItemText' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles' import AddOutlinedIcon from '@material-ui/icons/AddOutlined' import BuildOutlinedIcon from '@material-ui/icons/BuildOutlined' import CreateOutlinedIcon from '@material-ui/icons/CreateOutlined' import DnsOutlinedIcon from '@material-ui/icons/DnsOutlined' import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined' import axios from 'axios' -import React, { useEffect } from 'react' +import React, { useEffect, useState } from 'react' import { Link, useParams } from 'react-router-dom' import { getCities } from '../../actions/cities' import { getEditorCompetition, setEditorSlideId } from '../../actions/editor' @@ -72,6 +73,12 @@ const useStyles = makeStyles((theme: Theme) => backgroundColor: theme.palette.background.default, padding: theme.spacing(3), }, + alignCheckboxText: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + paddingRight: 20, + }, }) ) @@ -86,7 +93,6 @@ const PresentationEditorPage: React.FC = () => { const activeSlideId = useAppSelector((state) => state.editor.activeSlideId) const competition = useAppSelector((state) => state.editor.competition) const competitionLoading = useAppSelector((state) => state.editor.loading) - // TODO: wait for dispatch to finish useEffect(() => { dispatch(getEditorCompetition(id)) dispatch(getCities()) @@ -134,18 +140,31 @@ const PresentationEditorPage: React.FC = () => { } const renderSlideIcon = (slide: RichSlide) => { - switch (slide.questions && slide.questions[0].type_id) { - case 0: - return <InfoOutlinedIcon></InfoOutlinedIcon> // information slide - case 1: - return <CreateOutlinedIcon></CreateOutlinedIcon> // text question - case 2: - return <BuildOutlinedIcon></BuildOutlinedIcon> // practical qustion - case 3: - return <DnsOutlinedIcon></DnsOutlinedIcon> // multiple choice question + if (slide.questions && slide.questions[0] && slide.questions[0].type_id) { + switch (slide.questions[0].type_id) { + case 1: + return <CreateOutlinedIcon /> // text question + case 2: + return <BuildOutlinedIcon /> // practical qustion + case 3: + return <DnsOutlinedIcon /> // multiple choice question + } + } else { + return <InfoOutlinedIcon /> // information slide } } + const GreenCheckbox = withStyles({ + root: { + color: '#FFFFFF', + '&$checked': { + color: '#FFFFFF', + }, + }, + checked: {}, + })((props: CheckboxProps) => <Checkbox color="default" {...props} />) + const [checkbox, setCheckbox] = useState(false) + return ( <PresentationEditorContainer> <CssBaseline /> @@ -157,7 +176,12 @@ const PresentationEditorPage: React.FC = () => { <Typography variant="h6" noWrap> {competition.name} </Typography> + <ViewButtonGroup> + <GreenCheckbox checked={checkbox} onChange={(event) => setCheckbox(event.target.checked)} /> + <Typography className={classes.alignCheckboxText} variant="button"> + Applicera ändringar på samtliga vyer + </Typography> <ViewButton variant="contained" color="secondary"> Åskådarvy </ViewButton> diff --git a/client/src/pages/presentationEditor/components/CompetitionSettings.tsx b/client/src/pages/presentationEditor/components/CompetitionSettings.tsx index b0834e35690eea67f620d1ab60fd938c8e89ef0b..75d418403d7ec51e13563adf3c9afcf2ef15152f 100644 --- a/client/src/pages/presentationEditor/components/CompetitionSettings.tsx +++ b/client/src/pages/presentationEditor/components/CompetitionSettings.tsx @@ -1,5 +1,10 @@ import { Button, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, Divider, FormControl, InputLabel, @@ -9,11 +14,12 @@ import { MenuItem, Select, TextField, + Typography, } from '@material-ui/core' import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' import CloseIcon from '@material-ui/icons/Close' import axios from 'axios' -import React from 'react' +import React, { useState } from 'react' import { useParams } from 'react-router-dom' import { getEditorCompetition } from '../../../actions/editor' import { useAppDispatch, useAppSelector } from '../../../hooks' @@ -35,7 +41,6 @@ const useStyles = makeStyles((theme: Theme) => }, textCenter: { textAlign: 'center', - background: 'white', }, center: { display: 'flex', @@ -52,6 +57,12 @@ const useStyles = makeStyles((theme: Theme) => width: '87%', background: 'white', }, + addButtons: { + padding: 5, + }, + panelList: { + padding: 0, + }, }) ) @@ -73,15 +84,6 @@ const CompetitionSettings: React.FC = () => { .catch(console.log) } - const handleClick = async (tid: number) => { - await axios - .delete(`/competitions/${id}/teams/${tid}`) - .then(() => { - dispatch(getEditorCompetition(id)) - }) - .catch(console.log) - } - const cities = useAppSelector((state) => state.cities.cities) const updateCompetitionCity = async (city: City) => { await axios @@ -100,6 +102,36 @@ const CompetitionSettings: React.FC = () => { }) } + const removeTeam = async (tid: number) => { + await axios + .delete(`/competitions/${id}/teams/${tid}`) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + const addTeam = async () => { + setAddTeamOpen(false) + await axios + .post(`/competitions/${id}/teams`, { name: selectedTeamName }) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + // For "add team" dialog + const [addTeamOpen, setAddTeamOpen] = useState(false) + const openAddTeam = () => { + setAddTeamOpen(true) + } + const closeAddTeam = () => { + setAddTeamOpen(false) + } + let selectedTeamName = '' + const updateSelectedTeamName = (event: React.ChangeEvent<{ value: string }>) => { + selectedTeamName = event.target.value + } + return ( <div className={classes.textInputContainer}> <form noValidate autoComplete="off"> @@ -113,8 +145,7 @@ const CompetitionSettings: React.FC = () => { /> <Divider /> <FormControl variant="outlined" className={classes.dropDown}> - <InputLabel id="region-selection-label">Region</InputLabel> - {/*TODO: fixa så cities laddar in i statet likt i CompetitionManager*/} + <InputLabel>Region</InputLabel> <Select value={cities.find((city) => city.id === competition.city_id)?.name || ''} label="Region" @@ -129,7 +160,7 @@ const CompetitionSettings: React.FC = () => { </FormControl> </form> - <List> + <List className={classes.panelList}> <ListItem> <ListItemText className={classes.textCenter} primary="Lag" /> </ListItem> @@ -138,13 +169,31 @@ const CompetitionSettings: React.FC = () => { <div key={team.id}> <ListItem divider button> <ListItemText primary={team.name} /> - <CloseIcon onClick={() => handleClick(team.id)} /> + <CloseIcon onClick={() => removeTeam(team.id)} /> </ListItem> </div> ))} - <ListItem className={classes.center} button> - <Button>Lägg till lag</Button> + + <ListItem className={classes.center} button onClick={openAddTeam}> + <Typography className={classes.addButtons} variant="button"> + Lägg till lag + </Typography> </ListItem> + <Dialog open={addTeamOpen} onClose={closeAddTeam}> + <DialogTitle className={classes.center}>Lägg till lag</DialogTitle> + <DialogContent> + <DialogContentText>Skriv namnet på laget och klicka sedan på bekräfta.</DialogContentText> + <TextField autoFocus margin="dense" label="Lagnamn" fullWidth onChange={updateSelectedTeamName} /> + </DialogContent> + <DialogActions> + <Button onClick={closeAddTeam} color="secondary"> + Avbryt + </Button> + <Button onClick={addTeam} color="primary"> + Bekräfta + </Button> + </DialogActions> + </Dialog> </List> <ListItem button> @@ -153,7 +202,7 @@ const CompetitionSettings: React.FC = () => { src="https://i1.wp.com/stickoutmedia.se/wp-content/uploads/2021/01/placeholder-3.png?ssl=1" className={classes.importedImage} /> - <ListItemText className={classes.textCenter} primary="Välj bakgrundsbild ..." /> + <ListItemText className={classes.textCenter}>Välj bakgrundsbild ...</ListItemText> </ListItem> </div> ) diff --git a/client/src/pages/presentationEditor/components/SlideSettings.tsx b/client/src/pages/presentationEditor/components/SlideSettings.tsx index c61d478ebeb37398a6b443226e29aacb032fbcdd..e59586bbb6d346b11d7a6201c8029cd0f824771b 100644 --- a/client/src/pages/presentationEditor/components/SlideSettings.tsx +++ b/client/src/pages/presentationEditor/components/SlideSettings.tsx @@ -1,6 +1,11 @@ import { Button, Checkbox, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, FormControl, InputLabel, List, @@ -9,18 +14,18 @@ import { MenuItem, Select, TextField, + Typography, } from '@material-ui/core' import { CheckboxProps } from '@material-ui/core/Checkbox' import { green, grey } from '@material-ui/core/colors' import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles' import CloseIcon from '@material-ui/icons/Close' -import MoreHorizOutlinedIcon from '@material-ui/icons/MoreHorizOutlined' import axios from 'axios' -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import { getEditorCompetition } from '../../../actions/editor' import { useAppDispatch, useAppSelector } from '../../../hooks' -import { TextComponent } from '../../../interfaces/ApiModels' +import { QuestionAlternative, TextComponent } from '../../../interfaces/ApiModels' import { HiddenInput } from './styled' const useStyles = makeStyles((theme: Theme) => @@ -39,7 +44,6 @@ const useStyles = makeStyles((theme: Theme) => }, textCenter: { textAlign: 'center', - background: 'white', }, center: { display: 'flex', @@ -50,6 +54,7 @@ const useStyles = makeStyles((theme: Theme) => margin: theme.spacing(2), width: '87%', background: 'white', + padding: 0, }, clickableIcon: { cursor: 'pointer', @@ -63,6 +68,16 @@ const useStyles = makeStyles((theme: Theme) => whiteBackground: { background: 'white', }, + addButtons: { + padding: 5, + }, + panelList: { + padding: 0, + }, + addImageButton: { + padding: 5, + cursor: 'pointer', + }, }) ) @@ -75,23 +90,22 @@ const SlideSettings: React.FC = () => { const { id }: CompetitionParams = useParams() const dispatch = useAppDispatch() const competition = useAppSelector((state) => state.editor.competition) - let currentSlide = competition.slides[0] - // Init currentSlide if slides are not in order - for (const slide of competition.slides) { - if (slide.order === 1) { - currentSlide = slide - break - } - } + const activeSlideId = useAppSelector((state) => state.editor.activeSlideId) + const activeSlide = useAppSelector((state) => + state.editor.competition.slides.find((slide) => slide && slide.id === state.editor.activeSlideId) + ) - const handleCloseAnswerClick = async (alternative: number) => { - await axios - // TODO: implementera API för att kunnata bort svarsalternativ - .delete(`/competitions/${id}/slide/question/alternative/${alternative}`) - .then(() => { - dispatch(getEditorCompetition(id)) - }) - .catch(console.log) + const handleCloseAnswerClick = async (alternative_id: number) => { + if (activeSlide && activeSlide.questions[0]) { + await axios + .delete( + `/competitions/${id}/slides/${activeSlideId}/questions/${activeSlide?.questions[0].id}/alternatives/${alternative_id}` + ) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } } const texts = useAppSelector( @@ -110,25 +124,97 @@ const SlideSettings: React.FC = () => { } const [pictures, setPictures] = useState(pictureList) - const updateSlideType = async (event: React.ChangeEvent<{ value: unknown }>) => { - await axios - // TODO: implementera API för att kunna ändra i questions->type_id - .put(`/competitions/${id}/slides/${currentSlide?.id}`, { type_id: event.target.value }) - .then(() => { - dispatch(getEditorCompetition(id)) - }) - .catch(console.log) + const updateSlideType = async () => { + closeSlideTypeDialog() + if (activeSlide) { + if (activeSlide.questions[0] && activeSlide.questions[0].type_id !== selectedSlideType) { + if (selectedSlideType === 0) { + // Change slide type from a question type to information + await axios + .delete(`/competitions/${id}/slides/${activeSlide.order}/questions/${activeSlide.questions[0].id}`) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } else { + // Change slide type from question type to another question type + await axios + .delete(`/competitions/${id}/slides/${activeSlide.order}/questions/${activeSlide.questions[0].id}`) + .catch(console.log) + await axios + .post(`/competitions/${id}/slides/${activeSlide.order}/questions`, { + name: 'Ny fråga', + total_score: 0, + type_id: selectedSlideType, + slide_id: activeSlide.id, + }) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + } else if (selectedSlideType !== 0) { + // Change slide type from information to a question type + await axios + .post(`/competitions/${id}/slides/${activeSlide.order}/questions`, { + name: 'Ny fråga', + total_score: 0, + type_id: selectedSlideType, + slide_id: activeSlide.id, + }) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + } } - const updateAlternativeValue = async (event: React.ChangeEvent<HTMLInputElement>) => { - // Wheter the alternative is true or false - await axios - // TODO: implementera API för att kunna ändra i alternatives->value - .put(`/competitions/${id}/slides/${currentSlide?.id}`, { value: event.target.value }) - .then(() => { - dispatch(getEditorCompetition(id)) - }) - .catch(console.log) + const updateAlternativeValue = async (alternative: QuestionAlternative) => { + if (activeSlide && activeSlide.questions[0]) { + let newValue: number + if (alternative.value === 0) { + newValue = 1 + } else newValue = 0 + console.log('newValue: ' + newValue) + await axios + .put( + `/competitions/${id}/slides/${activeSlide?.id}/questions/${activeSlide?.questions[0].id}/alternatives/${alternative.id}`, + { value: newValue } + ) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + } + + const updateAlternativeText = async (alternative_id: number, newText: string) => { + if (activeSlide && activeSlide.questions[0]) { + await axios + .put( + `/competitions/${id}/slides/${activeSlide?.id}/questions/${activeSlide?.questions[0].id}/alternatives/${alternative_id}`, + { text: newText } + ) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + } + + const addAlternative = async () => { + if (activeSlide && activeSlide.questions[0]) { + await axios + .post( + `/competitions/${id}/slides/${activeSlide?.order}/questions/${activeSlide?.questions[0].id}/alternatives`, + { text: '', value: 0 } + ) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } } const handleFileSelected = (e: React.ChangeEvent<HTMLInputElement>): void => { @@ -163,27 +249,86 @@ const SlideSettings: React.FC = () => { checked: {}, })((props: CheckboxProps) => <Checkbox color="default" {...props} />) + const updateTimer = async (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => { + setTimer(+event.target.value) + if (activeSlide) { + await axios + .put(`/competitions/${id}/slides/${activeSlide.order}`, { timer: event.target.value }) + .then(() => { + dispatch(getEditorCompetition(id)) + }) + .catch(console.log) + } + } + const [timer, setTimer] = useState<number | undefined>(0) + useEffect(() => { + setTimer(activeSlide?.timer) + }, [activeSlide]) + + // For "slide type" dialog + const [selectedSlideType, setSelectedSlideType] = useState(0) + const [slideTypeDialog, setSlideTypeDialog] = useState(false) + const openSlideTypeDialog = (type_id: number) => { + setSelectedSlideType(type_id) + setSlideTypeDialog(true) + } + const closeSlideTypeDialog = () => { + setSlideTypeDialog(false) + } + + const numberToBool = (num: number) => { + if (num === 0) return false + else return true + } + return ( <div className={classes.textInputContainer}> <div className={classes.whiteBackground}> <FormControl variant="outlined" className={classes.dropDown}> - <InputLabel id="slide-type-selection-label">Sidtyp</InputLabel> - <Select value={currentSlide?.questions[0].type_id || 0} label="Sidtyp" onChange={updateSlideType}> + <InputLabel>Sidtyp</InputLabel> + <Select value={activeSlide?.questions[0]?.type_id || 0} label="Sidtyp" className={classes.panelList}> <MenuItem value={0}> - <Button>Informationssida</Button> + <Typography variant="button" onClick={() => openSlideTypeDialog(0)}> + Informationssida + </Typography> </MenuItem> <MenuItem value={1}> - <Button>Skriftlig fråga</Button> + <Typography variant="button" onClick={() => openSlideTypeDialog(1)}> + Skriftlig fråga + </Typography> </MenuItem> <MenuItem value={2}> - <Button>Praktisk fråga</Button> + <Typography variant="button" onClick={() => openSlideTypeDialog(2)}> + Praktisk fråga + </Typography> </MenuItem> <MenuItem value={3}> - <Button>Flervalsfråga</Button> + <Typography variant="button" onClick={() => openSlideTypeDialog(3)}> + Flervalsfråga + </Typography> </MenuItem> </Select> </FormControl> </div> + <Dialog open={slideTypeDialog} onClose={closeSlideTypeDialog}> + <DialogTitle className={classes.center} color="secondary"> + Varning! + </DialogTitle> + <DialogContent> + <DialogContentText> + Om du ändrar sidtypen kommer eventuella frågeinställningar gå förlorade. Det inkluderar: frågans namn, poäng + och svarsalternativ.{' '} + </DialogContentText> + </DialogContent> + <DialogActions> + <Button onClick={closeSlideTypeDialog} color="secondary"> + Avbryt + </Button> + <Button onClick={updateSlideType} color="primary"> + Bekräfta + </Button> + </DialogActions> + </Dialog> <ListItem> <TextField @@ -193,11 +338,13 @@ const SlideSettings: React.FC = () => { helperText="Lämna blank för att inte använda timerfunktionen" label="Timer" type="number" - value={currentSlide?.timer} + defaultValue={activeSlide?.timer || 0} + onChange={updateTimer} + value={timer} /> </ListItem> - <List> + <List className={classes.panelList}> <ListItem divider> <ListItemText className={classes.textCenter} @@ -205,30 +352,32 @@ const SlideSettings: React.FC = () => { secondary="(Fyll i rutan höger om textfältet för att markera korrekt svar)" /> </ListItem> - {currentSlide && - currentSlide.questions[0] && - currentSlide.questions[0].question_alternatives && - currentSlide.questions[0].question_alternatives.map((alt) => ( + {activeSlide && + activeSlide.questions[0] && + activeSlide.questions[0].alternatives && + activeSlide.questions[0].alternatives.map((alt) => ( <div key={alt.id}> <ListItem divider> <TextField className={classes.textInput} id="outlined-basic" - label={`Svar ${alt.id}`} - value={alt.text} + defaultValue={alt.text} + onChange={(event) => updateAlternativeText(alt.id, event.target.value)} variant="outlined" /> - <GreenCheckbox checked={alt.value} onChange={updateAlternativeValue} /> + <GreenCheckbox checked={numberToBool(alt.value)} onChange={() => updateAlternativeValue(alt)} /> <CloseIcon className={classes.clickableIcon} onClick={() => handleCloseAnswerClick(alt.id)} /> </ListItem> </div> ))} - <ListItem className={classes.center} button> - <Button>Lägg till svarsalternativ</Button> + <ListItem className={classes.center} button onClick={addAlternative}> + <Typography className={classes.addButtons} variant="button"> + Lägg till svarsalternativ + </Typography> </ListItem> </List> - <List> + <List className={classes.panelList}> <ListItem divider> <ListItemText className={classes.textCenter} primary="Text" /> </ListItem> @@ -237,17 +386,18 @@ const SlideSettings: React.FC = () => { <div key={text.id}> <ListItem divider> <TextField className={classes.textInput} label={text.data.text} variant="outlined" /> - <MoreHorizOutlinedIcon className={classes.clickableIcon} /> <CloseIcon className={classes.clickableIcon} /> </ListItem> </div> ))} <ListItem className={classes.center} button onClick={handleAddText}> - <Button>Lägg till text</Button> + <Typography className={classes.addButtons} variant="button"> + Lägg till text + </Typography> </ListItem> </List> - <List> + <List className={classes.panelList}> <ListItem divider> <ListItemText className={classes.textCenter} primary="Bilder" /> </ListItem> @@ -267,8 +417,8 @@ const SlideSettings: React.FC = () => { <ListItem className={classes.center} button> <HiddenInput accept="image/*" id="contained-button-file" multiple type="file" onChange={handleFileSelected} /> - <label htmlFor="contained-button-file"> - <Button component="span">Lägg till bild</Button> + <label className={classes.addImageButton} htmlFor="contained-button-file"> + <Typography variant="button">Lägg till bild</Typography> </label> </ListItem> </List> diff --git a/client/src/reducers/editorReducer.ts b/client/src/reducers/editorReducer.ts index 81b10c32d206d8870a7cbee38c632991330b7149..20d0b42885b4d3ebeffbca9ead97b1eb0ddc2fad 100644 --- a/client/src/reducers/editorReducer.ts +++ b/client/src/reducers/editorReducer.ts @@ -17,7 +17,7 @@ const initialState: EditorState = { slides: [], teams: [], }, - activeSlideId: 0, + activeSlideId: -1, loading: true, } @@ -25,8 +25,8 @@ export default function (state = initialState, action: AnyAction) { switch (action.type) { case Types.SET_EDITOR_COMPETITION: return { + ...state, competition: action.payload as RichCompetition, - activeSlideId: action.payload.slides[0].id as number, loading: false, } case Types.SET_EDITOR_SLIDE_ID: diff --git a/server/app/apis/slides.py b/server/app/apis/slides.py index 4720fd4468f3636ab3058278bafe001e184da639..93250b3a8429bd917d9080da65b1eec2e05e8098 100644 --- a/server/app/apis/slides.py +++ b/server/app/apis/slides.py @@ -24,7 +24,6 @@ class SlidesList(Resource): def post(self, CID): item_comp = dbc.get.one(Competition, CID) item_slide = dbc.add.slide(item_comp) - dbc.add.question(f"Fråga {item_slide.order + 1}", 10, 0, item_slide) dbc.utils.refresh(item_comp) return list_response(list_schema.dump(item_comp.slides)) diff --git a/server/populate.py b/server/populate.py index 609193ba0dc5e5a19e3425fa25144d4aabe688d6..f371018423dcb4852a3e18a7b8fb227691d50cbe 100644 --- a/server/populate.py +++ b/server/populate.py @@ -82,13 +82,12 @@ def _add_items(): h = random.randrange(150, 400) dbc.add.component(1, item_slide, {"text": f"hej{k}"}, x, y, w, h) - # TODO: Remove comments when slide without questions is fixed - # item_slide = dbc.add.slide(item_comp) - # item_slide.title = f"Slide {len(item_comp.slides)}" - # item_slide.body = f"Body {len(item_comp.slides)}" - # item_slide.timer = 100 + j - # # item_slide.settings = "{}" - # dbc.utils.commit_and_refresh(item_slide) + item_slide = dbc.add.slide(item_comp) + item_slide.title = f"Slide {len(item_comp.slides)}" + item_slide.body = f"Body {len(item_comp.slides)}" + item_slide.timer = 100 + j + # item_slide.settings = "{}" + dbc.utils.commit_and_refresh(item_slide) # Add teams for name in teams: