mirror of
https://github.com/evroon/bracket.git
synced 2026-06-11 10:15:19 -04:00
Add teams with players (#1118)
fixes https://github.com/evroon/bracket/issues/978
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user