mirror of
https://github.com/evroon/bracket.git
synced 2026-06-11 18:24:38 -04:00
Handle edge case with empty stage item inputs (#997)
This commit is contained in:
@@ -1,12 +1,18 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from fastapi import HTTPException
|
||||
from pydantic import BaseModel
|
||||
from starlette import status
|
||||
|
||||
from bracket.logic.ranking.elo import (
|
||||
determine_team_ranking_for_stage_item,
|
||||
)
|
||||
from bracket.logic.ranking.statistics import TeamStatistics
|
||||
from bracket.models.db.stage_item_inputs import StageItemInputFinal, StageItemInputTentative
|
||||
from bracket.models.db.stage_item_inputs import (
|
||||
StageItemInputEmpty,
|
||||
StageItemInputFinal,
|
||||
StageItemInputTentative,
|
||||
)
|
||||
from bracket.models.db.team import Team
|
||||
from bracket.models.db.util import StageWithStageItems
|
||||
from bracket.sql.matches import clear_scores_for_matches_in_stage_item
|
||||
@@ -65,7 +71,15 @@ async def get_team_update_for_input(
|
||||
target_stage_item_input = await get_stage_item_input_by_id(
|
||||
tournament_id, target_stage_item_input_id
|
||||
)
|
||||
assert isinstance(target_stage_item_input, StageItemInputFinal)
|
||||
if isinstance(target_stage_item_input, StageItemInputEmpty):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Please first assign teams to all stage items in the current stage.",
|
||||
)
|
||||
|
||||
assert isinstance(
|
||||
target_stage_item_input, StageItemInputFinal
|
||||
), f"Unexpected stage item type: {type(target_stage_item_input)}"
|
||||
return StageItemInputUpdate(
|
||||
stage_item_input=stage_item_input, team=target_stage_item_input.team
|
||||
)
|
||||
|
||||
@@ -126,12 +126,13 @@ async def activate_next_stage(
|
||||
stages = await get_full_tournament_details(tournament_id)
|
||||
deactivated_stage = next((stage for stage in stages if stage.is_active), None)
|
||||
|
||||
await sql_activate_next_stage(new_active_stage_id, tournament_id)
|
||||
if stage_body.direction == "next":
|
||||
await update_matches_in_activated_stage(tournament_id, new_active_stage_id)
|
||||
else:
|
||||
if deactivated_stage:
|
||||
await update_matches_in_deactivated_stage(tournament_id, deactivated_stage)
|
||||
|
||||
await sql_activate_next_stage(new_active_stage_id, tournament_id)
|
||||
return SuccessResponse()
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Alert, Button, Container, Grid, Loader, Modal, Title } from '@mantine/core';
|
||||
import { Alert, Button, Container, Grid, Modal, Title } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { FaArrowRight } from '@react-icons/all-files/fa/FaArrowRight';
|
||||
import { IconAlertCircle, IconSquareArrowRight } from '@tabler/icons-react';
|
||||
@@ -11,6 +11,8 @@ import { StageItemInput, formatStageItemInput } from '../../interfaces/stage_ite
|
||||
import { TeamInterface } from '../../interfaces/team';
|
||||
import { getStageItemLookup } from '../../services/lookups';
|
||||
import { activateNextStage } from '../../services/stage';
|
||||
import RequestErrorAlert from '../utils/error_alert';
|
||||
import { GenericSkeleton } from '../utils/skeletons';
|
||||
|
||||
type Update = { stage_item_input: StageItemInput; team: TeamInterface };
|
||||
type StageItemUpdate = { updates: Update[]; stageItem: StageItemWithRounds };
|
||||
@@ -47,7 +49,10 @@ function UpdatesToStageItemInputsTables({
|
||||
swrRankingsPerStageItemResponse: SWRResponse;
|
||||
}) {
|
||||
if (swrRankingsPerStageItemResponse.isLoading) {
|
||||
return <Loader />;
|
||||
return <GenericSkeleton />;
|
||||
}
|
||||
if (swrRankingsPerStageItemResponse.error) {
|
||||
return <RequestErrorAlert error={swrRankingsPerStageItemResponse.error} />;
|
||||
}
|
||||
|
||||
const items = swrRankingsPerStageItemResponse.data.data;
|
||||
|
||||
@@ -4,7 +4,13 @@ import React from 'react';
|
||||
|
||||
export function ErrorAlert({ title, message }: { title: string; message: string }) {
|
||||
return (
|
||||
<Alert icon={<IconAlertCircle size={16} />} title={title} color="red" radius="lg">
|
||||
<Alert
|
||||
icon={<IconAlertCircle size={32} />}
|
||||
title={title}
|
||||
color="red"
|
||||
radius="lg"
|
||||
variant="outline"
|
||||
>
|
||||
{message}
|
||||
</Alert>
|
||||
);
|
||||
|
||||
@@ -2,11 +2,15 @@ import { Center, Grid, Skeleton } from '@mantine/core';
|
||||
import React from 'react';
|
||||
|
||||
export function GenericSkeleton() {
|
||||
return <Skeleton height={75} radius="lg" mb="xl" />;
|
||||
}
|
||||
|
||||
export function GenericSkeletonThreeRows() {
|
||||
return (
|
||||
<>
|
||||
<Skeleton height={75} radius="lg" mb="xl" />
|
||||
<Skeleton height={75} radius="lg" mb="xl" />
|
||||
<Skeleton height={75} radius="lg" mb="xl" />
|
||||
<GenericSkeleton />
|
||||
<GenericSkeleton />
|
||||
<GenericSkeleton />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import { SWRResponse } from 'swr';
|
||||
|
||||
import NotFoundTitle from '../../404';
|
||||
import { DropzoneButton } from '../../../components/utils/file_upload';
|
||||
import { GenericSkeleton } from '../../../components/utils/skeletons';
|
||||
import { GenericSkeletonThreeRows } from '../../../components/utils/skeletons';
|
||||
import { capitalize, getBaseURL, getTournamentIdFromRouter } from '../../../components/utils/util';
|
||||
import { Club } from '../../../interfaces/club';
|
||||
import { Tournament } from '../../../interfaces/tournament';
|
||||
@@ -266,7 +266,7 @@ export default function SettingsPage() {
|
||||
let content = <NotFoundTitle />;
|
||||
|
||||
if (swrTournamentResponse.isLoading || swrClubsResponse.isLoading) {
|
||||
content = <GenericSkeleton />;
|
||||
content = <GenericSkeletonThreeRows />;
|
||||
}
|
||||
|
||||
if (tournamentDataFull != null) {
|
||||
|
||||
Reference in New Issue
Block a user