Skip to content

Commit bd983ef

Browse files
committed
[ongeki] Add loading animation for SongScoreRankingPage
1 parent 257e1fa commit bd983ef

File tree

5 files changed

+157
-98
lines changed

5 files changed

+157
-98
lines changed

src/app/dashboard/dashboard.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ <h4 class="placeholder mb-1" style="width: 12em"></h4>
8484
<h3 class="m-0">
8585
{{'DashboardPage.Profiles' | translate}}
8686
</h3>
87-
<code class="small">({{ currentCard || ('DashboardPage.NoBind' | translate) }})</code>
87+
<code *ngIf="!loadingProfile" class="small">({{ currentCard || ('DashboardPage.NoBind' | translate) }})</code>
8888
</div>
8989
<a *ngIf="!loadingProfile" class="more-announcements" routerLink="/cards">{{'DashboardPage.Switch' | translate}}</a>
9090
</div>

src/app/sega/ongeki/ongeki-song-score-ranking/ongeki-song-score-ranking.component.html

Lines changed: 139 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
<div class="offcanvas-header position-absolute end-0 z-3" >
1+
<div class="offcanvas-header position-absolute end-0 z-3">
22
<button type="button" class="btn-close" (click)="offcanvasService.dismiss()"></button>
33
</div>
44
<div class="offcanvas-body pt-0 px-0">
5-
<div class="music-info-container row pb-3 pt-3 gap-3 px-3 m-0" [style.--jacket-img] = "'url(' + host + 'assets/ongeki/jacket/UI_Jacket_' + (music.id|formatNumber:4) + '.webp)'">
5+
<div class="music-info-container row pb-3 pt-3 gap-3 px-3 m-0"
6+
[style.--jacket-img]="'url(' + host + 'assets/ongeki/jacket/UI_Jacket_' + (music.id|formatNumber:4) + '.webp)'">
67
<div class="col-12 p-0">
78
<img class="music-img"
89
src="{{host}}assets/ongeki/jacket/UI_Jacket_{{music.id|formatNumber:4}}.webp"
910
alt="">
1011
</div>
1112
<div class="col-12 music-info">
12-
<h4 class="music-title">{{music.name}}</h4>
13-
<div class="mb-1">{{music.artistName}}</div>
14-
<div class="text-secondary">{{music.genre}}</div>
13+
<h4 class="music-title">{{ music.name }}</h4>
14+
<div class="mb-1">{{ music.artistName }}</div>
15+
<div class="text-secondary">{{ music.genre }}</div>
1516
</div>
1617
</div>
17-
<div class="mx-3">
18-
<ng-container *ngIf="songData">
19-
<hr class="mt-0">
20-
<section *ngIf="bossCard" class="mb-2">
18+
19+
<ng-container *ngIf="bossCard">
20+
<hr class="mt-0">
21+
<div class="mx-3">
22+
<section class="mb-2">
2123
<h3 class="mb-3">{{ "Ongeki.MusicList.SongScoreRanking.Boss" | translate }}</h3>
2224
<div class="d-flex align-items-end">
2325
<img class="boss-img"
@@ -27,113 +29,152 @@ <h3 class="mb-3">{{ "Ongeki.MusicList.SongScoreRanking.Boss" | translate }}</h3>
2729
[attribute]="bossCard.attribute??''"></app-ongeki-card-level>
2830
</div>
2931
</section>
30-
</ng-container>
32+
</div>
33+
</ng-container>
34+
35+
<ng-container *ngIf="loadingSongData">
36+
<hr>
37+
<div class="text-center">
38+
<div class="spinner-border" role="status">
39+
<span class="visually-hidden">Loading...</span>
40+
</div>
41+
</div>
42+
</ng-container>
43+
<ng-container *ngIf="!loadingSongData && !songData">
44+
<hr>
45+
<div class="mx-3">
46+
<section class="mb-3">
47+
<h3 class="mb-3">{{ "Ongeki.MusicList.SongScoreRanking.Details" | translate }}</h3>
48+
<div class="alert alert-danger" role="alert">
49+
{{ "Common.FailedToLoad" | translate }}
50+
</div>
51+
</section>
52+
</div>
53+
</ng-container>
54+
<ng-container *ngIf="songData">
3155
<hr>
32-
<section class="mb-3">
33-
<h3 class="mb-3">{{ "Ongeki.MusicList.SongScoreRanking.Details" | translate }}</h3>
34-
<ng-container *ngIf="!isLunatic(music) && songData">
35-
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 0}"></ng-container>
36-
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 1}"></ng-container>
37-
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 2}"></ng-container>
38-
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 3}"></ng-container>
39-
</ng-container>
40-
<ng-container *ngIf="isLunatic(music) && songData">
41-
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 10}"></ng-container>
42-
</ng-container>
43-
</section>
44-
<h3>{{ "Ongeki.MusicList.SongScoreRanking.Ranking" | translate }}</h3>
45-
<nav>
46-
<div class="nav nav-tabs" id="nav-tab" role="tablist">
56+
<div class="mx-3">
57+
<section class="mb-3">
58+
<h3 class="mb-3">{{ "Ongeki.MusicList.SongScoreRanking.Details" | translate }}</h3>
59+
<ng-container *ngIf="!isLunatic(music) && songData">
60+
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 0}"></ng-container>
61+
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 1}"></ng-container>
62+
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 2}"></ng-container>
63+
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 3}"></ng-container>
64+
</ng-container>
65+
<ng-container *ngIf="isLunatic(music) && songData">
66+
<ng-container *ngTemplateOutlet="difficultyDetail; context: {$implicit: 10}"></ng-container>
67+
</ng-container>
68+
</section>
69+
</div>
70+
<hr>
71+
<div class="mx-3">
72+
<h3>{{ "Ongeki.MusicList.SongScoreRanking.Ranking" | translate }}</h3>
73+
<nav>
74+
<div class="nav nav-tabs" id="nav-tab" role="tablist">
75+
<ng-container *ngIf="music.id < 8e3 && songData">
76+
<button class="nav-link" id="nav-ba-tab" (click)="handleTabButtonClick(0)" data-bs-toggle="tab"
77+
data-bs-target="#nav-ba" type="button" role="tab" aria-controls="nav-ba" aria-selected="false">BA
78+
</button>
79+
<button class="nav-link" id="nav-ad-tab" (click)="handleTabButtonClick(1)" data-bs-toggle="tab"
80+
data-bs-target="#nav-ad" type="button" role="tab" aria-controls="nav-ad" aria-selected="false">AD
81+
</button>
82+
<button class="nav-link" id="nav-ex-tab" (click)="handleTabButtonClick(2)" data-bs-toggle="tab"
83+
data-bs-target="#nav-ex" type="button" role="tab" aria-controls="nav-ex" aria-selected="false">EX
84+
</button>
85+
<button class="nav-link active" id="nav-ma-tab" (click)="handleTabButtonClick(3)" data-bs-toggle="tab"
86+
data-bs-target="#nav-ma" type="button" role="tab" aria-controls="nav-ma" aria-selected="true">MA
87+
</button>
88+
</ng-container>
89+
<ng-container *ngIf="music.id > 8e3 && songData">
90+
<button class="nav-link active" id="nav-lu-tab" (click)="handleTabButtonClick(10)" data-bs-toggle="tab"
91+
data-bs-target="#nav-lu" type="button" role="tab" aria-controls="nav-lu" aria-selected="true">LUNATIC
92+
</button>
93+
</ng-container>
94+
</div>
95+
</nav>
96+
<div class="tab-content" id="nav-tabContent">
4797
<ng-container *ngIf="music.id < 8e3 && songData">
48-
<button class="nav-link" id="nav-ba-tab" (click)="handleTabButtonClick(0)" data-bs-toggle="tab" data-bs-target="#nav-ba" type="button" role="tab" aria-controls="nav-ba" aria-selected="false">BA</button>
49-
<button class="nav-link" id="nav-ad-tab" (click)="handleTabButtonClick(1)" data-bs-toggle="tab" data-bs-target="#nav-ad" type="button" role="tab" aria-controls="nav-ad" aria-selected="false">AD</button>
50-
<button class="nav-link" id="nav-ex-tab" (click)="handleTabButtonClick(2)" data-bs-toggle="tab" data-bs-target="#nav-ex" type="button" role="tab" aria-controls="nav-ex" aria-selected="false">EX</button>
51-
<button class="nav-link active" id="nav-ma-tab" (click)="handleTabButtonClick(3)" data-bs-toggle="tab" data-bs-target="#nav-ma" type="button" role="tab" aria-controls="nav-ma" aria-selected="true">MA</button>
98+
<div class="tab-pane fade" id="nav-ba" role="tabpanel" aria-labelledby="nav-ba-tab" tabindex="0">
99+
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[0]?.ranking}"/>
100+
</div>
101+
<div class="tab-pane fade" id="nav-ad" role="tabpanel" aria-labelledby="nav-ad-tab" tabindex="0">
102+
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[1]?.ranking}"/>
103+
</div>
104+
<div class="tab-pane fade" id="nav-ex" role="tabpanel" aria-labelledby="nav-ex-tab" tabindex="0">
105+
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[2]?.ranking}"/>
106+
</div>
107+
<div class="tab-pane fade show active" id="nav-ma" aria-labelledby="nav-ma-tab" tabindex="0">
108+
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[3]?.ranking}"/>
109+
</div>
52110
</ng-container>
53111
<ng-container *ngIf="music.id > 8e3 && songData">
54-
<button class="nav-link active" id="nav-lu-tab" (click)="handleTabButtonClick(10)" data-bs-toggle="tab"data-bs-target="#nav-lu" type="button" role="tab" aria-controls="nav-lu" aria-selected="true">LUNATIC</button>
112+
<div class="tab-pane fade show active" id="nav-ma" aria-labelledby="nav-ma-tab" tabindex="0">
113+
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[10]?.ranking}"/>
114+
</div>
55115
</ng-container>
56116
</div>
57-
</nav>
58-
<div class="tab-content" id="nav-tabContent">
59-
<ng-container *ngIf="music.id < 8e3 && songData">
60-
<div class="tab-pane fade" id="nav-ba" role="tabpanel" aria-labelledby="nav-ba-tab" tabindex="0">
61-
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[0]?.ranking}"/>
62-
</div>
63-
<div class="tab-pane fade" id="nav-ad" role="tabpanel" aria-labelledby="nav-ad-tab" tabindex="0">
64-
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[1]?.ranking}"/>
65-
</div>
66-
<div class="tab-pane fade" id="nav-ex" role="tabpanel" aria-labelledby="nav-ex-tab" tabindex="0">
67-
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[2]?.ranking}"/>
68-
</div>
69-
<div class="tab-pane fade show active" id="nav-ma" aria-labelledby="nav-ma-tab" tabindex="0">
70-
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[3]?.ranking}"/>
71-
</div>
72-
</ng-container>
73-
<ng-container *ngIf="music.id > 8e3 && songData">
74-
<div class="tab-pane fade show active" id="nav-ma" aria-labelledby="nav-ma-tab" tabindex="0">
75-
<ng-container *ngTemplateOutlet="rankingTable;context: {playerRanking: songData[10]?.ranking}"/>
76-
</div>
77-
</ng-container>
78117
</div>
79-
</div>
118+
</ng-container>
80119
</div>
81120

