Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(multi): Adding tournament support and increasing max tables #10

Merged
merged 7 commits into from
Jan 27, 2024
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
2 changes: 2 additions & 0 deletions apps/api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=pool
POSTGRES_PORT=5432
CHALLONGE_API_KEY=secret
CHALLONGE_USERNAME=username
11 changes: 6 additions & 5 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# Use nxgo/cli as the base image to do the build
FROM nxgo/cli as builder
# FROM nxgo/cli as builder
FROM golang:1.20-alpine as builder

# Create app directory
WORKDIR /workspace

# Build argument for fontawesome npm token
ARG FONTAWESOME_NPM_AUTH_TOKEN
# ARG FONTAWESOME_NPM_AUTH_TOKEN

# Copy package.json and the lock file
COPY package.json package-lock.json .npmrc ./
# COPY package.json package-lock.json .npmrc ./

# Install app dependencies
RUN npm ci
# RUN npm ci

# Copy go mod files
COPY go.mod go.sum ./
Expand All @@ -29,7 +30,7 @@ COPY apps/seed apps/seed
COPY libs/go libs/go

# Copy Nx files
COPY nx.json workspace.json tsconfig.base.json ./
# COPY nx.json workspace.json tsconfig.base.json ./

# Build api app
# RUN nx build api
Expand Down
9 changes: 8 additions & 1 deletion apps/api/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"

"github.com/codephobia/pool-overlay/libs/go/api"
"github.com/codephobia/pool-overlay/libs/go/challonge"
overlayPkg "github.com/codephobia/pool-overlay/libs/go/overlay"
"github.com/codephobia/pool-overlay/libs/go/state"
"github.com/codephobia/pool-overlay/libs/go/telestrator"
Expand All @@ -19,6 +20,7 @@ type Core struct {
overlay *overlayPkg.Overlay
telestrator *telestrator.Telestrator
tables map[int]*state.State
challonge *challonge.Challonge
}

// NewCore returns a new Core.
Expand Down Expand Up @@ -47,6 +49,10 @@ func NewCore() (*Core, error) {
tables := map[int]*state.State{}
tables[1] = state.NewState(db, 1)
tables[2] = state.NewState(db, 2)
tables[3] = state.NewState(db, 3)

// Initialize Challonge.
challonge := challonge.NewChallonge(os.Getenv("CHALLONGE_API_KEY"), os.Getenv("CHALLONGE_USERNAME"), db, overlay, tables)

// Initialize API Server.
apiConfig := &api.Config{
Expand All @@ -58,14 +64,15 @@ func NewCore() (*Core, error) {
Previous: "1",
},
}
server := api.NewServer(apiConfig, db, overlay, telestrator, tables)
server := api.NewServer(apiConfig, db, overlay, telestrator, tables, challonge)

return &Core{
db: db,
server: server,
overlay: overlay,
telestrator: telestrator,
tables: tables,
challonge: challonge,
}, nil
}

Expand Down
2 changes: 2 additions & 0 deletions apps/dashboard/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

import { overlayRoute } from './overlay/overlay.route';
import { tournamentsRoute } from './tournament/tournaments.route';
import { playersRoute } from './players/players.route';
import { gamesRoute } from './games/games.route';
import { drawingRoute } from './drawing/drawing.route';

