Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show modal when activating stages #897

Merged
merged 2 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/bracket/logic/ranking/elo.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def determine_ranking_for_stage_item(
return team_x_stats


async def determine_team_ranking_for_stage_item(
def determine_team_ranking_for_stage_item(
stage_item: StageItemWithRounds,
ranking: Ranking,
) -> list[tuple[TeamId, TeamStatistics]]:
Expand Down
26 changes: 16 additions & 10 deletions backend/bracket/logic/scheduling/handle_stage_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
)
from bracket.logic.ranking.statistics import TeamStatistics
from bracket.models.db.match import MatchWithDetails
from bracket.models.db.util import StageWithStageItems
from bracket.sql.matches import sql_get_match, sql_update_team_ids_for_match
from bracket.sql.rankings import get_ranking_for_stage_item
from bracket.sql.stage_items import get_stage_item
from bracket.sql.stages import get_full_tournament_details
from bracket.utils.id_types import MatchId, StageId, StageItemId, TeamId, TournamentId
from bracket.utils.types import assert_some
Expand Down Expand Up @@ -65,23 +65,29 @@ async def set_team_ids_for_match(
await sql_update_team_ids_for_match(assert_some(match.id), team1_id, team2_id)


async def get_team_rankings_lookup(tournament_id: TournamentId) -> StageItemXTeamRanking:
stages = await get_full_tournament_details(tournament_id)

stage_items = {
stage_item.id: assert_some(await get_stage_item(tournament_id, stage_item.id))
for stage in stages
for stage_item in stage.stage_items
}
async def get_team_rankings_lookup_for_stage(
tournament_id: TournamentId, stage: StageWithStageItems
) -> StageItemXTeamRanking:
stage_items = {stage_item.id: stage_item for stage_item in stage.stage_items}
return {
stage_item_id: await determine_team_ranking_for_stage_item(
stage_item_id: determine_team_ranking_for_stage_item(
stage_item,
assert_some(await get_ranking_for_stage_item(tournament_id, stage_item.id)),
)
for stage_item_id, stage_item in stage_items.items()
}


async def get_team_rankings_lookup(tournament_id: TournamentId) -> StageItemXTeamRanking:
return {
stage_item_id: team_ranking
for stage in await get_full_tournament_details(tournament_id)
for stage_item_id, team_ranking in (
await get_team_rankings_lookup_for_stage(tournament_id, stage)
).items()
}


async def update_matches_in_activated_stage(tournament_id: TournamentId, stage_id: StageId) -> None:
[stage] = await get_full_tournament_details(tournament_id, stage_id=stage_id)
stage_item_x_team_rankings = await get_team_rankings_lookup(tournament_id)
Expand Down
26 changes: 5 additions & 21 deletions backend/bracket/routes/stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
from starlette import status

from bracket.database import database
from bracket.logic.ranking.elo import (
determine_team_ranking_for_stage_item,
)
from bracket.logic.scheduling.builder import determine_available_inputs
from bracket.logic.scheduling.handle_stage_activation import update_matches_in_activated_stage
from bracket.logic.scheduling.handle_stage_activation import (
get_team_rankings_lookup_for_stage,
update_matches_in_activated_stage,
)
from bracket.logic.subscriptions import check_requirement
from bracket.models.db.stage import Stage, StageActivateBody, StageUpdateBody
from bracket.models.db.user import UserPublic
Expand All @@ -22,8 +22,6 @@
SuccessResponse,
)
from bracket.routes.util import stage_dependency
from bracket.sql.rankings import get_ranking_for_stage_item
from bracket.sql.stage_items import get_stage_item
from bracket.sql.stages import (
get_full_tournament_details,
get_next_stage_in_tournament,
Expand All @@ -33,7 +31,6 @@
)
from bracket.sql.teams import get_teams_with_members
from bracket.utils.id_types import StageId, TournamentId
from bracket.utils.types import assert_some

router = APIRouter()

Expand Down Expand Up @@ -158,17 +155,4 @@ async def get_rankings(
Get the rankings for the stage items in this stage.
"""
[stage] = await get_full_tournament_details(tournament_id, stage_id=stage_id)

stage_items = {
stage_item.id: assert_some(await get_stage_item(tournament_id, stage_item.id))
for stage_item in stage.stage_items
}
stage_item_x_ranking = {
stage_item_id: await determine_team_ranking_for_stage_item(
stage_item,
assert_some(await get_ranking_for_stage_item(tournament_id, stage_item.id)),
)
for stage_item_id, stage_item in stage_items.items()
}

return StageRankingResponse(data=stage_item_x_ranking)
return StageRankingResponse(data=await get_team_rankings_lookup_for_stage(tournament_id, stage))
6 changes: 6 additions & 0 deletions frontend/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
"active_next_round_modal_choose_option_checked": "Adjust the start times of the next matches to start immediately(now). This will be done by modifying the margin times of the matches in the previous round.",
"active_next_round_modal_choose_option_unchecked": "Use default timing (the next matches will be planned tightly after the matches of the active round end, taking margin into account)",
"active_next_round_modal_description": "This will assign times and courts to matches of next round, which is the round after the current activated (green) round.",
"active_next_stage_modal_description": "This will start the next stage. Teams will be automatically assigned to the matches.",
"plan_next_stage_button": "Start the next stage",
"active_next_stage_modal_title": "Start the next stage",
"active_previous_stage_modal_description": "Are you sure you want to go back to the previous stage? Match results will be discarded.",
"plan_previous_stage_button": "Go back to the previous stage",
"active_previous_stage_modal_title": "Go back to the previous stage",
"active_next_round_modal_title": "Assign times and courts to matches of next round",
"active_player_checkbox_label": "This player is active",
"active_players_checkbox_label": "These players are active",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/builder/builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export default function Builder({

const button = (
<Stack miw="24rem" align="top" key={-1}>
<h4>
<h4 style={{ marginTop: '0rem' }}>
<CreateStageButton tournament={tournament} swrStagesResponse={swrStagesResponse} />
</h4>
</Stack>
Expand Down
43 changes: 0 additions & 43 deletions frontend/src/components/buttons/next_stage_button.tsx

This file was deleted.

69 changes: 69 additions & 0 deletions frontend/src/components/modals/activate_next_stage_modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Alert, Button, Modal } from '@mantine/core';
import { useForm } from '@mantine/form';
import { IconAlertCircle, IconSquareArrowRight } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import React, { useState } from 'react';
import { SWRResponse } from 'swr';

import { activateNextStage } from '../../services/stage';

export default function ActivateNextStageModal({
tournamentId,
swrStagesResponse,
}: {
tournamentId: number;
swrStagesResponse: SWRResponse;
}) {
const { t } = useTranslation();
const [opened, setOpened] = useState(false);

const form = useForm({
initialValues: {},
});

return (
<>
<Modal
opened={opened}
onClose={() => setOpened(false)}
title={t('active_next_stage_modal_title')}
size="40rem"
>
<form
onSubmit={form.onSubmit(async () => {
await activateNextStage(tournamentId, 'next');
swrStagesResponse.mutate();
setOpened(false);
})}
>
<Alert icon={<IconAlertCircle size={16} />} color="gray" radius="lg">
{t('active_next_stage_modal_description')}
</Alert>

<Button
fullWidth
color="indigo"
size="md"
mt="lg"
type="submit"
leftSection={<IconSquareArrowRight size={24} />}
>
{t('plan_next_stage_button')}
</Button>
</form>
</Modal>

<Button
size="md"
mb="10"
color="indigo"
leftSection={<IconSquareArrowRight size={24} />}
onClick={async () => {
setOpened(true);
}}
>
{t('next_stage_button')}
</Button>
</>
);
}
69 changes: 69 additions & 0 deletions frontend/src/components/modals/activate_previous_stage_modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Alert, Button, Modal } from '@mantine/core';
import { useForm } from '@mantine/form';
import { IconAlertCircle, IconSquareArrowLeft } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import React, { useState } from 'react';
import { SWRResponse } from 'swr';

import { activateNextStage } from '../../services/stage';

export default function ActivatePreviousStageModal({
tournamentId,
swrStagesResponse,
}: {
tournamentId: number;
swrStagesResponse: SWRResponse;
}) {
const { t } = useTranslation();
const [opened, setOpened] = useState(false);

const form = useForm({
initialValues: {},
});

return (
<>
<Modal
opened={opened}
onClose={() => setOpened(false)}
title={t('active_previous_stage_modal_title')}
size="40rem"
>
<form
onSubmit={form.onSubmit(async () => {
await activateNextStage(tournamentId, 'previous');
swrStagesResponse.mutate();
setOpened(false);
})}
>
<Alert icon={<IconAlertCircle size={16} />} color="orange" radius="lg">
{t('active_previous_stage_modal_description')}
</Alert>

<Button
fullWidth
color="indigo"
size="md"
mt="lg"
type="submit"
leftSection={<IconSquareArrowLeft size={24} />}
>
{t('plan_previous_stage_button')}
</Button>
</form>
</Modal>

<Button
size="md"
mb="10"
color="indigo"
leftSection={<IconSquareArrowLeft size={24} />}
onClick={async () => {
setOpened(true);
}}
>
{t('previous_stage_button')}
</Button>
</>
);
}
15 changes: 8 additions & 7 deletions frontend/src/pages/tournaments/[id]/stages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import React from 'react';

import Builder from '../../../components/builder/builder';
import { CreateStageButtonLarge } from '../../../components/buttons/create_stage';
import {
NextStageButton,
PreviousStageButton,
} from '../../../components/buttons/next_stage_button';
import ActivateNextStageModal from '../../../components/modals/activate_next_stage_modal';
import ActivatePreviousStageModal from '../../../components/modals/activate_previous_stage_modal';
import { NoContent } from '../../../components/no_content/empty_table_info';
import { TableSkeletonTwoColumnsSmall } from '../../../components/utils/skeletons';
import { getTournamentIdFromRouter } from '../../../components/utils/util';
Expand Down Expand Up @@ -47,11 +45,14 @@ export default function StagesPage() {
content = (
<>
<Group grow mt="1rem" maw="30rem">
<PreviousStageButton
tournamentData={tournamentData}
<ActivatePreviousStageModal
tournamentId={tournamentData.id}
swrStagesResponse={swrStagesResponse}
/>
<ActivateNextStageModal
tournamentId={tournamentData.id}
swrStagesResponse={swrStagesResponse}
/>
<NextStageButton tournamentData={tournamentData} swrStagesResponse={swrStagesResponse} />
</Group>
<Group mt="1rem" align="top">
<Builder
Expand Down