82121
<ng-template #difficultyDetail let-difficulty>
83122
<div class="card my-2">
84-
<ng-container [ngSwitch]="difficulty">
85-
<div *ngSwitchCase="0" class="card-header py-1 px-2 text-truncate">
86-
<div class="hstack">
87-
<ng-icon name="bootstrap-stop-fill" class="color-basic h-100 d-flex align-items-center"></ng-icon>
88-
<div class="p-0 align-middle ps-1 small">
89-
Basic
90-
{{getLevelString(music, difficulty) | toLevelDecimal}}
91-
</div>
123+
<ng-container [ngSwitch]="difficulty">
124+
<div *ngSwitchCase="0" class="card-header py-1 px-2 text-truncate">
125+
<div class="hstack">
126+
<ng-icon name="bootstrap-stop-fill" class="color-basic h-100 d-flex align-items-center"></ng-icon>
127+
<div class="p-0 align-middle ps-1 small">
128+
Basic
129+
{{ getLevelString(music, difficulty) | toLevelDecimal }}
92130
</div>
93131
</div>
94-
<div *ngSwitchCase="1" class="card-header py-1 px-2 text-truncate">
95-
<div class="hstack">
96-
<ng-icon name="bootstrap-stop-fill" class="color-advanced h-100 d-flex align-items-center"></ng-icon>
97-
<div class="p-0 align-middle ps-1 small">
98-
Advanced
99-
{{getLevelString(music, difficulty) | toLevelDecimal}}
100-
</div>
132+
</div>
133+
<div *ngSwitchCase="1" class="card-header py-1 px-2 text-truncate">
134+
<div class="hstack">
135+
<ng-icon name="bootstrap-stop-fill" class="color-advanced h-100 d-flex align-items-center"></ng-icon>
136+
<div class="p-0 align-middle ps-1 small">
137+
Advanced
138+
{{ getLevelString(music, difficulty) | toLevelDecimal }}
101139
</div>
102140
</div>
103-
<div *ngSwitchCase="2" class="card-header py-1 px-2 text-truncate">
104-
<div class="hstack">
105-
<ng-icon name="bootstrap-stop-fill" class="color-expert h-100 d-flex align-items-center"></ng-icon>
106-
<div class="p-0 align-middle ps-1 small">
107-
Expert
108-
{{getLevelString(music, difficulty) | toLevelDecimal}}
109-
</div>
141+
</div>
142+
<div *ngSwitchCase="2" class="card-header py-1 px-2 text-truncate">
143+
<div class="hstack">
144+
<ng-icon name="bootstrap-stop-fill" class="color-expert h-100 d-flex align-items-center"></ng-icon>
145+
<div class="p-0 align-middle ps-1 small">
146+
Expert
147+
{{ getLevelString(music, difficulty) | toLevelDecimal }}
110148
</div>
111149
</div>
112-
<div *ngSwitchCase="3" class="card-header py-1 px-2 text-truncate">
113-
<div class="hstack">
114-
<ng-icon name="bootstrap-stop-fill" class="color-master h-100 d-flex align-items-center"></ng-icon>
115-
<div class="p-0 align-middle ps-1 small">
116-
Master
117-
{{getLevelString(music, difficulty) | toLevelDecimal}}
118-
</div>
150+
</div>
151+
<div *ngSwitchCase="3" class="card-header py-1 px-2 text-truncate">
152+
<div class="hstack">
153+
<ng-icon name="bootstrap-stop-fill" class="color-master h-100 d-flex align-items-center"></ng-icon>
154+
<div class="p-0 align-middle ps-1 small">
155+
Master
156+
{{ getLevelString(music, difficulty) | toLevelDecimal }}
119157
</div>
120158
</div>
121-
<div *ngSwitchCase="10" class="card-header py-1 px-2 text-truncate border border-danger bg-lunatic">
122-
<div class="hstack text-danger">
123-
<ng-icon name="bootstrap-stop-fill" class="h-100 d-flex align-items-center"></ng-icon>
124-
<div class="p-0 align-middle ps-1 small">
125-
Lunatic
126-
{{getLevelString(music, difficulty) | toLevelDecimal}}
127-
</div>
159+
</div>
160+
<div *ngSwitchCase="10" class="card-header py-1 px-2 text-truncate border border-danger bg-lunatic">
161+
<div class="hstack text-danger">
162+
<ng-icon name="bootstrap-stop-fill" class="h-100 d-flex align-items-center"></ng-icon>
163+
<div class="p-0 align-middle ps-1 small">
164+
Lunatic
165+
{{ getLevelString(music, difficulty) | toLevelDecimal }}
128166
</div>
129167
</div>
130-
</ng-container>
168+
</div>
169+
</ng-container>
131170
<div class="card-body py-1 px-3">
132171
<div class="difficulty-detail-body d-flex align-items-center justify-content-between">
133172
<div class="float-start small fw-bold">
134173
<div *ngIf="songData[difficulty]">
135-
<div>{{songData[difficulty].techScoreMax}}</div>
136-
<div class="small text-secondary">{{ "Ongeki.MusicList.SongScoreRanking.PlayCount" | translate }}{{ "Common.Colon" | translate }}{{ songData[difficulty].playCount }}</div>
174+
<div>{{ songData[difficulty].techScoreMax }}</div>
175+
<div
176+
class="small text-secondary">{{ "Ongeki.MusicList.SongScoreRanking.PlayCount" | translate }}{{ "Common.Colon" | translate }}{{ songData[difficulty].playCount }}
177+
</div>
137178
</div>
138179
<div *ngIf="!songData[difficulty]">
139180
<div>No Record</div>
@@ -165,7 +206,12 @@ <h3>{{ "Ongeki.MusicList.SongScoreRanking.Ranking" | translate }}</h3>
165206