const routes: Routes = [
overlayRoute,
tournamentsRoute,
playersRoute,
gamesRoute,
drawingRoute,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { faDesktop, faUser, faPool8Ball, faPencil } from '@fortawesome/pro-regular-svg-icons';
import { faDesktop, faUser, faPool8Ball, faPencil, faTrophyStar } from '@fortawesome/pro-regular-svg-icons';

@Component({
selector: 'pool-overlay-side-nav',
Expand All @@ -10,6 +10,10 @@ export class SideNavComponent {
icon: faDesktop,
title: 'Overlay',
link: 'overlay',
}, {
icon: faTrophyStar,
title: 'Tournaments',
link: 'tournaments',
}, {
icon: faUser,
title: 'Players',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export class ControllerStore extends ComponentStore<ControllerState> {
showFlags: false,
showFargo: true,
showScore: true,
waitingForPlayers: false,
waitingForTournamentStart: false,
tableNoLongerInUse: false,
},
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { faPlus } from '@fortawesome/pro-regular-svg-icons';
})
export class HomePageComponent {
public faPlus = faPlus;
public tables: number[] = [1, 2];
public tables: number[] = [1, 2, 3];
public currentTable = 1;

public setTable(table: number): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ <h1 class="text-gray-50 uppercase text-4xl">{{ isCreating ? 'Create' : 'Update'
/>
</div>
</div>
<div class="flex flex-wrap -mx-3 mb-6">
<div class="w-full px-3 mb-6 md:mb-0">
<label class="block uppercase tracking-wide text-gray-100 text-xs font-bold mb-2" for="fargo_id">Fargo Observable ID</label>
<input
class="appearance-none block w-full bg-gray-200 text-gray-700 border rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
id="fargo_observable_id"
type="number"
min="0"
placeholder="Fargo Observable ID"
formControlName="fargo_observable_id"
/>
</div>
</div>
<div class="flex flex-wrap -mx-3 mb-6">
<div class="w-full px-3 mb-6 md:mb-0">
<label class="block uppercase tracking-wide text-gray-100 text-xs font-bold mb-2" for="fargo_id">Fargo ID</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class PlayerFormComponent {
this.form.addControl('id', this._fb.control(this._player.id, Validators.required));
this.form.controls.name.patchValue(this._player.name);
this.form.controls.flag_id.patchValue(this._player.flag_id);
this.form.controls.fargo_observable_id.patchValue(this._player.fargo_observable_id);
this.form.controls.fargo_id.patchValue(this._player.fargo_id);
this.form.controls.fargo_rating.patchValue(this._player.fargo_rating);
}
Expand All @@ -42,6 +43,7 @@ export class PlayerFormComponent {
this.form = this._fb.group({
name: ['', Validators.required],
flag_id: [1, Validators.required],
fargo_observable_id: [0, Validators.required],
fargo_id: [0, Validators.required],
fargo_rating: [0, Validators.required],
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
<div class="w-1/12 flex flex-col justify-center items-start px-10">
<p class="text-white uppercase text-xs">Flag</p>
</div>
<div class="w-5/12 flex flex-col justify-center items-start px-10">
<div class="w-3/12 flex flex-col justify-center items-start px-10">
<p class="text-white uppercase text-xs">Name</p>
</div>
<div class="w-2/12 flex flex-col justify-center items-start px-10">
<p class="text-white uppercase text-xs whitespace-nowrap">Fargo Observable ID</p>
</div>
<div class="w-2/12 flex flex-col justify-center items-start px-10">
<p class="text-white uppercase text-xs whitespace-nowrap">Fargo ID</p>
</div>
Expand All @@ -19,9 +22,12 @@
<div class="w-1/12 flex flex-col justify-center items-start px-10">
<img *ngIf="player?.flag" class="w-5 h-auto" src="./assets/flags/{{ player?.flag?.image_path }}" [alt]="player?.flag?.country" />
</div>
<div class="w-5/12 flex flex-col justify-center px-10">
<div class="w-3/12 flex flex-col justify-center px-10">
<p class="text-white uppercase text-xs whitespace-nowrap">{{ player?.name }}</p>
</div>
<div class="w-2/12 flex flex-col justify-center px-10">
<p class="text-white uppercase text-xs">{{ player?.fargo_observable_id }}</p>
</div>
<div class="w-2/12 flex flex-col justify-center px-10">
<p class="text-white uppercase text-xs">{{ player?.fargo_id }}</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<div class="flex flex-col flex-grow" *ngIf="vm$ | async as vm">
<div *ngIf="vm.hasTournaments" class="flex flex-row h-66px bg-sad-input border-sad-active border-b">
<div class="w-9/12 flex flex-col justify-center items-start px-10">
<p class="text-white uppercase text-xs">Name</p>
</div>
<div class="w-3/12 flex flex-col px-10"></div>
</div>
<ng-container *ngIf="vm.isLoaded; else loading">
<div class="flex flex-row h-66px" *ngFor="let tournament of vm.tournaments; even as isEven; odd as isOdd" [ngClass]="{ 'bg-sad-table-even': isEven, 'bg-sad-table-odd': isOdd }">
<div class="w-9/12 flex flex-col justify-center px-10">
<p class="text-white uppercase text-xs whitespace-nowrap">{{ tournament?.name }}</p>
</div>
<div class="w-3/12 flex flex-col justify-center items-end px-10">
<div class="flex flex-row gap-5 whitespace-nowrap">
<a href="https://challonge.com/{{ tournament.url }}" target="_blank" class="text-white bg-sad-challonge rounded py-2.5 px-5 uppercase text-xs mr-2.5">View on Challonge</a>
<a class="text-white bg-sad-success rounded py-2.5 px-5 uppercase text-xs" routerLink="./{{ tournament?.id }}">Select</a>
</div>
</div>
</div>
<ng-container *ngIf="!vm.hasTournaments">
<p class="p-4 text-white bg-sad-input border-sad-active border-t">Please create a new tournament on Challonge to continue.</p>
</ng-container>
</ng-container>
<ng-template #loading>
<div class="relative flex flex-row h-66px" *ngFor="let tournament of [1, 2, 3, 4, 5]; even as isEven; odd as isOdd" [ngClass]="{ 'bg-sad-table-even': isEven, 'bg-sad-table-odd': isOdd }">
<div class="shimmer-overlay"></div>
</div>
</ng-template>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Tournament } from '@pool-overlay/models';
import { TournamentListStore } from './tournament-list.store';

@Component({
selector: 'pool-overlay-tournament-list',
templateUrl: 'tournament-list.component.html',
providers: [TournamentListStore],
})
export class TournamentListComponent implements OnInit {
readonly vm$ = this.store.vm$;

@Output()
public selected = new EventEmitter<{ tournamentId: number }>();

constructor(private store: TournamentListStore) { }

public ngOnInit(): void {
this.store.getTournaments();
}

public selectTournament(tournamentId: number): void {
this.selected.emit({ tournamentId });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Injectable } from '@angular/core';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { Tournament } from '@pool-overlay/models';
import { switchMap, tap } from 'rxjs';
import { TournamentsService } from '../../services/tournament.service';

export enum LoadingState {
INIT,
LOADING,
LOADED,
}

interface TournamentListState {
callState: LoadingState;
tournaments: Tournament[];
}

export const initialState: TournamentListState = {
callState: LoadingState.INIT,
tournaments: [],
}

@Injectable()
export class TournamentListStore extends ComponentStore<TournamentListState> {
constructor(
private tournamentsService: TournamentsService,
) {
super(initialState);
}

// updaters
private updateCallState = this.updater<LoadingState>((state, callState) => ({
...state,
callState,
}));

private updateTournaments = this.updater<Tournament[]>((state, tournaments) => ({
...state,
tournaments,
callState: LoadingState.LOADED,
}));

// selectors
private isLoaded$ = this.select((state) => state.callState === LoadingState.LOADED);
private tournaments$ = this.select((state) => state.tournaments);
private hasTournaments$ = this.select(
this.isLoaded$,
this.tournaments$,
(loaded, tournaments) => loaded && !!tournaments.length
);
readonly vm$ = this.select(
this.isLoaded$,
this.tournaments$,
this.hasTournaments$,
(isLoaded, tournaments, hasTournaments) => ({
isLoaded,
tournaments,
hasTournaments,
})
);

// effects
readonly getTournaments = this.effect((trigger$) => trigger$.pipe(
tap(() => this.updateCallState(LoadingState.LOADING)),
switchMap(() => this.tournamentsService.getList().pipe(
tapResponse(
(tournaments) => this.updateTournaments(tournaments),
(err) => {
console.log(err);
}
)
)),
));
}
Loading
Loading