From 696960eaac362f616393957dbcf62963c4145980 Mon Sep 17 00:00:00 2001 From: Mathieu Hermann Date: Sun, 5 Jan 2025 16:55:52 +0100 Subject: [PATCH] feat(server): improve interface to deal with large amount of datas + improve sharing message --- package.json | 97 +++++----- roadmap.md | 4 +- src/app/common/scss/components.scss | 28 +++ src/app/common/scss/variables.scss | 1 + .../online-event/online-event.component.html | 181 +++++++++++------- .../online-event/online-event.component.ts | 14 +- src/app/pages/server/server.component.html | 81 +++++--- src/app/pages/server/server.component.ts | 10 +- 8 files changed, 264 insertions(+), 152 deletions(-) diff --git a/package.json b/package.json index 2aef0af..cdd65d9 100644 --- a/package.json +++ b/package.json @@ -1,49 +1,50 @@ { - "name": "retroski", - "version": "1.1.2", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "biome lint --write src", - "format": "biome format --write src", - "postbuild": "cp src/.htaccess dist/" - }, - "private": true, - "dependencies": { - "@angular/animations": "^19.0.5", - "@angular/common": "^19.0.5", - "@angular/compiler": "^19.0.5", - "@angular/core": "^19.0.5", - "@angular/forms": "^19.0.5", - "@angular/platform-browser": "^19.0.5", - "@angular/platform-browser-dynamic": "^19.0.5", - "@angular/router": "^19.0.5", - "@angular/service-worker": "^19.0.5", - "date-fns": "4.1.0", - "dexie": "^4.0.9", - "excalibur": "0.30.2", - "pocketbase": "0.22.1", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.0.5", - "@angular/cli": "^19.0.5", - "@angular/compiler-cli": "^19.0.5", - "@biomejs/biome": "1.9.4", - "@types/jasmine": "~5.1.0", - "@types/node": "22.10.2", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.6.3", - "vite": "^5.0.0" - } -} \ No newline at end of file + "name": "retroski", + "version": "1.1.2", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "lint": "biome lint --write src", + "format": "biome format --write src", + "postbuild": "cp src/.htaccess dist/", + "preview": "http-server ./dist" + }, + "private": true, + "dependencies": { + "@angular/animations": "^19.0.5", + "@angular/common": "^19.0.5", + "@angular/compiler": "^19.0.5", + "@angular/core": "^19.0.5", + "@angular/forms": "^19.0.5", + "@angular/platform-browser": "^19.0.5", + "@angular/platform-browser-dynamic": "^19.0.5", + "@angular/router": "^19.0.5", + "@angular/service-worker": "^19.0.5", + "date-fns": "4.1.0", + "dexie": "^4.0.9", + "excalibur": "0.30.2", + "pocketbase": "0.22.1", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.15.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^19.0.5", + "@angular/cli": "^19.0.5", + "@angular/compiler-cli": "^19.0.5", + "@biomejs/biome": "1.9.4", + "@types/jasmine": "~5.1.0", + "@types/node": "22.10.2", + "jasmine-core": "~5.1.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "~3.2.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.1.0", + "typescript": "~5.6.3", + "vite": "^5.0.0" + } +} diff --git a/roadmap.md b/roadmap.md index f40c9f0..6dff51e 100644 --- a/roadmap.md +++ b/roadmap.md @@ -4,9 +4,9 @@ - Improve particles and performance - Improve skier sprites when turning - Define new default tracks, records and ghosts -- Improve online data list to match big items list - Define premium url & link -- Add verification step +- ✔️ ~~Improve online data list to match big items list~~ +- ✔️ ~~Add verification step~~ - ✔️ ~~Add password management step~~ - ✔️ ~~Use mailing server~~ - ✔️ ~~Implement async multiplayer~~ diff --git a/src/app/common/scss/components.scss b/src/app/common/scss/components.scss index e692125..dc16d6c 100644 --- a/src/app/common/scss/components.scss +++ b/src/app/common/scss/components.scss @@ -85,6 +85,9 @@ } .retro-subtitle { + display: flex; + align-items: center; + gap: 0.5rem; font-size: var(--text-subtitle); margin-top: 0.5rem; margin-bottom: 0.25rem; @@ -93,6 +96,22 @@ position: sticky; top: 26px; background-color: var(--color-surface); + + .alternative { + cursor: pointer; + transition: color ease-in-out var(--transition-time); + + &:not(:first-child) { + border-left: 1px solid var(--color-tertiary); + padding-left: 0.5rem; + font-size: var(--text-small); + } + + &:not(.active) { + color: var(--color-tertiary-light); + font-weight: 300 !important; + } + } } .retro-text { @@ -280,6 +299,15 @@ } } + &.inactive { + border: 1px solid var(--color-disabled); + color: var(--color-disabled); + + &:hover { + background-color: var(--color-disabled-lightest); + } + } + .icon { font-size: var(--icon-small); } diff --git a/src/app/common/scss/variables.scss b/src/app/common/scss/variables.scss index 8e9180c..0a8ce52 100644 --- a/src/app/common/scss/variables.scss +++ b/src/app/common/scss/variables.scss @@ -15,6 +15,7 @@ html { --color-error-darkest: #700002; --color-text: var(--color-primary); --color-disabled: #9c9c9c; + --color-disabled-lightest: #d1d1d1; --text-font-family: "Kode mono", monospace; --text-big: 32px; diff --git a/src/app/pages/online-event/online-event.component.html b/src/app/pages/online-event/online-event.component.html index d7897e1..8953418 100644 --- a/src/app/pages/online-event/online-event.component.html +++ b/src/app/pages/online-event/online-event.component.html @@ -1,83 +1,122 @@ - +
@if (event()) { -
Event : {{ event()!.name }}
-
Track : {{ track()?.fullName }}
-
Event type : {{ event()!.racesLimit ? 'Race' : 'Time-attack' }}
- @if (!event()!.racesLimit) { -
Ranking
- } @else { -
Race final ranking
- } -
- @for (ranking of rankings(); track ranking; let index = $index) { - - - } - @if (!rankings()) { -
Loading ranking
- } @else if(!rankings()?.length) { - @if (event()!.racesLimit) { -
No riders have finished all races yet
- } @else { -
No riders have completed a ride yet
- } - } +
+ Event : {{ event()!.name }} +
+
+ Track : {{ track()?.fullName }} +
+
+ Event type : + {{ + event()!.racesLimit ? "Race" : "Time-attack" + }} +
+
+ + Top 10 + + + Full ranking + +
+
+ @for (ranking of (rankingsDisplay() === 'top' ? topRankings() : + rankings()); track ranking; let index = $index) { + + + } @if (!rankings()) { +
Loading ranking
+ } @else if(!rankings()?.length) { @if (event()!.racesLimit) { +
+ No riders have finished all races yet
-
All results
-
- @for (result of results(); track result) { - - } - @if (!results()) { -
Loading results
- } @else if(!results()?.length) { -
No results yet
- } -
- @if (event()!.racesLimit) { -
Remaining races - @if (remainingRaces()?.length) { - ({{ remainingRaces()?.length }}/{{ event()!.racesLimit }}) - } -
- @for (race of remainingRaces(); track race; let index = $index) { - - } - @if (!remainingRaces()) { -
Loading remaining races
- } @else if(!remainingRaces()?.length) { -
You have completed all races
- } + } @else { +
No riders have completed a ride yet
+ } } +
+
+ + Last results + + + All results + +
+
+ @for (result of (resultsDisplay() === 'last' ? lastResults() : + results()); track result) { + + } @if (!results()) { +
Loading results
+ } @else if(!results()?.length) { +
No results yet
} - } @else { -
Loading event
+
+ @if (event()!.racesLimit) { +
+ Remaining races @if (remainingRaces()?.length) { ({{ + remainingRaces()?.length + }}/{{ event()!.racesLimit }}) } +
+ @for (race of remainingRaces(); track race; let index = $index) { + + } @if (!remainingRaces()) { +
Loading remaining races
+ } @else if(!remainingRaces()?.length) { +
You have completed all races
+ } } } @else { +
Loading event
}
diff --git a/src/app/pages/online-event/online-event.component.ts b/src/app/pages/online-event/online-event.component.ts index 0d200f5..a1da250 100644 --- a/src/app/pages/online-event/online-event.component.ts +++ b/src/app/pages/online-event/online-event.component.ts @@ -1,4 +1,12 @@ -import { ChangeDetectionStrategy, Component, computed, inject, type Signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + computed, + inject, + signal, + type WritableSignal, + type Signal +} from '@angular/core'; import { RankingLineComponent } from '../../common/components/ranking-line/ranking-line.component'; import { ToolbarComponent } from '../../common/components/toolbar/toolbar.component'; import { ButtonIconComponent } from '../../common/components/button-icon/button-icon.component'; @@ -26,9 +34,13 @@ export class OnlineEventComponent { protected event: Signal; protected track: Signal; protected results: Signal; + protected lastResults = computed(() => this.results()?.slice(0, 10)); protected rankings: Signal; + protected topRankings = computed(() => this.rankings()?.slice(0, 10)); protected remainingRaces: Signal; protected user: User | null; + protected rankingsDisplay: WritableSignal<'top' | 'full'> = signal('top'); + protected resultsDisplay: WritableSignal<'last' | 'all'> = signal('last'); private eventService = inject(EventService); private route = inject(ActivatedRoute); diff --git a/src/app/pages/server/server.component.html b/src/app/pages/server/server.component.html index 7427eb5..7c7af9f 100644 --- a/src/app/pages/server/server.component.html +++ b/src/app/pages/server/server.component.html @@ -7,55 +7,82 @@ > - +
Server : {{ server()?.name }}
-
Active riders
+
+ Most active riders + All active riders +
- @for (rider of riders(); track rider.name) { + @for (rider of (ridersDisplay() === 'active' ? activeRiders() : + riders()); track rider.name) {
{{ rider.name }}
-
{{ rider.rides }} ride{{ rider.rides > 1 ? 's' : '' }}
-
- } - @if(!riders()) { -
- Loading active riders +
+ {{ rider.rides }} ride{{ rider.rides > 1 ? "s" : "" }} +
+ } @if(!riders()) { +
Loading active riders
} @else if(!riders()?.length) { -
- No active riders yet -
+
No active riders yet
}
-
Events
+
+ Active events + All events +
@for (event of events(); track event.id) { -
+
{{ event.name }}
-
{{ event.racesLimit !== 0 ? 'Race' : 'Time-attack' }}
-
- } - @if(!events()) { -
- Loading events +
+ {{ event.racesLimit !== 0 ? "Race" : "Time-attack" }} +
+ } @if(!events()) { +
Loading events
} @else if(!events()?.length) { -
- No events available yet -
+
No events available yet
}
@if(user?.id === server()?.owner) { } diff --git a/src/app/pages/server/server.component.ts b/src/app/pages/server/server.component.ts index 866cb76..3562052 100644 --- a/src/app/pages/server/server.component.ts +++ b/src/app/pages/server/server.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject, signal, type WritableSignal } from '@angular/core'; import { ButtonIconComponent } from '../../common/components/button-icon/button-icon.component'; import { ToolbarComponent } from '../../common/components/toolbar/toolbar.component'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; @@ -29,8 +29,12 @@ export class ServerComponent { protected server = signal(null); protected riders = signal(null); + protected activeRiders = computed(() => this.riders()?.slice(0, 5)); protected events = signal(null); + protected activeEvents = computed(() => this.events()); protected user = this.authService.getUser(); + protected ridersDisplay: WritableSignal<'active' | 'all'> = signal('active'); + protected eventsDisplay: WritableSignal<'active' | 'all'> = signal('active'); constructor() { this.serverService @@ -55,8 +59,8 @@ export class ServerComponent { protected shareServer() { navigator .share({ - title: 'RetroSki invitation', - text: `Come ride with us by clicking on the link or using the server access code : ${this.serverId}`, + title: "Let's ride on RetroSki", + text: `A RetroSki server is live, and you’re invited to hit the slopes! 🎿\nClick the link to join the server or use the server code : ${this.serverId}.\nRace, challenge your friends, or simply enjoy the ride on some of the most exciting 2D alpine tracks.\nDon’t miss out, see you on the mountain! 🏁`, url: window.location.href }) .catch(() => void 0);