166207
<ng-template #rankingTable let-playerRanking="playerRanking">
167208
<div *ngIf="playerRanking" class="callout callout-info mt-2 mb-1">
168-
{{"Ongeki.MusicList.SongScoreRanking.RankingInfo" | translate: {ranking: (playerRanking.rank | ordinal),total: playerRanking.playedCount} }}
209+
{{
210+
"Ongeki.MusicList.SongScoreRanking.RankingInfo" | translate: {
211+
ranking: (playerRanking.rank | ordinal),
212+
total: playerRanking.playedCount
213+
}
214+
}}
169215
</div>
170216
<table class="table table-striped table-borderless mb-0">
171217
<thead>
@@ -183,7 +229,7 @@ <h3>{{ "Ongeki.MusicList.SongScoreRanking.Ranking" | translate }}</h3>
183229
{{ i + 1 }}
184230
</span>
185231
</td>
186-
<td>{{ item.username | fullWidth}}</td>
232+
<td>{{ item.username | fullWidth }}</td>
187233
<td>{{ item.score }}</td>
188234
</tr>
189235
</tbody>

src/app/sega/ongeki/ongeki-song-score-ranking/ongeki-song-score-ranking.component.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {HttpParams} from '@angular/common/http';
88
import { UserService } from 'src/app/user.service';
99
import {NgxIndexedDBService} from 'ngx-indexed-db';
1010
import {OngekiCard} from '../model/OngekiCard';
11+
import {TranslateService} from '@ngx-translate/core';
1112

