Skip to content
Snippets Groups Projects
Commit 1d40817d authored by Emil Wahlqvist's avatar Emil Wahlqvist
Browse files

Resolve "Minor editor fixes/adds"

parent cb9aa8f4
No related branches found
No related tags found
1 merge request!86Resolve "Minor editor fixes/adds"
Pipeline #41765 passed with warnings
client/public/t8-circled.png

42.4 KiB

import axios from 'axios' import axios from 'axios'
import { AppDispatch } from './../store' import { AppDispatch, RootState } from './../store'
import Types from './types' import Types from './types'
export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch) => { export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch, getState: () => RootState) => {
await axios await axios
.get(`/competitions/${id}`) .get(`/competitions/${id}`)
.then((res) => { .then((res) => {
...@@ -10,6 +10,9 @@ export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch ...@@ -10,6 +10,9 @@ export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch
type: Types.SET_EDITOR_COMPETITION, type: Types.SET_EDITOR_COMPETITION,
payload: res.data, payload: res.data,
}) })
if (getState().editor.activeSlideId === -1 && res.data.slides[0]) {
setEditorSlideId(res.data.slides[0].id)(dispatch)
}
}) })
.catch((err) => { .catch((err) => {
console.log(err) console.log(err)
......
...@@ -61,7 +61,7 @@ export interface Question extends NameID { ...@@ -61,7 +61,7 @@ export interface Question extends NameID {
export interface QuestionAlternative { export interface QuestionAlternative {
id: number id: number
text: string text: string
value: boolean value: number
question_id: number question_id: number
} }
export interface QuestionAnswer { export interface QuestionAnswer {
......
...@@ -34,5 +34,5 @@ export interface RichQuestion { ...@@ -34,5 +34,5 @@ export interface RichQuestion {
total_score: number total_score: number
question_type: QuestionType question_type: QuestionType
type_id: number type_id: number
question_alternatives: QuestionAlternative[] alternatives: QuestionAlternative[]
} }
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 AppBar from '@material-ui/core/AppBar'
import { CheckboxProps } from '@material-ui/core/Checkbox'
import CssBaseline from '@material-ui/core/CssBaseline' import CssBaseline from '@material-ui/core/CssBaseline'
import Drawer from '@material-ui/core/Drawer' import Drawer from '@material-ui/core/Drawer'
import ListItemText from '@material-ui/core/ListItemText' 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 AddOutlinedIcon from '@material-ui/icons/AddOutlined'
import BuildOutlinedIcon from '@material-ui/icons/BuildOutlined' import BuildOutlinedIcon from '@material-ui/icons/BuildOutlined'
import CreateOutlinedIcon from '@material-ui/icons/CreateOutlined' import CreateOutlinedIcon from '@material-ui/icons/CreateOutlined'
import DnsOutlinedIcon from '@material-ui/icons/DnsOutlined' import DnsOutlinedIcon from '@material-ui/icons/DnsOutlined'
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined' import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'
import axios from 'axios' import axios from 'axios'
import React, { useEffect } from 'react' import React, { useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom' import { Link, useParams } from 'react-router-dom'
import { getCities } from '../../actions/cities' import { getCities } from '../../actions/cities'
import { getEditorCompetition, setEditorSlideId } from '../../actions/editor' import { getEditorCompetition, setEditorSlideId } from '../../actions/editor'
...@@ -72,6 +73,12 @@ const useStyles = makeStyles((theme: Theme) => ...@@ -72,6 +73,12 @@ const useStyles = makeStyles((theme: Theme) =>
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
padding: theme.spacing(3), padding: theme.spacing(3),
}, },
alignCheckboxText: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
paddingRight: 20,
},
}) })
) )
...@@ -86,7 +93,6 @@ const PresentationEditorPage: React.FC = () => { ...@@ -86,7 +93,6 @@ const PresentationEditorPage: React.FC = () => {
const activeSlideId = useAppSelector((state) => state.editor.activeSlideId) const activeSlideId = useAppSelector((state) => state.editor.activeSlideId)
const competition = useAppSelector((state) => state.editor.competition) const competition = useAppSelector((state) => state.editor.competition)
const competitionLoading = useAppSelector((state) => state.editor.loading) const competitionLoading = useAppSelector((state) => state.editor.loading)
// TODO: wait for dispatch to finish
useEffect(() => { useEffect(() => {
dispatch(getEditorCompetition(id)) dispatch(getEditorCompetition(id))
dispatch(getCities()) dispatch(getCities())
...@@ -134,18 +140,31 @@ const PresentationEditorPage: React.FC = () => { ...@@ -134,18 +140,31 @@ const PresentationEditorPage: React.FC = () => {
} }
const renderSlideIcon = (slide: RichSlide) => { const renderSlideIcon = (slide: RichSlide) => {
switch (slide.questions && slide.questions[0].type_id) { if (slide.questions && slide.questions[0] && slide.questions[0].type_id) {
case 0: switch (slide.questions[0].type_id) {
return <InfoOutlinedIcon></InfoOutlinedIcon> // information slide case 1:
case 1: return <CreateOutlinedIcon /> // text question
return <CreateOutlinedIcon></CreateOutlinedIcon> // text question case 2:
case 2: return <BuildOutlinedIcon /> // practical qustion
return <BuildOutlinedIcon></BuildOutlinedIcon> // practical qustion case 3:
case 3: return <DnsOutlinedIcon /> // multiple choice question
return <DnsOutlinedIcon></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 ( return (
<PresentationEditorContainer> <PresentationEditorContainer>
<CssBaseline /> <CssBaseline />
...@@ -157,7 +176,12 @@ const PresentationEditorPage: React.FC = () => { ...@@ -157,7 +176,12 @@ const PresentationEditorPage: React.FC = () => {
<Typography variant="h6" noWrap> <Typography variant="h6" noWrap>
{competition.name} {competition.name}
</Typography> </Typography>
<ViewButtonGroup> <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"> <ViewButton variant="contained" color="secondary">
Åskådarvy Åskådarvy
</ViewButton> </ViewButton>
......
import { import {
Button, Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Divider, Divider,
FormControl, FormControl,
InputLabel, InputLabel,
...@@ -9,11 +14,12 @@ import { ...@@ -9,11 +14,12 @@ import {
MenuItem, MenuItem,
Select, Select,
TextField, TextField,
Typography,
} from '@material-ui/core' } from '@material-ui/core'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import CloseIcon from '@material-ui/icons/Close' import CloseIcon from '@material-ui/icons/Close'
import axios from 'axios' import axios from 'axios'
import React from 'react' import React, { useState } from 'react'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { getEditorCompetition } from '../../../actions/editor' import { getEditorCompetition } from '../../../actions/editor'
import { useAppDispatch, useAppSelector } from '../../../hooks' import { useAppDispatch, useAppSelector } from '../../../hooks'
...@@ -35,7 +41,6 @@ const useStyles = makeStyles((theme: Theme) => ...@@ -35,7 +41,6 @@ const useStyles = makeStyles((theme: Theme) =>
}, },
textCenter: { textCenter: {
textAlign: 'center', textAlign: 'center',
background: 'white',
}, },
center: { center: {
display: 'flex', display: 'flex',
...@@ -52,6 +57,12 @@ const useStyles = makeStyles((theme: Theme) => ...@@ -52,6 +57,12 @@ const useStyles = makeStyles((theme: Theme) =>
width: '87%', width: '87%',
background: 'white', background: 'white',
}, },
addButtons: {
padding: 5,
},
panelList: {
padding: 0,
},
}) })
) )
...@@ -73,15 +84,6 @@ const CompetitionSettings: React.FC = () => { ...@@ -73,15 +84,6 @@ const CompetitionSettings: React.FC = () => {
.catch(console.log) .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 cities = useAppSelector((state) => state.cities.cities)
const updateCompetitionCity = async (city: City) => { const updateCompetitionCity = async (city: City) => {
await axios await axios
...@@ -100,6 +102,36 @@ const CompetitionSettings: React.FC = () => { ...@@ -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 ( return (
<div className={classes.textInputContainer}> <div className={classes.textInputContainer}>
<form noValidate autoComplete="off"> <form noValidate autoComplete="off">
...@@ -113,8 +145,7 @@ const CompetitionSettings: React.FC = () => { ...@@ -113,8 +145,7 @@ const CompetitionSettings: React.FC = () => {
/> />
<Divider /> <Divider />
<FormControl variant="outlined" className={classes.dropDown}> <FormControl variant="outlined" className={classes.dropDown}>
<InputLabel id="region-selection-label">Region</InputLabel> <InputLabel>Region</InputLabel>
{/*TODO: fixa så cities laddar in i statet likt i CompetitionManager*/}
<Select <Select
value={cities.find((city) => city.id === competition.city_id)?.name || ''} value={cities.find((city) => city.id === competition.city_id)?.name || ''}
label="Region" label="Region"
...@@ -129,7 +160,7 @@ const CompetitionSettings: React.FC = () => { ...@@ -129,7 +160,7 @@ const CompetitionSettings: React.FC = () => {
</FormControl> </FormControl>
</form> </form>
<List> <List className={classes.panelList}>
<ListItem> <ListItem>
<ListItemText className={classes.textCenter} primary="Lag" /> <ListItemText className={classes.textCenter} primary="Lag" />
</ListItem> </ListItem>
...@@ -138,13 +169,31 @@ const CompetitionSettings: React.FC = () => { ...@@ -138,13 +169,31 @@ const CompetitionSettings: React.FC = () => {
<div key={team.id}> <div key={team.id}>
<ListItem divider button> <ListItem divider button>
<ListItemText primary={team.name} /> <ListItemText primary={team.name} />
<CloseIcon onClick={() => handleClick(team.id)} /> <CloseIcon onClick={() => removeTeam(team.id)} />
</ListItem> </ListItem>
</div> </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> </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> </List>
<ListItem button> <ListItem button>
...@@ -153,7 +202,7 @@ const CompetitionSettings: React.FC = () => { ...@@ -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" src="https://i1.wp.com/stickoutmedia.se/wp-content/uploads/2021/01/placeholder-3.png?ssl=1"
className={classes.importedImage} className={classes.importedImage}
/> />
<ListItemText className={classes.textCenter} primary="Välj bakgrundsbild ..." /> <ListItemText className={classes.textCenter}>Välj bakgrundsbild ...</ListItemText>
</ListItem> </ListItem>
</div> </div>
) )
......
import { import {
Button, Button,
Checkbox, Checkbox,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
FormControl, FormControl,
InputLabel, InputLabel,
List, List,
...@@ -9,18 +14,18 @@ import { ...@@ -9,18 +14,18 @@ import {
MenuItem, MenuItem,
Select, Select,
TextField, TextField,
Typography,
} from '@material-ui/core' } from '@material-ui/core'
import { CheckboxProps } from '@material-ui/core/Checkbox' import { CheckboxProps } from '@material-ui/core/Checkbox'
import { green, grey } from '@material-ui/core/colors' import { green, grey } from '@material-ui/core/colors'
import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles' import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles'
import CloseIcon from '@material-ui/icons/Close' import CloseIcon from '@material-ui/icons/Close'
import MoreHorizOutlinedIcon from '@material-ui/icons/MoreHorizOutlined'
import axios from 'axios' import axios from 'axios'
import React, { useState } from 'react' import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import { getEditorCompetition } from '../../../actions/editor' import { getEditorCompetition } from '../../../actions/editor'
import { useAppDispatch, useAppSelector } from '../../../hooks' import { useAppDispatch, useAppSelector } from '../../../hooks'
import { TextComponent } from '../../../interfaces/ApiModels' import { QuestionAlternative, TextComponent } from '../../../interfaces/ApiModels'
import { HiddenInput } from './styled' import { HiddenInput } from './styled'
const useStyles = makeStyles((theme: Theme) => const useStyles = makeStyles((theme: Theme) =>
...@@ -39,7 +44,6 @@ const useStyles = makeStyles((theme: Theme) => ...@@ -39,7 +44,6 @@ const useStyles = makeStyles((theme: Theme) =>
}, },
textCenter: { textCenter: {
textAlign: 'center', textAlign: 'center',
background: 'white',
}, },
center: { center: {
display: 'flex', display: 'flex',
...@@ -50,6 +54,7 @@ const useStyles = makeStyles((theme: Theme) => ...@@ -50,6 +54,7 @@ const useStyles = makeStyles((theme: Theme) =>
margin: theme.spacing(2), margin: theme.spacing(2),
width: '87%', width: '87%',
background: 'white', background: 'white',
padding: 0,
}, },
clickableIcon: { clickableIcon: {
cursor: 'pointer', cursor: 'pointer',
...@@ -63,6 +68,16 @@ const useStyles = makeStyles((theme: Theme) => ...@@ -63,6 +68,16 @@ const useStyles = makeStyles((theme: Theme) =>
whiteBackground: { whiteBackground: {
background: 'white', background: 'white',
}, },
addButtons: {
padding: 5,
},
panelList: {
padding: 0,
},
addImageButton: {
padding: 5,
cursor: 'pointer',
},
}) })
) )
...@@ -75,23 +90,22 @@ const SlideSettings: React.FC = () => { ...@@ -75,23 +90,22 @@ const SlideSettings: React.FC = () => {
const { id }: CompetitionParams = useParams() const { id }: CompetitionParams = useParams()
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const competition = useAppSelector((state) => state.editor.competition) const competition = useAppSelector((state) => state.editor.competition)
let currentSlide = competition.slides[0] const activeSlideId = useAppSelector((state) => state.editor.activeSlideId)
// Init currentSlide if slides are not in order const activeSlide = useAppSelector((state) =>
for (const slide of competition.slides) { state.editor.competition.slides.find((slide) => slide && slide.id === state.editor.activeSlideId)
if (slide.order === 1) { )
currentSlide = slide
break
}
}
const handleCloseAnswerClick = async (alternative: number) => { const handleCloseAnswerClick = async (alternative_id: number) => {
await axios if (activeSlide && activeSlide.questions[0]) {
// TODO: implementera API för att kunnata bort svarsalternativ await axios
.delete(`/competitions/${id}/slide/question/alternative/${alternative}`) .delete(
.then(() => { `/competitions/${id}/slides/${activeSlideId}/questions/${activeSlide?.questions[0].id}/alternatives/${alternative_id}`
dispatch(getEditorCompetition(id)) )
}) .then(() => {
.catch(console.log) dispatch(getEditorCompetition(id))
})
.catch(console.log)
}
} }
const texts = useAppSelector( const texts = useAppSelector(
...@@ -110,25 +124,97 @@ const SlideSettings: React.FC = () => { ...@@ -110,25 +124,97 @@ const SlideSettings: React.FC = () => {
} }
const [pictures, setPictures] = useState(pictureList) const [pictures, setPictures] = useState(pictureList)
const updateSlideType = async (event: React.ChangeEvent<{ value: unknown }>) => { const updateSlideType = async () => {
await axios closeSlideTypeDialog()
// TODO: implementera API för att kunna ändra i questions->type_id if (activeSlide) {
.put(`/competitions/${id}/slides/${currentSlide?.id}`, { type_id: event.target.value }) if (activeSlide.questions[0] && activeSlide.questions[0].type_id !== selectedSlideType) {
.then(() => { if (selectedSlideType === 0) {
dispatch(getEditorCompetition(id)) // Change slide type from a question type to information
}) await axios
.catch(console.log) .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>) => { const updateAlternativeValue = async (alternative: QuestionAlternative) => {
// Wheter the alternative is true or false if (activeSlide && activeSlide.questions[0]) {
await axios let newValue: number
// TODO: implementera API för att kunna ändra i alternatives->value if (alternative.value === 0) {
.put(`/competitions/${id}/slides/${currentSlide?.id}`, { value: event.target.value }) newValue = 1
.then(() => { } else newValue = 0
dispatch(getEditorCompetition(id)) console.log('newValue: ' + newValue)
}) await axios
.catch(console.log) .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 => { const handleFileSelected = (e: React.ChangeEvent<HTMLInputElement>): void => {
...@@ -163,27 +249,86 @@ const SlideSettings: React.FC = () => { ...@@ -163,27 +249,86 @@ const SlideSettings: React.FC = () => {
checked: {}, checked: {},
})((props: CheckboxProps) => <Checkbox color="default" {...props} />) })((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 ( return (
<div className={classes.textInputContainer}> <div className={classes.textInputContainer}>
<div className={classes.whiteBackground}> <div className={classes.whiteBackground}>
<FormControl variant="outlined" className={classes.dropDown}> <FormControl variant="outlined" className={classes.dropDown}>
<InputLabel id="slide-type-selection-label">Sidtyp</InputLabel> <InputLabel>Sidtyp</InputLabel>
<Select value={currentSlide?.questions[0].type_id || 0} label="Sidtyp" onChange={updateSlideType}> <Select value={activeSlide?.questions[0]?.type_id || 0} label="Sidtyp" className={classes.panelList}>
<MenuItem value={0}> <MenuItem value={0}>
<Button>Informationssida</Button> <Typography variant="button" onClick={() => openSlideTypeDialog(0)}>
Informationssida
</Typography>
</MenuItem> </MenuItem>
<MenuItem value={1}> <MenuItem value={1}>
<Button>Skriftlig fråga</Button> <Typography variant="button" onClick={() => openSlideTypeDialog(1)}>
Skriftlig fråga
</Typography>
</MenuItem> </MenuItem>
<MenuItem value={2}> <MenuItem value={2}>
<Button>Praktisk fråga</Button> <Typography variant="button" onClick={() => openSlideTypeDialog(2)}>
Praktisk fråga
</Typography>
</MenuItem> </MenuItem>
<MenuItem value={3}> <MenuItem value={3}>
<Button>Flervalsfråga</Button> <Typography variant="button" onClick={() => openSlideTypeDialog(3)}>
Flervalsfråga
</Typography>
</MenuItem> </MenuItem>
</Select> </Select>
</FormControl> </FormControl>
</div> </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> <ListItem>
<TextField <TextField
...@@ -193,11 +338,13 @@ const SlideSettings: React.FC = () => { ...@@ -193,11 +338,13 @@ const SlideSettings: React.FC = () => {
helperText="Lämna blank för att inte använda timerfunktionen" helperText="Lämna blank för att inte använda timerfunktionen"
label="Timer" label="Timer"
type="number" type="number"
value={currentSlide?.timer} defaultValue={activeSlide?.timer || 0}
onChange={updateTimer}
value={timer}
/> />
</ListItem> </ListItem>
<List> <List className={classes.panelList}>
<ListItem divider> <ListItem divider>
<ListItemText <ListItemText
className={classes.textCenter} className={classes.textCenter}
...@@ -205,30 +352,32 @@ const SlideSettings: React.FC = () => { ...@@ -205,30 +352,32 @@ const SlideSettings: React.FC = () => {
secondary="(Fyll i rutan höger om textfältet för att markera korrekt svar)" secondary="(Fyll i rutan höger om textfältet för att markera korrekt svar)"
/> />
</ListItem> </ListItem>
{currentSlide && {activeSlide &&
currentSlide.questions[0] && activeSlide.questions[0] &&
currentSlide.questions[0].question_alternatives && activeSlide.questions[0].alternatives &&
currentSlide.questions[0].question_alternatives.map((alt) => ( activeSlide.questions[0].alternatives.map((alt) => (
<div key={alt.id}> <div key={alt.id}>
<ListItem divider> <ListItem divider>
<TextField <TextField
className={classes.textInput} className={classes.textInput}
id="outlined-basic" id="outlined-basic"
label={`Svar ${alt.id}`} defaultValue={alt.text}
value={alt.text} onChange={(event) => updateAlternativeText(alt.id, event.target.value)}
variant="outlined" variant="outlined"
/> />
<GreenCheckbox checked={alt.value} onChange={updateAlternativeValue} /> <GreenCheckbox checked={numberToBool(alt.value)} onChange={() => updateAlternativeValue(alt)} />
<CloseIcon className={classes.clickableIcon} onClick={() => handleCloseAnswerClick(alt.id)} /> <CloseIcon className={classes.clickableIcon} onClick={() => handleCloseAnswerClick(alt.id)} />
</ListItem> </ListItem>
</div> </div>
))} ))}
<ListItem className={classes.center} button> <ListItem className={classes.center} button onClick={addAlternative}>
<Button>Lägg till svarsalternativ</Button> <Typography className={classes.addButtons} variant="button">
Lägg till svarsalternativ
</Typography>
</ListItem> </ListItem>
</List> </List>
<List> <List className={classes.panelList}>
<ListItem divider> <ListItem divider>
<ListItemText className={classes.textCenter} primary="Text" /> <ListItemText className={classes.textCenter} primary="Text" />
</ListItem> </ListItem>
...@@ -237,17 +386,18 @@ const SlideSettings: React.FC = () => { ...@@ -237,17 +386,18 @@ const SlideSettings: React.FC = () => {
<div key={text.id}> <div key={text.id}>
<ListItem divider> <ListItem divider>
<TextField className={classes.textInput} label={text.data.text} variant="outlined" /> <TextField className={classes.textInput} label={text.data.text} variant="outlined" />
<MoreHorizOutlinedIcon className={classes.clickableIcon} />
<CloseIcon className={classes.clickableIcon} /> <CloseIcon className={classes.clickableIcon} />
</ListItem> </ListItem>
</div> </div>
))} ))}
<ListItem className={classes.center} button onClick={handleAddText}> <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> </ListItem>
</List> </List>
<List> <List className={classes.panelList}>
<ListItem divider> <ListItem divider>
<ListItemText className={classes.textCenter} primary="Bilder" /> <ListItemText className={classes.textCenter} primary="Bilder" />
</ListItem> </ListItem>
...@@ -267,8 +417,8 @@ const SlideSettings: React.FC = () => { ...@@ -267,8 +417,8 @@ const SlideSettings: React.FC = () => {
<ListItem className={classes.center} button> <ListItem className={classes.center} button>
<HiddenInput accept="image/*" id="contained-button-file" multiple type="file" onChange={handleFileSelected} /> <HiddenInput accept="image/*" id="contained-button-file" multiple type="file" onChange={handleFileSelected} />
<label htmlFor="contained-button-file"> <label className={classes.addImageButton} htmlFor="contained-button-file">
<Button component="span">Lägg till bild</Button> <Typography variant="button">Lägg till bild</Typography>
</label> </label>
</ListItem> </ListItem>
</List> </List>
......
...@@ -17,7 +17,7 @@ const initialState: EditorState = { ...@@ -17,7 +17,7 @@ const initialState: EditorState = {
slides: [], slides: [],
teams: [], teams: [],
}, },
activeSlideId: 0, activeSlideId: -1,
loading: true, loading: true,
} }
...@@ -25,8 +25,8 @@ export default function (state = initialState, action: AnyAction) { ...@@ -25,8 +25,8 @@ export default function (state = initialState, action: AnyAction) {
switch (action.type) { switch (action.type) {
case Types.SET_EDITOR_COMPETITION: case Types.SET_EDITOR_COMPETITION:
return { return {
...state,
competition: action.payload as RichCompetition, competition: action.payload as RichCompetition,
activeSlideId: action.payload.slides[0].id as number,
loading: false, loading: false,
} }
case Types.SET_EDITOR_SLIDE_ID: case Types.SET_EDITOR_SLIDE_ID:
......
...@@ -24,7 +24,6 @@ class SlidesList(Resource): ...@@ -24,7 +24,6 @@ class SlidesList(Resource):
def post(self, CID): def post(self, CID):
item_comp = dbc.get.one(Competition, CID) item_comp = dbc.get.one(Competition, CID)
item_slide = dbc.add.slide(item_comp) 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) dbc.utils.refresh(item_comp)
return list_response(list_schema.dump(item_comp.slides)) return list_response(list_schema.dump(item_comp.slides))
......
...@@ -82,13 +82,12 @@ def _add_items(): ...@@ -82,13 +82,12 @@ def _add_items():
h = random.randrange(150, 400) h = random.randrange(150, 400)
dbc.add.component(1, item_slide, {"text": f"hej{k}"}, x, y, w, h) 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 = dbc.add.slide(item_comp) item_slide.title = f"Slide {len(item_comp.slides)}"
# item_slide.title = f"Slide {len(item_comp.slides)}" item_slide.body = f"Body {len(item_comp.slides)}"
# item_slide.body = f"Body {len(item_comp.slides)}" item_slide.timer = 100 + j
# item_slide.timer = 100 + j # item_slide.settings = "{}"
# # item_slide.settings = "{}" dbc.utils.commit_and_refresh(item_slide)
# dbc.utils.commit_and_refresh(item_slide)
# Add teams # Add teams
for name in teams: for name in teams:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment