Skip to content
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
4 changes: 2 additions & 2 deletions .github/workflows/api-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ on:
- prod

concurrency:
group: ${{ format('{0}-{1}-{2}', github.workflow, github.ref, github.event_name == 'workflow_call' && github.run_id || 'manual') }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.environment }}
cancel-in-progress: false

env:
REGISTRY: ghcr.io
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/frontend-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ on:
- prod

concurrency:
group: ${{ format('{0}-{1}-{2}', github.workflow, github.ref, github.event_name == 'workflow_call' && github.run_id || 'manual') }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.environment }}
cancel-in-progress: false

env:
REGISTRY: ghcr.io
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/github-service-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ on:
- prod

concurrency:
group: ${{ format('{0}-{1}-{2}', github.workflow, github.ref, github.event_name == 'workflow_call' && github.run_id || 'manual') }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.environment }}
cancel-in-progress: false

env:
REGISTRY: ghcr.io
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/k8s-service-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ on:
- prod

concurrency:
group: ${{ format('{0}-{1}-{2}', github.workflow, github.ref, github.event_name == 'workflow_call' && github.run_id || 'manual') }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.environment }}
cancel-in-progress: false

env:
REGISTRY: ghcr.io
Expand Down
21 changes: 17 additions & 4 deletions api/src/match/match.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class MatchController {
constructor(
private readonly matchService: MatchService,
private readonly eventService: EventService,
) { }
) {}

private logger = new Logger("MatchController");

Expand Down Expand Up @@ -113,9 +113,7 @@ export class MatchController {

@UseGuards(JwtAuthGuard)
@Get("team/:teamId")
async getMatchesForTeam(
@Param("teamId", ParseUUIDPipe) teamId: string,
) {
async getMatchesForTeam(@Param("teamId", ParseUUIDPipe) teamId: string) {
return await this.matchService.getMatchesForTeam(teamId);
}

Expand Down Expand Up @@ -156,6 +154,21 @@ export class MatchController {
return this.matchService.revealMatch(matchId);
}

@UseGuards(JwtAuthGuard)
@Put("reveal-all/:eventId/:phase")
async revealAllMatches(
@Param("eventId", ParseUUIDPipe) eventId: string,
@Param("phase") phase: string,
@UserId() userId: string,
) {
if (!(await this.eventService.isEventAdmin(eventId, userId)))
throw new UnauthorizedException(
"You are not authorized to reveal matches for this event.",
);

return this.matchService.revealAllMatchesInPhase(eventId, phase as any);
}

@Get(":matchId")
async getMatchById(
@Param("matchId", ParseUUIDPipe) matchId: string,
Expand Down
57 changes: 43 additions & 14 deletions api/src/match/match.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,7 @@ export class MatchService {
}

const tournamentTeamCount = await this.getTournamentTeamCount(event.id);
const finalRoundIndex = Math.max(
0,
Math.log2(tournamentTeamCount) - 1,
);
const finalRoundIndex = Math.max(0, Math.log2(tournamentTeamCount) - 1);

if (event.currentRound >= finalRoundIndex) {
this.logger.log(`Event ${event.name} has finished the final round.`);
Expand Down Expand Up @@ -833,18 +830,23 @@ export class MatchService {
select: {
id: true,
},
where: {
teams: {
id: teamId,
where: [
{
teams: { id: teamId },
state: MatchState.FINISHED,
phase: MatchPhase.QUEUE,
},
state: MatchState.FINISHED,
},
{
teams: { id: teamId },
state: MatchState.FINISHED,
isRevealed: true,
},
],
withDeleted: true,
})
).map(match => match.id);
).map((match) => match.id);

if (matchesToQuery.length === 0)
return [];
if (matchesToQuery.length === 0) return [];

const matches = await this.matchRepository.find({
where: {
Expand All @@ -864,8 +866,15 @@ export class MatchService {
});

return matches.map((match) => {
const { id: _id, ...rest } = match;
return rest;
// Reveal ID only if it's NOT from the queue AND it is revealed.
const shouldRevealId =
match.phase !== MatchPhase.QUEUE && match.isRevealed;

if (!shouldRevealId) {
const { id: _id, ...rest } = match;
return rest;
}
return match;
});
}

Expand Down Expand Up @@ -1025,6 +1034,26 @@ export class MatchService {
});
}

async revealAllMatchesInPhase(eventId: string, phase: MatchPhase) {
const matches = await this.matchRepository.find({
where: {
teams: {
event: {
id: eventId,
},
},
phase: phase,
},
});

if (matches.length > 0) {
await this.matchRepository.update(
matches.map((m) => m.id),
{ isRevealed: true },
);
}
}

getGlobalStats() {
return this.matchStatsRepository
.createQueryBuilder("match_stats")
Expand Down
10 changes: 9 additions & 1 deletion api/src/team/team.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,13 @@ export class TeamController {
@EventId eventId: string,
@Body() inviteUserDto: InviteUserDto,
@Team() team: TeamEntity,
@UserId() userId: string
) {
if(userId === inviteUserDto.userToInviteId)
throw new BadRequestException(
"You cannot invite yourself to a team.",
)

if(await this.teamService.isTeamFull(team.id))
throw new BadRequestException("This team is full.");
if (
Expand Down Expand Up @@ -169,8 +175,9 @@ export class TeamController {
@EventId eventId: string,
@Param("searchQuery") searchQuery: string,
@Team() team: TeamEntity,
@UserId() userId: string
) {
return this.userService.searchUsersForInvite(eventId, searchQuery, team.id);
return this.userService.searchUsersForInvite(eventId, searchQuery, team.id, userId);
}

@UseGuards(JwtAuthGuard)
Expand All @@ -195,6 +202,7 @@ export class TeamController {
);
if (!(await this.teamService.isUserInvitedToTeam(userId, teamId)))
throw new BadRequestException("You are not invited to this team.");

if(await this.teamService.isTeamFull(teamId))
throw new BadRequestException("This team is full.");

Expand Down
1 change: 0 additions & 1 deletion api/src/team/team.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { FindOptionsRelations } from "typeorm/find-options/FindOptionsRelations"
import { MatchService } from "../match/match.service";
import { Cron, CronExpression } from "@nestjs/schedule";
import { LockKeys } from "../constants";
import { EventEntity } from "../event/entities/event.entity";

@Injectable()
export class TeamService {
Expand Down
6 changes: 4 additions & 2 deletions api/src/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export class UserService {
constructor(
@InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
private configService: ConfigService,
) { }
private readonly configService: ConfigService,
) {}

async createUser(
email: string,
Expand Down Expand Up @@ -128,6 +128,7 @@ export class UserService {
eventId: string,
searchQuery: string,
teamId: string,
userId: string,
): Promise<UserInviteSearchResult[]> {
const isEventPublic = await this.userRepository.manager
.getRepository(EventEntity)
Expand Down Expand Up @@ -159,6 +160,7 @@ export class UserService {
social: `%${searchQuery}%`,
},
)
.andWhere("user.id != :userId", { userId })
.andWhere("team.id IS NULL")
.andWhere(
"(inviteEvent.id IS NULL OR inviteEvent.id != :eventId OR inviteTeam.id = :teamId)",
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/actions/tournament-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export enum MatchState {
}

export interface Match {
id: string;
id?: string;
round: number;
state: MatchState;
phase: MatchPhase;
Expand Down
13 changes: 10 additions & 3 deletions frontend/app/actions/tournament.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,22 @@ export async function revealMatch(
return handleError(axiosInstance.put<Match>(`/match/reveal/${matchId}`));
}

export async function revealAllMatches(
eventId: string,
phase: string,
): Promise<ServerActionResponse<void>> {
return handleError(
axiosInstance.put<void>(`/match/reveal-all/${eventId}/${phase}`),
);
}

export async function getMatchById(
matchId: string,
): Promise<ServerActionResponse<Match>> {
return handleError(axiosInstance.get<Match>(`/match/${matchId}`));
}

export async function getMatchesForTeam(
teamId: string,
): Promise<Match[]> {
export async function getMatchesForTeam(teamId: string): Promise<Match[]> {
return (await axiosInstance.get(`/match/team/${teamId}`)).data;
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/app/changelog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ async function markdownToHtml(md: string): Promise<string> {
return String(file);
}

// determines which version number was incremented in a release (e.g. v1.2.3.4 -> v1.3.0.0 is a level 2 bump)
// determines which version number was incremented in a release (e.g. v1.2.3.4 -> v1.3.0.0 is a level 2 bump).
function bumpLevel(curr: string, prev?: string): 1 | 2 | 3 | 4 {
if (!prev)
return 4;
Expand Down
14 changes: 9 additions & 5 deletions frontend/app/events/[id]/bracket/graphView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,18 @@ export default function GraphView({
};

newNodes.push({
id: match.id,
id: match.id ?? `match-${round}-${index}`,
type: "matchNode",
position: { x: coord.x, y: coord.y },
data: {
match,
width: MATCH_WIDTH,
height: MATCH_HEIGHT,
onClick: (clickedMatch: Match) => {
if (match.state === MatchState.FINISHED || isEventAdmin)
if (
(match.state === MatchState.FINISHED || isEventAdmin) &&
clickedMatch.id
)
router.push(`/events/${eventId}/match/${clickedMatch.id}`);
},
},
Expand All @@ -151,7 +154,7 @@ export default function GraphView({
};

newNodes.push({
id: placementMatch.id,
id: placementMatch.id ?? `placement-${round}`,
type: "matchNode",
position: { x: placementCoord.x, y: placementCoord.y },
data: {
Expand All @@ -160,8 +163,9 @@ export default function GraphView({
height: MATCH_HEIGHT,
onClick: (clickedMatch: Match) => {
if (
placementMatch.state === MatchState.FINISHED ||
isEventAdmin
(placementMatch.state === MatchState.FINISHED ||
isEventAdmin) &&
clickedMatch.id
)
router.push(`/events/${eventId}/match/${clickedMatch.id}`);
},
Expand Down
Loading