1213
interface Ranking {
1314
level?: number;
@@ -50,6 +51,7 @@ export class OngekiSongScoreRankingComponent {
5051
protected readonly Math = Math;
5152
ranking: Ranking[];
5253
songData: {[key: number]: ISongData};
54+
loadingSongData = true;
5355
host = environment.assetsHost;
5456
protected readonly parseFloat = parseFloat;
5557
@Input() public music: OngekiMusic;
@@ -58,6 +60,7 @@ export class OngekiSongScoreRankingComponent {
5860
private dbService: NgxIndexedDBService,
5961
private api: ApiService,
6062
private userService: UserService,
63+
private translate: TranslateService,
6164
public messageService: MessageService,
6265
public offcanvasService: NgbOffcanvas,
6366
) {
@@ -69,14 +72,22 @@ export class OngekiSongScoreRankingComponent {
6972
});
7073

7174
const { id } = this.music;
72-
this.api.get(`api/game/ongeki/song/${id}?aimeId=${String(this.userService.currentUser.defaultCard.extId)}`).subscribe(
73-
res => {
75+
this.api.get(`api/game/ongeki/song/${id}?aimeId=${String(this.userService.currentUser.defaultCard.extId)}`).subscribe({
76+
next: (res) => {
7477
const songData = {};
7578
for (const data of res) {
7679
songData[data.level] = data;
7780
}
7881
this.songData = songData;
82+
this.loadingSongData = false;
83+
},
84+
error: (err) => {
85+
this.translate.get('Common.FailedToLoad').subscribe((res: string) => {
86+
this.messageService.notice(res, 'danger');
87+
});
88+
this.loadingSongData = false;
7989
}
90+
}
8091
);
8192

8293
if (!this.isLunatic(this.music)){

src/assets/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"ChuniV2": "CHUNITHM NEW",
55
"Mai2": "Maimai DX",
66
"Colon": ": ",
7-
"OK": "OK"
7+
"OK": "OK",
8+
"FailedToLoad": "Failed to load"
89
},
910
"App": {
1011
"Footer": {

src/assets/i18n/zh.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"ChuniV2": "中二节奏NEW",
55
"Mai2": "舞萌DX",
66
"Colon": "",
7-
"OK": "确定"
7+
"OK": "确定",
8+
"FailedToLoad": "加载失败"
89
},
910
"App": {
1011
"Footer": {

0 commit comments

Comments
 (0)