diff --git a/client/src/pages/presentationEditor/components/SlideDisplay.tsx b/client/src/pages/presentationEditor/components/SlideDisplay.tsx index b6505eed2bd3b1e38f8e7b3c07471d683f4a9682..05c87d301047b49ac6ba715072f2f245647a3c8a 100644 --- a/client/src/pages/presentationEditor/components/SlideDisplay.tsx +++ b/client/src/pages/presentationEditor/components/SlideDisplay.tsx @@ -64,7 +64,7 @@ const SlideDisplay = ({ variant, activeViewTypeId, currentSlideId }: SlideDispla {slide?.timer && ( <Card style={{ display: 'flex', alignItems: 'center', padding: 10 }}> <TimerIcon fontSize="large" /> - <Timer variant={variant} /> + <Timer variant={variant} currentSlideId={currentSlideId} /> </Card> )} </SlideDisplayText> diff --git a/client/src/pages/presentationEditor/components/answerComponents/AnswerMatch.tsx b/client/src/pages/presentationEditor/components/answerComponents/AnswerMatch.tsx index 15fabf0e54f7dc65453ee476520e2c4708b98890..bedd621fa5629f87a93176369542f1420222bf98 100644 --- a/client/src/pages/presentationEditor/components/answerComponents/AnswerMatch.tsx +++ b/client/src/pages/presentationEditor/components/answerComponents/AnswerMatch.tsx @@ -70,7 +70,7 @@ const AnswerMatch = ({ variant, activeSlide, competitionId }: AnswerMultipleProp }, [teamId]) const getButtonStyle = () => { - if (!(timer.value === null || (timer.enabled && timer.value))) { + if (activeSlide?.timer !== undefined && !timer.enabled) { return { fill: '#AAAAAA' } // Buttons are light grey if timer is not on } return {} @@ -79,7 +79,7 @@ const AnswerMatch = ({ variant, activeSlide, competitionId }: AnswerMultipleProp const onMove = async (previousIndex: number, resultIndex: number) => { // moved outside the list if (resultIndex < 0 || resultIndex >= sortedAnswers.length || variant !== 'presentation') return - if (!(timer.value === null || (timer.enabled && timer.value))) return + if (activeSlide?.timer !== undefined && !timer.enabled) return const answersCopy = [...sortedAnswers] const [removed] = answersCopy.splice(previousIndex, 1) answersCopy.splice(resultIndex, 0, removed) diff --git a/client/src/pages/presentationEditor/components/answerComponents/AnswerMultiple.tsx b/client/src/pages/presentationEditor/components/answerComponents/AnswerMultiple.tsx index e648845a4c981ee4bae3b4fe44d2c2f4bb468e5a..c687faf00c1b811c793cd88035becec93f638d53 100644 --- a/client/src/pages/presentationEditor/components/answerComponents/AnswerMultiple.tsx +++ b/client/src/pages/presentationEditor/components/answerComponents/AnswerMultiple.tsx @@ -48,7 +48,7 @@ const AnswerMultiple = ({ variant, activeSlide, competitionId }: AnswerMultipleP const updateAnswer = async (alternative: QuestionAlternative, checked: boolean) => { // TODO: fix. Make list of alternatives and delete & post instead of put to allow multiple boxes checked. - if (!(activeSlide && (timer.value === null || (timer.enabled && timer.value)))) { + if (!activeSlide || (activeSlide?.timer !== undefined && !timer.enabled)) { return } const url = `/api/competitions/${competitionId}/teams/${teamId}/answers/question_alternatives/${alternative.id}` @@ -91,7 +91,7 @@ const AnswerMultiple = ({ variant, activeSlide, competitionId }: AnswerMultipleP <div key={alt.id}> <ListItem divider> <GreenCheckbox - disabled={!(timer.value === null || (timer.enabled && timer.value))} + disabled={activeSlide?.timer !== undefined && !timer.enabled} checked={decideChecked(alt)} onChange={(event: any) => updateAnswer(alt, event.target.checked)} /> diff --git a/client/src/pages/presentationEditor/components/answerComponents/AnswerSingle.tsx b/client/src/pages/presentationEditor/components/answerComponents/AnswerSingle.tsx index 29389c44d4c5e56c493c1abf8574fd6bef93638b..70d59c01c4985541f8f503448172998a93dd4a48 100644 --- a/client/src/pages/presentationEditor/components/answerComponents/AnswerSingle.tsx +++ b/client/src/pages/presentationEditor/components/answerComponents/AnswerSingle.tsx @@ -50,7 +50,7 @@ const AnswerSingle = ({ variant, activeSlide, competitionId }: AnswerSingleProps } const updateAnswer = async (alternative: QuestionAlternative) => { - if (!(activeSlide && (timer.value === null || (timer.enabled && timer.value)))) { + if (!activeSlide || (activeSlide?.timer !== undefined && !timer.enabled)) { return } @@ -79,7 +79,7 @@ const AnswerSingle = ({ variant, activeSlide, competitionId }: AnswerSingleProps */ const renderRadioButton = (alt: QuestionAlternative) => { let disabledStyle - if (!(timer.value === null || (timer.enabled && timer.value))) { + if (activeSlide?.timer !== undefined && !timer.enabled) { disabledStyle = { fill: '#AAAAAA' } // Buttons are light grey if timer is not on } if (variant === 'presentation') { diff --git a/client/src/pages/presentationEditor/components/answerComponents/AnswerText.tsx b/client/src/pages/presentationEditor/components/answerComponents/AnswerText.tsx index b7f0d687fbfbe4b112a5c7fac50c72c7277854f6..595462c97ecbc4583754d40cc4f94eeee204e224 100644 --- a/client/src/pages/presentationEditor/components/answerComponents/AnswerText.tsx +++ b/client/src/pages/presentationEditor/components/answerComponents/AnswerText.tsx @@ -39,7 +39,7 @@ const AnswerText = ({ activeSlide, competitionId }: AnswerTextProps) => { setTimerHandle(undefined) } //Only updates answer if the timer is on - if (timer.value === null || (timer.enabled && timer.value)) { + if (activeSlide?.timer !== undefined && !timer.enabled) { //Only updates answer 100ms after last input was made setTimerHandle(window.setTimeout(() => updateAnswer(answer), 100)) } @@ -79,7 +79,7 @@ const AnswerText = ({ activeSlide, competitionId }: AnswerTextProps) => { </ListItem> <ListItem style={{ height: '100%' }}> <TextField - disabled={team === undefined || !(timer.value === null || (timer.enabled && timer.value))} + disabled={team === undefined || (activeSlide?.timer !== undefined && !timer.enabled)} defaultValue={getDefaultString()} style={{ height: '100%' }} variant="outlined" diff --git a/client/src/pages/views/components/Timer.tsx b/client/src/pages/views/components/Timer.tsx index bb65eca40b230acee42ec11d77a842bb52bfd979..5b496325803d8f092178ef39506b704f11ab0443 100644 --- a/client/src/pages/views/components/Timer.tsx +++ b/client/src/pages/views/components/Timer.tsx @@ -4,9 +4,10 @@ import { useAppDispatch, useAppSelector } from '../../../hooks' type TimerProps = { variant: 'editor' | 'presentation' + currentSlideId?: number } -const Timer = ({ variant }: TimerProps) => { +const Timer = ({ variant, currentSlideId }: TimerProps) => { const dispatch = useAppDispatch() const timer = useAppSelector((state) => state.presentation.timer) const [remainingTimer, setRemainingTimer] = useState<number>(0) @@ -22,6 +23,8 @@ const Timer = ({ variant }: TimerProps) => { const displayTime = `${remainingDisplayMinutes}:${remainingDisplaySeconds}` const [timerIntervalId, setTimerIntervalId] = useState<NodeJS.Timeout | null>(null) const slideTimer = useAppSelector((state) => { + if (currentSlideId && variant === 'presentation') + return state.presentation.competition.slides.find((slide) => slide.id === currentSlideId)?.timer if (variant === 'presentation') return state.presentation.competition.slides.find((slide) => slide.id === state.presentation.activeSlideId)?.timer return state.editor.competition.slides.find((slide) => slide.id === state.editor.activeSlideId)?.timer diff --git a/server/app/apis/slides.py b/server/app/apis/slides.py index b1052c8ddc0877fe213e0ba0392b1ab601f1ca24..654ee49f6ce02d8e56d6d5529fcbbcf0c0b12af2 100644 --- a/server/app/apis/slides.py +++ b/server/app/apis/slides.py @@ -38,7 +38,7 @@ class SlidesList(Resource): def post(self, competition_id): """ Posts a new slide to the specified competition. """ - item_slide = dbc.add.slide_without_question(competition_id) + item_slide = dbc.add.slide(competition_id) return item_response(schema.dump(item_slide)) diff --git a/server/app/database/controller/add.py b/server/app/database/controller/add.py index 9d37c8f802375052b567d9af536cdc8d933d4ac4..86b6e4b6875dfd66cbe33c04b7a5595bc70b7686 100644 --- a/server/app/database/controller/add.py +++ b/server/app/database/controller/add.py @@ -125,20 +125,7 @@ def slide(competition_id): # Add slide item_slide = db_add(Slide(order, competition_id)) - return item_slide - - -def slide_without_question(competition_id): - """ Adds a slide to the provided competition. """ - - # Get the last order from given competition - order = dbc.utils.count(Slide, {"competition_id": competition_id}) - - # Add slide - item_slide = db_add(Slide(order, competition_id)) - - item_slide = dbc.utils.refresh(item_slide) - return item_slide + return dbc.utils.refresh(item_slide) def competition(name, year, city_id): diff --git a/server/app/database/controller/copy.py b/server/app/database/controller/copy.py index d19f6bd362ffc00066c12bc196e24a7d7d5ee5b8..f2a06fac5a990d5857abff7526c3aaa2344ddf24 100644 --- a/server/app/database/controller/copy.py +++ b/server/app/database/controller/copy.py @@ -4,7 +4,8 @@ This file contains functionality to copy and duplicate data to the database. from app.database.controller import add, get, search, utils from app.database.models import Question -from app.database.types import IMAGE_COMPONENT_ID, QUESTION_COMPONENT_ID, TEXT_COMPONENT_ID +from app.database.types import (IMAGE_COMPONENT_ID, QUESTION_COMPONENT_ID, + TEXT_COMPONENT_ID) def _alternative(item_old, question_id): @@ -90,7 +91,7 @@ def slide_to_competition(item_slide_old, item_competition): Does not copy team, question answers. """ - item_slide_new = add.slide_without_question(item_competition.id) + item_slide_new = add.slide(item_competition.id) # Copy all fields item_slide_new.title = item_slide_old.title diff --git a/server/tests/test_app.py b/server/tests/test_app.py index 6439c465deb3b8662df68f457d967d3bfec63759..e4e46c686c88b6ab728223fc1f1011fcb0d6bf4e 100644 --- a/server/tests/test_app.py +++ b/server/tests/test_app.py @@ -9,7 +9,8 @@ import pytest from app.core import sockets from tests import app, client, db -from tests.test_helpers import add_default_values, change_order_test, delete, get, post, put +from tests.test_helpers import (add_default_values, change_order_test, delete, + get, post, put) # @pytest.mark.skip(reason="Takes long time") @@ -398,14 +399,13 @@ def test_question_api(client): slide_order = 1 response, body = get(client, f"/api/competitions/{CID}/questions", headers=headers) assert response.status_code == codes.OK - assert body["count"] == 2 + assert body["count"] == 0 # Get questions from another competition that should have some questions CID = 3 - num_questions = 3 response, body = get(client, f"/api/competitions/{CID}/questions", headers=headers) assert response.status_code == codes.OK - assert body["count"] == num_questions + assert body["count"] == 0 # Add question name = "Nytt namn" @@ -417,7 +417,6 @@ def test_question_api(client): {"name": name, "type_id": type_id}, headers=headers, ) - num_questions = 4 assert response.status_code == codes.OK assert item_question["name"] == name assert item_question["type_id"] == type_id @@ -425,7 +424,7 @@ def test_question_api(client): # Checks number of questions response, body = get(client, f"/api/competitions/{CID}/questions", headers=headers) assert response.status_code == codes.OK - assert body["count"] == num_questions + assert body["count"] == 1 """ # Delete question response, _ = delete(client, f"/api/competitions/{CID}/slides/{slide_order}/questions/{QID}", headers=headers) diff --git a/server/tests/test_helpers.py b/server/tests/test_helpers.py index 47fa647dcac0098dd5ef4e09313a834d1ca58c16..7bcda31a086e687f9bb3e1b96f263d2cc34a482f 100644 --- a/server/tests/test_helpers.py +++ b/server/tests/test_helpers.py @@ -41,10 +41,7 @@ def add_default_values(): # Add competitions item_competition = dbc.add.competition("Tom tävling", 2012, item_city.id) - item_question = dbc.add.question("hej", 5, 1, item_competition.slides[0].id) - item_team1 = dbc.add.team("Hej lag 3", item_competition.id) - item_team2 = dbc.add.team("Hej lag 4", item_competition.id) db.session.add(Code("111111", 1, item_competition.id, item_team1.id)) # Team db.session.add(Code("222222", 2, item_competition.id)) # Judge