Skip to content

Commit 257e1fa

Browse files
committed
[chusan] Update filter for music list
1 parent 4bbb3b6 commit 257e1fa

File tree

5 files changed

+126
-29
lines changed

5 files changed

+126
-29
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ This project was generated with [Angular CLI](https://github.com/angular/angular
88

99
## Develop with CDN
1010

11-
- Add the following rule to your hosts file: <br>
12-
`127.0.0.1 portal-dev.naominet.live`
1311
- Change `proxy.conf.json` if needed
1412
- Launch the development server with the command: <br>`$ npm run start `
1513
- Visit [https://portal-dev.naominet.live](https://portal-dev.naominet.live).

src/app/sega/chunithm/v2/v2-songlist/v2-songlist.component.html

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<h1 class="page-heading">Music List</h1>
1+
<h1 class="page-heading">{{ "ChuniV2.MusicListPage.Title" | translate }}</h1>
22

33
<ng-template #pagination>
44
<pagination-template *ngIf="true" #p="paginationApi" class="user-select-none" id="server" maxSize="7"
@@ -19,20 +19,44 @@ <h1 class="page-heading">Music List</h1>
1919
</ul>
2020
</pagination-template>
2121
</ng-template>
22-
<ng-container *ngTemplateOutlet="pagination;"></ng-container>
23-
24-
<div class="row justify-content-start mb-2 g-2">
25-
<div *ngFor="let genre of genres; let i = index" class="col-auto">
26-
<input type="checkbox" class="form-check-input checkbox-btn" [value]="genre" [id]="'genre' + i" [formControl]="genreControls.controls[i]">
27-
<label class="checkbox-label" [for]="'genre' + i">{{genresMap.get(genre)}}</label>
22+
<div class="collapse" id="filterCollapse">
23+
<div class="row mb-2 g-1">
24+
<div class="col-12 col-sm-auto pt-1 me-3">{{'ChuniV2.MusicListPage.ReleaseVersion' | translate}}</div>
25+
<div class="col-12 col-sm">
26+
<div class="row justify-content-start align-items-center g-1">
27+
<div *ngFor="let version of releaseTagService.releaseTags; let i = index" class="col-auto">
28+
<input type="checkbox" class="form-check-input checkbox-btn" [value]="version" [id]="'version' + i" [formControl]="versionControls.controls[i]">
29+
<label class="checkbox-label" [for]="'version' + i">{{releaseTagService.releaseTagMap.get(version)}}</label>
30+
</div>
31+
</div>
32+
</div>
33+
</div>
34+
<div class="row mb-2 g-1">
35+
<div class="col-12 col-sm-auto pt-1 me-3">分类</div>
36+
<div class="col-12 col-sm">
37+
<div class="row justify-content-start align-items-center g-1">
38+
<div *ngFor="let genre of genres; let i = index" class="col-auto">
39+
<input type="checkbox" class="form-check-input checkbox-btn" [value]="genre" [id]="'genre' + i" [formControl]="genreControls.controls[i]">
40+
<label class="checkbox-label" [for]="'genre' + i">{{genreMap.get(genre)}}</label>
41+
</div>
42+
</div>
43+
</div>
2844
</div>
29-
<div class="col-auto">
30-
<input type="checkbox" class="form-check-input checkbox-btn" value="lunatic" id="lunatic" [formControl]="weControl">
31-
<label class="checkbox-label" for="lunatic">World's End</label>
45+
46+
<div class="row mb-2 g-1">
47+
<div class="col-12 p-0">
48+
<input type="text" #search class="form-control form-control-sm" placeholder="{{'ChuniV2.MusicListPage.FilterPlaceholder' | translate}}" [formControl]="patternControl">
49+
</div>
3250
</div>
3351
</div>
3452

35-
<input type="text" #search class="form-control mb-2" placeholder="Filter" [formControl]="patternControl">
53+
<div *ngIf="filteredSongList" class="mb-2">
54+
<span>{{'ChuniV2.MusicListPage.TotalSongNum' | translate: {num: totalElements} }}</span>
55+
<a class="link-btn ms-3" (click)="toggleFilter()">{{filterCollapsed?('ChuniV2.MusicListPage.ShowFilter' | translate):('ChuniV2.MusicListPage.HideFilter' | translate)}}</a>
56+
<a *ngIf="!isDefaultFilter()" class="link-btn ms-3" (click)="resetFilter()">{{'ChuniV2.MusicListPage.ResetFilter' | translate}}</a>
57+
</div>
58+
59+
<ng-container *ngTemplateOutlet="pagination;"></ng-container>
3660

3761
<div class="card-btn card mb-2 text-start user-select-none" (click)="showDetail(item)"
3862
*ngFor="let item of filteredSongList | async | paginate: { id: 'server', itemsPerPage: 15, currentPage: currentPage, totalItems: totalElements }">

src/app/sega/chunithm/v2/v2-songlist/v2-songlist.component.ts

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {NgbOffcanvas} from '@ng-bootstrap/ng-bootstrap';
99
import {V2SongScoreRankingComponent} from '../v2-song-score-ranking/v2-song-score-ranking.component';
1010
import {FormArray, FormControl} from '@angular/forms';
1111
import {combineLatest, debounceTime, distinctUntilChanged, lastValueFrom, map, Observable, startWith} from 'rxjs';
12+
import {Collapse} from 'bootstrap';
13+
import {ReleaseTagService} from '../util/release-tag.service';
1214

1315

1416
@Component({
@@ -18,34 +20,41 @@ import {combineLatest, debounceTime, distinctUntilChanged, lastValueFrom, map, O
1820
})
1921
export class V2SonglistComponent implements OnInit {
2022

21-
genres = ['POPS_ANIME', 'NICONICO', 'TOUHOU', 'VARIETY', 'GEKICHUMA', 'IRODORI', 'ORIGINAL'];
22-
genresMap = new Map([
23+
filterCollapsed = true;
24+
filterCollapse: Collapse;
25+
songList: ChusanMusic[] = [];
26+
filteredSongList: Observable<ChusanMusic[]>;
27+
displayedColumns: string[] = ['musicId', 'name', 'artistName'];
28+
host = environment.assetsHost;
29+
30+
genreMap = new Map([
2331
['POPS_ANIME', 'POPS & ANIME'],
2432
['NICONICO', 'niconico'],
2533
['TOUHOU', '東方Project'],
2634
['VARIETY', 'VARIETY'],
27-
['GEKICHUMA', 'ゲキマイ'],
2835
['IRODORI', 'イロドリミドリ'],
36+
['GEKICHUMA', 'ゲキマイ'],
2937
['ORIGINAL', 'ORIGINAL']
3038
]);
31-
songList: ChusanMusic[] = [];
32-
filteredSongList: Observable<ChusanMusic[]>;
33-
displayedColumns: string[] = ['musicId', 'name', 'artistName'];
34-
host = environment.assetsHost;
39+
genres: string[] = [...this.genreMap.keys()];
40+
3541
currentPage: 1;
3642
totalElements = 0;
43+
versionControls = new FormArray<FormControl<boolean>>([]);
3744
genreControls = new FormArray<FormControl<boolean>>([]);
3845
weControl = new FormControl(false);
3946
patternControl = new FormControl('');
4047

4148
constructor(
49+
public releaseTagService: ReleaseTagService,
50+
public router: Router,
51+
public route: ActivatedRoute,
4252
private dbService: NgxIndexedDBService,
4353
private api: ApiService,
4454
private messageService: MessageService,
45-
public router: Router,
46-
public route: ActivatedRoute,
4755
private offcanvasService: NgbOffcanvas,
4856
) {
57+
this.releaseTagService.releaseTags.forEach(() => this.versionControls.push(new FormControl(false)));
4958
this.genres.forEach(() => this.genreControls.push(new FormControl(false)));
5059
}
5160

@@ -63,27 +72,44 @@ export class V2SonglistComponent implements OnInit {
6372

6473
this.filteredSongList = combineLatest([
6574
this.genreControls.valueChanges.pipe(startWith(new Array<boolean>())),
75+
this.versionControls.valueChanges.pipe(startWith(new Array<boolean>())),
6676
this.patternControl.valueChanges.pipe(startWith('')),
6777
this.weControl.valueChanges.pipe(startWith(false)),
6878
]).pipe(
6979
debounceTime(200),
7080
distinctUntilChanged(),
71-
map(([genreValues, pattern, weChecked]) => {
81+
map(([genreValues, versionValues, pattern, weChecked]) => {
82+
let selectedVersions = this.releaseTagService.releaseTags.filter((_, index) => versionValues[index]);
83+
if (selectedVersions.length === 0 && !weChecked){
84+
selectedVersions = this.releaseTagService.releaseTags;
85+
}
86+
7287
let selectedGenres = this.genres.filter((_, index) => genreValues[index]);
7388
if (selectedGenres.length === 0 && !weChecked){
7489
selectedGenres = this.genres;
7590
}
7691

77-
let filtered = this.songList;
78-
if (selectedGenres.length !== this.genres.length){
79-
filtered = filtered.filter(song => selectedGenres.includes(song.genre) || (weChecked && song.levels['5'].enable));
80-
}
81-
filtered = filtered.filter(song => this.filterByPattern(song, pattern));
82-
return filtered;
92+
return this.filterSongs(selectedGenres, selectedVersions, weChecked, pattern);
8393
})
8494
);
8595
}
8696

97+
filterSongs(selectedGenres: string[], selectedVersions: string[], weChecked: boolean, pattern: string){
98+
let filtered = this.songList;
99+
if (weChecked){
100+
filtered = filtered.filter(song => song.levels['5'].enable);
101+
}
102+
if (selectedVersions.length !== this.releaseTagService.releaseTags.length){
103+
filtered = filtered.filter(song => selectedVersions.includes(song.releaseVersion));
104+
}
105+
if (selectedGenres.length !== this.genreMap.size){
106+
filtered = filtered.filter(song => selectedGenres.includes(song.genre));
107+
}
108+
filtered = filtered.filter(song => this.filterByPattern(song, pattern));
109+
this.totalElements = filtered.length;
110+
return filtered;
111+
}
112+
87113
pageChanged(page: number) {
88114
this.router.navigate(['chuni/v2/song'], {queryParams: {page}});
89115
}
@@ -97,6 +123,37 @@ export class V2SonglistComponent implements OnInit {
97123
return sameId || includesName || includesArtist;
98124
}
99125

126+
resetFilter() {
127+
this.weControl.setValue(false);
128+
this.genreControls.controls.forEach(c => c.setValue(false));
129+
this.versionControls.controls.forEach(c => c.setValue(false));
130+
this.patternControl.setValue('');
131+
}
132+
133+
isDefaultFilter() {
134+
return this.weControl.value === false &&
135+
this.genreControls.controls.every(c => c.value === false) &&
136+
this.genreControls.controls.every(c => c.value === false) &&
137+
this.patternControl.value === '';
138+
}
139+
140+
toggleFilter() {
141+
if (!this.filterCollapse){
142+
const collapseElement = document.getElementById('filterCollapse');
143+
if (collapseElement) {
144+
this.filterCollapse = new Collapse(collapseElement, {toggle: false});
145+
}
146+
}
147+
if (this.filterCollapsed){
148+
this.filterCollapse.show();
149+
this.filterCollapsed = false;
150+
}
151+
else{
152+
this.filterCollapse.hide();
153+
this.filterCollapsed = true;
154+
}
155+
}
156+
100157
showDetail(music: ChusanMusic) {
101158
const offcanvasRef = this.offcanvasService.open(V2SongScoreRankingComponent, {
102159
position: 'end',

src/assets/i18n/en.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,15 @@
444444
"MessageSuccess": "Successfully changed.",
445445
"MessageFailed": "Failed to change item."
446446
},
447+
"MusicListPage": {
448+
"Title": "Music List",
449+
"ReleaseVersion": "Release Version",
450+
"TotalSongNum": "Total {{num}} Songs",
451+
"ShowFilter": "Show Filter",
452+
"HideFilter": "Hide Filter",
453+
"ResetFilter": "Reset Filter",
454+
"FilterPlaceholder": "ID, Name, Artist"
455+
},
447456
"RivalPage": {
448457
"Title": "Rival",
449458
"IDInputPlaceholder": "Rival Card ID",

src/assets/i18n/zh.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,15 @@
444444
"MessageSuccess": "更换成功",
445445
"MessageFailed": "更换失败"
446446
},
447+
"MusicListPage": {
448+
"Title": "乐曲列表",
449+
"ReleaseVersion": "发布版本",
450+
"TotalSongNum": "共 {{num}} 首乐曲",
451+
"ShowFilter": "显示过滤",
452+
"HideFilter": "隐藏过滤",
453+
"ResetFilter": "重置过滤",
454+
"FilterPlaceholder": "ID, 曲名, 作者"
455+
},
447456
"RivalPage": {
448457
"Title": "好友",
449458
"IDInputPlaceholder": "好友ID",

0 commit comments

Comments
 (0)