mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-29 06:43:17 -05:00
Seeds -> admin tab
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { ActionFunctionArgs } from "react-router";
|
||||
import { z } from "zod";
|
||||
import { action as seedsAction } from "~/features/tournament/actions/to.$id.seeds.server";
|
||||
import { action as adminAction } from "~/features/tournament/actions/to.$id.admin.server";
|
||||
import { parseBody, parseParams } from "~/utils/remix.server";
|
||||
import { id } from "~/utils/zod";
|
||||
import { wrapActionForApi } from "../api-action-wrapper.server";
|
||||
@@ -32,7 +32,7 @@ export const action = async (args: ActionFunctionArgs) => {
|
||||
}),
|
||||
});
|
||||
|
||||
return wrapActionForApi(seedsAction, {
|
||||
return wrapActionForApi(adminAction, {
|
||||
...args,
|
||||
params: { id: String(tournamentId) },
|
||||
request: internalRequest,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ActionFunctionArgs } from "react-router";
|
||||
import { z } from "zod";
|
||||
import { action as seedsAction } from "~/features/tournament/actions/to.$id.seeds.server";
|
||||
import { action as adminAction } from "~/features/tournament/actions/to.$id.admin.server";
|
||||
import { parseBody, parseParams } from "~/utils/remix.server";
|
||||
import { id } from "~/utils/zod";
|
||||
import { wrapActionForApi } from "../api-action-wrapper.server";
|
||||
@@ -37,7 +37,7 @@ export const action = async (args: ActionFunctionArgs) => {
|
||||
}),
|
||||
});
|
||||
|
||||
return wrapActionForApi(seedsAction, {
|
||||
return wrapActionForApi(adminAction, {
|
||||
...args,
|
||||
params: { id: String(tournamentId) },
|
||||
request: internalRequest,
|
||||
|
||||
@@ -521,6 +521,74 @@ export const action: ActionFunction = async ({ request, params }) => {
|
||||
message = "Tournament reopened";
|
||||
break;
|
||||
}
|
||||
case "UPDATE_SEEDS": {
|
||||
validateIsTournamentOrganizer();
|
||||
errorToastIfFalsy(!tournament.hasStarted, "Tournament has started");
|
||||
|
||||
const teamsWithMembers = tournament.ctx.teams
|
||||
.filter((t) => data.seeds.includes(t.id))
|
||||
.map((team) => ({
|
||||
teamId: team.id,
|
||||
members: team.members.map((m) => ({
|
||||
userId: m.userId,
|
||||
username: m.username,
|
||||
})),
|
||||
}));
|
||||
|
||||
await TournamentRepository.updateTeamSeeds({
|
||||
tournamentId,
|
||||
teamIds: data.seeds,
|
||||
teamsWithMembers,
|
||||
});
|
||||
|
||||
message = "Seeds saved successfully";
|
||||
break;
|
||||
}
|
||||
case "UPDATE_STARTING_BRACKETS": {
|
||||
validateIsTournamentOrganizer();
|
||||
errorToastIfFalsy(!tournament.hasStarted, "Tournament has started");
|
||||
|
||||
const validBracketIdxs =
|
||||
tournament.ctx.settings.bracketProgression.flatMap(
|
||||
(bracket, bracketIdx) => (!bracket.sources ? [bracketIdx] : []),
|
||||
);
|
||||
|
||||
errorToastIfFalsy(
|
||||
data.startingBrackets.every((t) =>
|
||||
validBracketIdxs.includes(t.startingBracketIdx),
|
||||
),
|
||||
"Invalid starting bracket idx",
|
||||
);
|
||||
|
||||
await TournamentTeamRepository.updateStartingBrackets(
|
||||
data.startingBrackets,
|
||||
);
|
||||
|
||||
message = "Starting brackets updated";
|
||||
break;
|
||||
}
|
||||
case "UPDATE_AB_DIVISIONS": {
|
||||
validateIsTournamentOrganizer();
|
||||
errorToastIfFalsy(!tournament.hasStarted, "Tournament has started");
|
||||
|
||||
errorToastIfFalsy(
|
||||
tournament.ctx.settings.bracketProgression.some(
|
||||
(bracket) => !bracket.sources && bracket.settings?.hasAbDivisions,
|
||||
),
|
||||
"No starting bracket has A/B divisions enabled",
|
||||
);
|
||||
|
||||
const validTeamIds = new Set(tournament.ctx.teams.map((t) => t.id));
|
||||
errorToastIfFalsy(
|
||||
data.abDivisions.every((t) => validTeamIds.has(t.tournamentTeamId)),
|
||||
"Invalid tournament team id",
|
||||
);
|
||||
|
||||
await TournamentTeamRepository.updateAbDivisions(data.abDivisions);
|
||||
|
||||
message = "A/B divisions updated";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertUnreachable(data);
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
import type { ActionFunction } from "react-router";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import {
|
||||
clearTournamentDataCache,
|
||||
tournamentFromDB,
|
||||
} from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import {
|
||||
errorToastIfFalsy,
|
||||
parseParams,
|
||||
parseRequestPayload,
|
||||
successToast,
|
||||
} from "~/utils/remix.server";
|
||||
import { idObject } from "~/utils/zod";
|
||||
import * as TournamentRepository from "../TournamentRepository.server";
|
||||
import * as TournamentTeamRepository from "../TournamentTeamRepository.server";
|
||||
import { seedsActionSchema } from "../tournament-schemas.server";
|
||||
|
||||
export const action: ActionFunction = async ({ request, params }) => {
|
||||
const data = await parseRequestPayload({
|
||||
request,
|
||||
schema: seedsActionSchema,
|
||||
});
|
||||
const user = requireUser();
|
||||
const { id: tournamentId } = parseParams({
|
||||
params,
|
||||
schema: idObject,
|
||||
});
|
||||
const tournament = await tournamentFromDB({ tournamentId, user });
|
||||
|
||||
errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer");
|
||||
errorToastIfFalsy(!tournament.hasStarted, "Tournament has started");
|
||||
|
||||
switch (data._action) {
|
||||
case "UPDATE_SEEDS": {
|
||||
const teamsWithMembers = tournament.ctx.teams
|
||||
.filter((t) => data.seeds.includes(t.id))
|
||||
.map((team) => ({
|
||||
teamId: team.id,
|
||||
members: team.members.map((m) => ({
|
||||
userId: m.userId,
|
||||
username: m.username,
|
||||
})),
|
||||
}));
|
||||
|
||||
await TournamentRepository.updateTeamSeeds({
|
||||
tournamentId,
|
||||
teamIds: data.seeds,
|
||||
teamsWithMembers,
|
||||
});
|
||||
clearTournamentDataCache(tournamentId);
|
||||
return successToast("Seeds saved successfully");
|
||||
}
|
||||
case "UPDATE_STARTING_BRACKETS": {
|
||||
const validBracketIdxs =
|
||||
tournament.ctx.settings.bracketProgression.flatMap(
|
||||
(bracket, bracketIdx) => (!bracket.sources ? [bracketIdx] : []),
|
||||
);
|
||||
|
||||
errorToastIfFalsy(
|
||||
data.startingBrackets.every((t) =>
|
||||
validBracketIdxs.includes(t.startingBracketIdx),
|
||||
),
|
||||
"Invalid starting bracket idx",
|
||||
);
|
||||
|
||||
await TournamentTeamRepository.updateStartingBrackets(
|
||||
data.startingBrackets,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "UPDATE_AB_DIVISIONS": {
|
||||
errorToastIfFalsy(
|
||||
tournament.ctx.settings.bracketProgression.some(
|
||||
(bracket) => !bracket.sources && bracket.settings?.hasAbDivisions,
|
||||
),
|
||||
"No starting bracket has A/B divisions enabled",
|
||||
);
|
||||
|
||||
const validTeamIds = new Set(tournament.ctx.teams.map((t) => t.id));
|
||||
errorToastIfFalsy(
|
||||
data.abDivisions.every((t) => validTeamIds.has(t.tournamentTeamId)),
|
||||
"Invalid tournament team id",
|
||||
);
|
||||
|
||||
await TournamentTeamRepository.updateAbDivisions(data.abDivisions);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clearTournamentDataCache(tournamentId);
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -2,7 +2,6 @@ import clsx from "clsx";
|
||||
import {
|
||||
ClipboardCheck,
|
||||
LayoutGrid,
|
||||
ListOrdered,
|
||||
Medal,
|
||||
Menu,
|
||||
ScrollText,
|
||||
@@ -39,7 +38,6 @@ type NavItemKey =
|
||||
| "results"
|
||||
| "rules"
|
||||
| "lfg"
|
||||
| "seeds"
|
||||
| "admin";
|
||||
|
||||
interface NavItem {
|
||||
@@ -60,7 +58,6 @@ const PRIORITY_ORDER: NavItemKey[] = [
|
||||
"divisions",
|
||||
"streams",
|
||||
"rules",
|
||||
"seeds",
|
||||
"admin",
|
||||
];
|
||||
|
||||
@@ -253,19 +250,6 @@ function useNavItems({
|
||||
};
|
||||
}
|
||||
|
||||
const showSeeds =
|
||||
tournament.isOrganizer(user) &&
|
||||
!tournament.hasStarted &&
|
||||
!tournament.isLeagueSignup;
|
||||
if (showSeeds) {
|
||||
items.seeds = {
|
||||
key: "seeds",
|
||||
label: t("tournament:nav.seeds"),
|
||||
to: "seeds",
|
||||
icon: <ListOrdered />,
|
||||
};
|
||||
}
|
||||
|
||||
const showAdmin =
|
||||
tournament.isOrganizer(user) &&
|
||||
(!tournament.ctx.isFinalized || DANGEROUS_CAN_ACCESS_DEV_CONTROLS);
|
||||
|
||||
@@ -21,7 +21,6 @@ import * as React from "react";
|
||||
import { Link, useFetcher, useNavigation } from "react-router";
|
||||
import { Alert } from "~/components/Alert";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Catcher } from "~/components/Catcher";
|
||||
import { SendouButton } from "~/components/elements/Button";
|
||||
import {
|
||||
SendouChipRadio,
|
||||
@@ -39,13 +38,9 @@ import type { TournamentDataTeam } from "~/features/tournament-bracket/core/Tour
|
||||
import invariant from "~/utils/invariant";
|
||||
import { navIconUrl, userResultsPage } from "~/utils/urls";
|
||||
import { ordinalToRoundedSp } from "../../mmr/mmr-utils";
|
||||
import { action } from "../actions/to.$id.seeds.server";
|
||||
import { loader } from "../loaders/to.$id.seeds.server";
|
||||
import { useTournament } from "../routes/to.$id";
|
||||
import { TOURNAMENT } from "../tournament-constants";
|
||||
import { useTournament } from "./to.$id";
|
||||
import styles from "./to.$id.seeds.module.css";
|
||||
|
||||
export { action, loader };
|
||||
import styles from "./TournamentSeeds.module.css";
|
||||
|
||||
const AB_DIVISION_RADIO_OPTIONS = [
|
||||
{ value: "unassigned", label: "Unassigned" },
|
||||
@@ -53,7 +48,7 @@ const AB_DIVISION_RADIO_OPTIONS = [
|
||||
{ value: "1", label: "B" },
|
||||
] as const;
|
||||
|
||||
export default function TournamentSeedsPage() {
|
||||
export function TournamentSeeds() {
|
||||
const tournament = useTournament();
|
||||
const navigation = useNavigation();
|
||||
const [teamOrder, setTeamOrder] = React.useState(
|
||||
@@ -849,5 +844,3 @@ function computeRemovedPlayers(
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export const ErrorBoundary = Catcher;
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { LoaderFunctionArgs } from "react-router";
|
||||
import { redirect } from "react-router";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import { parseParams } from "~/utils/remix.server";
|
||||
import { tournamentBracketsPage } from "~/utils/urls";
|
||||
import { idObject } from "~/utils/zod";
|
||||
|
||||
export const loader = async ({ params }: LoaderFunctionArgs) => {
|
||||
const user = requireUser();
|
||||
const { id: tournamentId } = parseParams({
|
||||
params,
|
||||
schema: idObject,
|
||||
});
|
||||
const tournament = await tournamentFromDB({ tournamentId, user });
|
||||
|
||||
if (!tournament.isOrganizer(user) || tournament.hasStarted) {
|
||||
throw redirect(tournamentBracketsPage({ tournamentId }));
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import { Trash, Trophy, Tv, UserCog, Users } from "lucide-react";
|
||||
import { ListOrdered, Trash, Trophy, Tv, UserCog, Users } from "lucide-react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFetcher } from "react-router";
|
||||
@@ -37,12 +37,13 @@ import {
|
||||
tournamentPage,
|
||||
} from "~/utils/urls";
|
||||
import { BracketProgressionSelector } from "../../calendar/components/BracketProgressionSelector";
|
||||
import { TournamentSeeds } from "../components/TournamentSeeds";
|
||||
import { useTournament } from "./to.$id";
|
||||
import adminStyles from "./to.$id.admin.module.css";
|
||||
|
||||
export { action } from "../actions/to.$id.admin.server";
|
||||
|
||||
type AdminTab = "teams" | "staff" | "stream" | "brackets";
|
||||
type AdminTab = "teams" | "seeds" | "staff" | "stream" | "brackets";
|
||||
|
||||
export default function TournamentAdminPage() {
|
||||
const { t } = useTranslation(["tournament", "calendar"]);
|
||||
@@ -68,12 +69,15 @@ export default function TournamentAdminPage() {
|
||||
const showStaffTab = tournament.isAdmin(user);
|
||||
const showBracketsTab =
|
||||
!tournament.isLeagueSignup || showEditBrackets || showReopen;
|
||||
const showSeedsTab = !tournament.hasStarted && !tournament.isLeagueSignup;
|
||||
|
||||
const isVisibleTab = (tab: string): tab is AdminTab => {
|
||||
switch (tab) {
|
||||
case "teams":
|
||||
case "stream":
|
||||
return true;
|
||||
case "seeds":
|
||||
return showSeedsTab;
|
||||
case "staff":
|
||||
return showStaffTab;
|
||||
case "brackets":
|
||||
@@ -138,6 +142,11 @@ export default function TournamentAdminPage() {
|
||||
<SendouTab id="teams" icon={<Users />}>
|
||||
{t("tournament:admin.tab.teams")}
|
||||
</SendouTab>
|
||||
{showSeedsTab ? (
|
||||
<SendouTab id="seeds" icon={<ListOrdered />}>
|
||||
{t("tournament:admin.tab.seeds")}
|
||||
</SendouTab>
|
||||
) : null}
|
||||
{showStaffTab ? (
|
||||
<SendouTab id="staff" icon={<UserCog />}>
|
||||
{t("tournament:admin.tab.staff")}
|
||||
@@ -157,6 +166,11 @@ export default function TournamentAdminPage() {
|
||||
<Divider smallText>Participant list download</Divider>
|
||||
<DownloadParticipants />
|
||||
</SendouTabPanel>
|
||||
{showSeedsTab ? (
|
||||
<SendouTabPanel id="seeds">
|
||||
<TournamentSeeds />
|
||||
</SendouTabPanel>
|
||||
) : null}
|
||||
{showStaffTab ? (
|
||||
<SendouTabPanel id="staff">
|
||||
<Staff />
|
||||
|
||||
@@ -60,37 +60,6 @@ export const registerSchema = z.union([
|
||||
}),
|
||||
]);
|
||||
|
||||
export const seedsActionSchema = z.union([
|
||||
z.object({
|
||||
_action: _action("UPDATE_SEEDS"),
|
||||
seeds: z.preprocess(safeJSONParse, z.array(id)),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_STARTING_BRACKETS"),
|
||||
startingBrackets: z.preprocess(
|
||||
safeJSONParse,
|
||||
z.array(
|
||||
z.object({
|
||||
tournamentTeamId: id,
|
||||
startingBracketIdx: bracketIdx,
|
||||
}),
|
||||
),
|
||||
),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_AB_DIVISIONS"),
|
||||
abDivisions: z.preprocess(
|
||||
safeJSONParse,
|
||||
z.array(
|
||||
z.object({
|
||||
tournamentTeamId: id,
|
||||
abDivision: z.union([z.literal(0), z.literal(1), z.null()]),
|
||||
}),
|
||||
),
|
||||
),
|
||||
}),
|
||||
]);
|
||||
|
||||
export const tournamentSearchSearchParamsSchema = z.object({
|
||||
q: z.string().max(100),
|
||||
limit: z.coerce.number().int().min(1).max(25).catch(25),
|
||||
@@ -192,4 +161,32 @@ export const adminActionSchema = z.union([
|
||||
z.object({
|
||||
_action: _action("REOPEN_TOURNAMENT"),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_SEEDS"),
|
||||
seeds: z.preprocess(safeJSONParse, z.array(id)),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_STARTING_BRACKETS"),
|
||||
startingBrackets: z.preprocess(
|
||||
safeJSONParse,
|
||||
z.array(
|
||||
z.object({
|
||||
tournamentTeamId: id,
|
||||
startingBracketIdx: bracketIdx,
|
||||
}),
|
||||
),
|
||||
),
|
||||
}),
|
||||
z.object({
|
||||
_action: _action("UPDATE_AB_DIVISIONS"),
|
||||
abDivisions: z.preprocess(
|
||||
safeJSONParse,
|
||||
z.array(
|
||||
z.object({
|
||||
tournamentTeamId: id,
|
||||
abDivision: z.union([z.literal(0), z.literal(1), z.null()]),
|
||||
}),
|
||||
),
|
||||
),
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -127,7 +127,6 @@ export default [
|
||||
route("teams/:tid", "features/tournament/routes/to.$id.teams.$tid.tsx"),
|
||||
route("join", "features/tournament/routes/to.$id.join.tsx"),
|
||||
route("admin", "features/tournament/routes/to.$id.admin.tsx"),
|
||||
route("seeds", "features/tournament/routes/to.$id.seeds.tsx"),
|
||||
route("results", "features/tournament/routes/to.$id.results.tsx"),
|
||||
route("streams", "features/tournament/routes/to.$id.streams.tsx"),
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ test.describe("Tournament A/B divisions", () => {
|
||||
|
||||
await navigate({
|
||||
page,
|
||||
url: `/to/${AB_RR_TOURNAMENT_ID}/seeds`,
|
||||
url: `/to/${AB_RR_TOURNAMENT_ID}/admin?tab=seeds`,
|
||||
});
|
||||
|
||||
await page.getByTestId("set-ab-divisions").click();
|
||||
|
||||
@@ -256,7 +256,7 @@ test.describe("Tournament", () => {
|
||||
|
||||
await navigate({
|
||||
page,
|
||||
url: `${tournamentPage(1)}/seeds`,
|
||||
url: `${tournamentPage(1)}/admin?tab=seeds`,
|
||||
});
|
||||
|
||||
await page.getByTestId("seed-team-1-handle").hover();
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Suppleanter",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Seedninger",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -77,6 +76,7 @@
|
||||
"teams.mapsPickedStatus": "Status for banevalg",
|
||||
"admin.download": "Hent liste over deltagere",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Seedninger",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Ersatzspieler",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Seeds",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -77,6 +76,7 @@
|
||||
"teams.mapsPickedStatus": "Status ausgewählter Arenen",
|
||||
"admin.download": "Teilnehmerliste herunterladen",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Seeds",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "LFG",
|
||||
"nav.subs": "Subs",
|
||||
"nav.divisions": "Divisions",
|
||||
"nav.seeds": "Seeds",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "Find team",
|
||||
"registerNow": "Register now",
|
||||
@@ -77,6 +76,7 @@
|
||||
"teams.mapsPickedStatus": "Maps picked status",
|
||||
"admin.download": "Download participants",
|
||||
"admin.tab.teams": "Teams",
|
||||
"admin.tab.seeds": "Seeds",
|
||||
"admin.tab.staff": "Staff",
|
||||
"admin.tab.stream": "Stream",
|
||||
"admin.tab.brackets": "Brackets",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Subs",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Listas de Equipos",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "Estado de mapas elegidos",
|
||||
"admin.download": "Descarga participantes",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Listas de Equipos",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Subs",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Listas de Equipos",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "Estado de escenarios elegidos",
|
||||
"admin.download": "Descarga participantes",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Listas de Equipos",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Remplaçants",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Seeds",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "Statut des stages sélectionnés",
|
||||
"admin.download": "Télécharger les participants",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Seeds",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Remplaçants",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Seeds",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "Statut des stages sélectionnés",
|
||||
"admin.download": "Télécharger les participants",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Seeds",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "מחליפים",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "דירוג",
|
||||
"nav.admin": "מנהל",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "סטטוס בחירת המפות",
|
||||
"admin.download": "הורדת משתתפים",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "דירוג",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Sub",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Seed",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "Stato scenari selezionati",
|
||||
"admin.download": "Download partecipanti",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Seed",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "サブ",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "シード",
|
||||
"nav.admin": "管理",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -75,6 +74,7 @@
|
||||
"teams.mapsPickedStatus": "マップの選択状況",
|
||||
"admin.download": "参加者リストをダウンロード",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "シード",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "",
|
||||
"nav.admin": "",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -75,6 +74,7 @@
|
||||
"teams.mapsPickedStatus": "",
|
||||
"admin.download": "",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "",
|
||||
"nav.admin": "",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -77,6 +76,7 @@
|
||||
"teams.mapsPickedStatus": "",
|
||||
"admin.download": "",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "",
|
||||
"nav.admin": "Admin",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -79,6 +78,7 @@
|
||||
"teams.mapsPickedStatus": "Status wybranych map",
|
||||
"admin.download": "Zapisz uczestników",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Inscritos",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Sementes",
|
||||
"nav.admin": "Administrador",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -78,6 +77,7 @@
|
||||
"teams.mapsPickedStatus": "Status dos mapas escolhidos",
|
||||
"admin.download": "Download dos participantes",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Sementes",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "Запасные",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "Семена",
|
||||
"nav.admin": "Администратор",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -79,6 +78,7 @@
|
||||
"teams.mapsPickedStatus": "Статус выбранных карт",
|
||||
"admin.download": "Скачать участников",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "Семена",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
"nav.looking": "",
|
||||
"nav.subs": "替补",
|
||||
"nav.divisions": "",
|
||||
"nav.seeds": "种子",
|
||||
"nav.admin": "管理",
|
||||
"findTeam": "",
|
||||
"registerNow": "",
|
||||
@@ -75,6 +74,7 @@
|
||||
"teams.mapsPickedStatus": "地图的选择情况",
|
||||
"admin.download": "下载参赛者",
|
||||
"admin.tab.teams": "",
|
||||
"admin.tab.seeds": "种子",
|
||||
"admin.tab.staff": "",
|
||||
"admin.tab.stream": "",
|
||||
"admin.tab.brackets": "",
|
||||
|
||||
Reference in New Issue
Block a user