Add teams with players (#1118)

fixes https://github.com/evroon/bracket/issues/978
This commit is contained in:
Erik Vroon
2025-02-12 12:27:14 +01:00
committed by GitHub
parent 9b88dfff0f
commit 2fa8c08da3
4 changed files with 52 additions and 24 deletions

View File

@@ -1,3 +1,4 @@
import csv
import os
from uuid import uuid4
@@ -9,6 +10,7 @@ from heliclockter import datetime_utc
from bracket.database import database
from bracket.logic.subscriptions import check_requirement
from bracket.logic.teams import get_team_logo_path
from bracket.models.db.player import PlayerBody
from bracket.models.db.team import (
FullTeamWithPlayers,
Team,
@@ -34,6 +36,7 @@ from bracket.routes.util import (
team_with_players_dependency,
)
from bracket.schema import players_x_teams, teams
from bracket.sql.players import get_all_players_in_tournament, insert_player
from bracket.sql.teams import (
get_team_by_id,
get_team_count,
@@ -209,19 +212,31 @@ async def create_multiple_teams(
user: UserPublic = Depends(user_authenticated_for_tournament),
_: Tournament = Depends(disallow_archived_tournament),
) -> SuccessResponse:
team_names = [team.strip() for team in team_body.names.split("\n") if len(team) > 0]
existing_teams = await get_teams_with_members(tournament_id)
check_requirement(existing_teams, user, "max_teams", additions=len(team_names))
reader = list(csv.reader(team_body.names.split("\n"), delimiter=","))
teams_and_players = [
(row[0], row[1:] if len(row) > 1 else []) for row in reader if len(row) > 0
]
players = [player for row in teams_and_players for player in row[1]]
for team_name in team_names:
await database.execute(
query=teams.insert(),
values=TeamInsertable(
name=team_name,
active=team_body.active,
created=datetime_utc.now(),
tournament_id=tournament_id,
).model_dump(),
)
existing_teams = await get_teams_with_members(tournament_id)
existing_players = await get_all_players_in_tournament(tournament_id)
check_requirement(existing_teams, user, "max_teams", additions=len(reader))
check_requirement(existing_players, user, "max_players", additions=len(players))
async with database.transaction():
for team_name, players in teams_and_players:
await database.execute(
query=teams.insert(),
values=TeamInsertable(
name=team_name,
active=team_body.active,
created=datetime_utc.now(),
tournament_id=tournament_id,
).model_dump(),
)
for player in players:
player_body = PlayerBody(name=player, active=team_body.active)
await insert_player(player_body, tournament_id)
return SuccessResponse()

View File

@@ -4,7 +4,7 @@ import pytest
from bracket.database import database
from bracket.models.db.team import Team
from bracket.schema import teams
from bracket.schema import players, teams
from bracket.utils.db import fetch_one_parsed_certain
from bracket.utils.dummy_records import DUMMY_MOCK_TIME, DUMMY_TEAM1
from bracket.utils.http import HTTPMethod
@@ -57,12 +57,13 @@ async def test_create_team(
async def test_create_teams(
startup_and_shutdown_uvicorn_server: None, auth_context: AuthContext
) -> None:
body = {"names": "Team -1\nTeam -2", "active": True}
body = {"names": "Team -1,Player 42,Player 43\nTeam -2", "active": True}
response = await send_tournament_request(
HTTPMethod.POST, "teams_multi", auth_context, None, body
)
assert response["success"] is True
await assert_row_count_and_clear(teams, 2)
await assert_row_count_and_clear(players, 3)
@pytest.mark.asyncio(loop_scope="session")

View File

@@ -31,8 +31,8 @@
"all_matches_scheduled_description": "Matches have been scheduled on all courts in this round. Add a new round or add a new court for more matches.",
"api_docs_title": "API docs",
"archive_tournament_button": "Archive Tournament",
"archived_label": "Archived",
"archived_header_label": "This tournament is archived. It is now read-only.",
"archived_label": "Archived",
"at_least_one_player_validation": "Enter at least one player",
"at_least_one_team_validation": "Enter at least one team",
"at_least_two_team_validation": "Need at least two teams",
@@ -116,6 +116,7 @@
"empty_name_validation": "Name cannot be empty",
"empty_password_validation": "Password cannot be empty",
"empty_slot": "Empty slot",
"example_label": "Example:",
"filter_stage_item_label": "Filter on stage item",
"filter_stage_item_placeholder": "No filter",
"forgot_password_button": "Forgot password?",
@@ -152,7 +153,7 @@
"multiple_players_input_placeholder": "Player 1",
"multiple_players_title": "Multiple Players",
"multiple_teams": "Multiple Teams",
"multiple_teams_input_label": "Add multiple teams. Put every team on a separate line",
"multiple_teams_input_label": "Add multiple teams. Put every team on a separate line. You can also add players per team, separated by `,`.",
"multiple_teams_input_placeholder": "Team 1",
"name_field_text": "name",
"name_input_label": "Name",
@@ -236,6 +237,7 @@
"team_count_input_round_robin_label": "Number of teams advancing from the previous stage",
"team_count_select_elimination_label": "Number of teams advancing from the previous stage",
"team_count_select_elimination_placeholder": "2, 4, 8 etc.",
"team_member_select_placeholder": "Pick team members for this team",
"team_member_select_title": "Team members",
"team_name_input_placeholder": "Best Team Ever",
"team_title": "Team",

View File

@@ -1,4 +1,4 @@
import { Textarea } from '@mantine/core';
import { Code, Text, Textarea } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { useTranslation } from 'next-i18next';
import React from 'react';
@@ -18,11 +18,21 @@ export function MultiPlayersInput({ form }: { form: UseFormReturnType<any> }) {
export function MultiTeamsInput({ form }: { form: UseFormReturnType<any> }) {
const { t } = useTranslation();
return (
<Textarea
label={t('multiple_teams_input_label')}
placeholder={t('multiple_teams_input_placeholder')}
minRows={10}
{...form.getInputProps('names')}
/>
<>
<Textarea
label={t('multiple_teams_input_label')}
placeholder={t('multiple_teams_input_placeholder')}
minRows={10}
{...form.getInputProps('names')}
/>
<Text mt="1rem">{t('example_label')}</Text>
<Code block>
Team 1
<br />
Team 2,Alex
<br />
Team 3,Bob,Charlie
</Code>
</>
);
}