Add compact table and update themes

This commit is contained in:
Geomitron
2023-12-25 11:23:50 -06:00
parent f931a1b221
commit 0abf801c7e
9 changed files with 99 additions and 68 deletions

View File

@@ -1,11 +1,6 @@
<app-search-bar /> <app-search-bar />
<div class="flex flex-1 overflow-hidden"> <div class="flex flex-1 overflow-hidden">
<div <app-result-table #resultTable (rowClicked)="chartSidebar.onRowClicked($event)" />
#resultTableDiv
class="basis-2/3 flex-1 overflow-y-auto scrollbar scrollbar-w-2 scrollbar-h-2 scrollbar-track-base-300 scrollbar-thumb-neutral scrollbar-thumb-rounded-full"
(scroll)="resultTable.tableScrolled($event)">
<app-result-table #resultTable (rowClicked)="chartSidebar.onRowClicked($event)" />
</div>
<div class="basis-1/3 min-w-[310px] max-w-[512px]"> <div class="basis-1/3 min-w-[310px] max-w-[512px]">
<app-chart-sidebar #chartSidebar /> <app-chart-sidebar #chartSidebar />
</div> </div>

View File

@@ -1,21 +1,9 @@
import { AfterViewInit, Component, ElementRef, HostBinding, ViewChild } from '@angular/core' import { Component, HostBinding } from '@angular/core'
import { SearchService } from 'src-angular/app/core/services/search.service'
@Component({ @Component({
selector: 'app-browse', selector: 'app-browse',
templateUrl: './browse.component.html', templateUrl: './browse.component.html',
}) })
export class BrowseComponent implements AfterViewInit { export class BrowseComponent {
@HostBinding('class.contents') contents = true @HostBinding('class.contents') contents = true
@ViewChild('resultTableDiv', { static: true }) resultTableDiv: ElementRef
constructor(private searchService: SearchService) { }
ngAfterViewInit() {
this.searchService.newSearch.subscribe(() => {
this.resultTableDiv.nativeElement.scrollTop = 0
})
}
} }

View File

@@ -1,35 +1,40 @@
<table id="resultTable" class="table table-zebra table-pin-rows"> <div
<thead> #resultTableDiv
<tr> class="basis-2/3 flex-1 overflow-y-auto scrollbar scrollbar-w-2 scrollbar-h-2 scrollbar-track-base-300 scrollbar-thumb-neutral scrollbar-thumb-rounded-full"
<th class="collapsing" id="checkboxColumn"> (scroll)="tableScrolled()">
<input type="checkbox" class="checkbox" [(ngModel)]="allSelected" /> <table id="resultTable" class="table table-zebra table-pin-rows" [class.table-xs]="settingsService.isCompactTable">
</th> <thead>
<th [ngClass]="sortDirection" (click)="onColClicked('name')"> <tr>
Name <i *ngIf="sortColumn === 'name'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i> <th class="collapsing" id="checkboxColumn">
</th> <input type="checkbox" class="checkbox" [(ngModel)]="allSelected" />
<th [ngClass]="sortDirection" (click)="onColClicked('artist')"> </th>
Artist <th [ngClass]="sortDirection" (click)="onColClicked('name')">
<i *ngIf="sortColumn === 'artist'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i> Name <i *ngIf="sortColumn === 'name'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i>
</th> </th>
<th [ngClass]="sortDirection" (click)="onColClicked('album')"> <th [ngClass]="sortDirection" (click)="onColClicked('artist')">
Album <i *ngIf="sortColumn === 'album'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i> Artist
</th> <i *ngIf="sortColumn === 'artist'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i>
<th [ngClass]="sortDirection" (click)="onColClicked('genre')"> </th>
Genre <i *ngIf="sortColumn === 'genre'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i> <th [ngClass]="sortDirection" (click)="onColClicked('album')">
</th> Album <i *ngIf="sortColumn === 'album'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i>
<th [ngClass]="sortDirection" (click)="onColClicked('year')"> </th>
Year <i *ngIf="sortColumn === 'year'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i> <th [ngClass]="sortDirection" (click)="onColClicked('genre')">
</th> Genre <i *ngIf="sortColumn === 'genre'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i>
</tr> </th>
</thead> <th [ngClass]="sortDirection" (click)="onColClicked('year')">
<tbody> Year <i *ngIf="sortColumn === 'year'" class="bi bi-caret-{{ sortDirection === 'ascending' ? 'down' : 'up' }}-fill"></i>
@for (song of songs; track song) { </th>
<tr </tr>
app-result-table-row </thead>
(click)="onRowClicked(song)" <tbody>
[class.!bg-neutral]="activeSong === song" @for (song of songs; track song) {
[class.!text-neutral-content]="activeSong === song" <tr
[song]="song"></tr> app-result-table-row
} (click)="onRowClicked(song)"
</tbody> [class.!bg-neutral]="activeSong === song"
</table> [class.!text-neutral-content]="activeSong === song"
[song]="song"></tr>
}
</tbody>
</table>
</div>

View File

@@ -1,4 +1,4 @@
import { Component, EventEmitter, HostBinding, OnInit, Output, QueryList, ViewChildren } from '@angular/core' import { Component, ElementRef, EventEmitter, HostBinding, HostListener, OnInit, Output, QueryList, ViewChild, ViewChildren } from '@angular/core'
import { sortBy } from 'lodash' import { sortBy } from 'lodash'
import { SettingsService } from 'src-angular/app/core/services/settings.service' import { SettingsService } from 'src-angular/app/core/services/settings.service'
@@ -17,6 +17,7 @@ export class ResultTableComponent implements OnInit {
@Output() rowClicked = new EventEmitter<ChartData[]>() @Output() rowClicked = new EventEmitter<ChartData[]>()
@ViewChild('resultTableDiv', { static: true }) resultTableDiv: ElementRef
@ViewChildren('tableRow') tableRows: QueryList<ResultTableRowComponent> @ViewChildren('tableRow') tableRows: QueryList<ResultTableRowComponent>
activeSong: ChartData[] | null = null activeSong: ChartData[] | null = null
@@ -31,13 +32,16 @@ export class ResultTableComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.searchService.newSearch.subscribe(() => { this.searchService.newSearch.subscribe(() => {
this.resultTableDiv.nativeElement.scrollTop = 0
this.activeSong = null this.activeSong = null
this.sortDirection = 'ascending' this.sortDirection = 'ascending'
this.sortColumn = null this.sortColumn = null
this.updateSort() this.updateSort()
setTimeout(() => this.tableScrolled(), 0)
}) })
this.searchService.updateSearch.subscribe(() => { this.searchService.updateSearch.subscribe(() => {
this.updateSort() this.updateSort()
setTimeout(() => this.tableScrolled(), 0)
}) })
} }
@@ -85,13 +89,16 @@ export class ResultTableComponent implements OnInit {
} }
} }
tableScrolled(event: Event): void { @HostListener('window:resize', ['$event'])
if (event.target instanceof HTMLElement) { onResize() {
if (event.target.scrollHeight - (event.target.scrollTop + event.target.clientHeight) < 100) { this.tableScrolled()
// Scrolled near the bottom of the table }
if (this.searchService.areMorePages && !this.searchService.searchLoading) { tableScrolled(): void {
this.searchService.search(this.searchService.searchControl.value || '*', true).subscribe() const table = this.resultTableDiv.nativeElement
} if (table.scrollHeight - (table.scrollTop + table.clientHeight) < 100) {
// Scrolled near the bottom of the table
if (this.searchService.areMorePages && !this.searchService.searchLoading) {
this.searchService.search(this.searchService.searchControl.value || '*', true).subscribe()
} }
} }
} }

View File

@@ -29,8 +29,9 @@
<ul> <ul>
<li><a (click)="setTheme('business')">Business</a></li> <li><a (click)="setTheme('business')">Business</a></li>
<li><a (click)="setTheme('dark')">Dark</a></li> <li><a (click)="setTheme('dark')">Dark</a></li>
<li><a (click)="setTheme('halloween')">Halloween</a></li> <li><a (click)="setTheme('dim')">Dim</a></li>
<li><a (click)="setTheme('night')">Night</a></li> <li><a (click)="setTheme('night')">Night</a></li>
<li><a (click)="setTheme('sunset')">Sunset</a></li>
<li><a (click)="setTheme('synthwave')">Synthwave</a></li> <li><a (click)="setTheme('synthwave')">Synthwave</a></li>
</ul> </ul>
</li> </li>
@@ -40,6 +41,7 @@
<li><a (click)="setTheme('aqua')">Aqua</a></li> <li><a (click)="setTheme('aqua')">Aqua</a></li>
<li><a (click)="setTheme('emerald')">Emerald</a></li> <li><a (click)="setTheme('emerald')">Emerald</a></li>
<li><a (click)="setTheme('lemonade')">Lemonade</a></li> <li><a (click)="setTheme('lemonade')">Lemonade</a></li>
<li><a (click)="setTheme('nord')">Nord</a></li>
<li><a (click)="setTheme('valentine')">Valentine</a></li> <li><a (click)="setTheme('valentine')">Valentine</a></li>
<li><a (click)="setTheme('winter')">Winter</a></li> <li><a (click)="setTheme('winter')">Winter</a></li>
</ul> </ul>
@@ -94,17 +96,34 @@
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<label class="label cursor-pointer"> <label class="label cursor-pointer">
<input type="radio" class="radio radio-secondary mr-2" [value]="true" [formControl]="isSng" /> <input type="radio" name="isSng" class="radio radio-secondary mr-2" [value]="true" [formControl]="isSng" />
.sng .sng
</label> </label>
<label class="label cursor-pointer"> <label class="label cursor-pointer">
<input type="radio" class="radio radio-secondary mr-2" [value]="false" [formControl]="isSng" /> <input type="radio" name="isSng" class="radio radio-secondary mr-2" [value]="false" [formControl]="isSng" />
.zip .zip
</label> </label>
</div> </div>
</div> </div>
<div class="form-control">
<div class="label">
<span class="label-text">Table Layout</span>
</div>
<div class="flex gap-2">
<label class="label cursor-pointer">
<input type="radio" name="isCompactTable" class="radio radio-secondary mr-2" [value]="false" [formControl]="isCompactTable" />
Default
</label>
<label class="label cursor-pointer">
<input type="radio" name="isCompactTable" class="radio radio-secondary mr-2" [value]="true" [formControl]="isCompactTable" />
Compact
</label>
</div>
</div>
<div class="absolute bottom-8 right-8 flex gap-6"> <div class="absolute bottom-8 right-8 flex gap-6">
<div class="join"> <div class="join">
<button *ngIf="updateAvailable" class="join-item btn btn-primary" (click)="downloadUpdate()"> <button *ngIf="updateAvailable" class="join-item btn btn-primary" (click)="downloadUpdate()">

View File

@@ -13,6 +13,7 @@ export class SettingsComponent implements OnInit {
@ViewChild('themeDropdown', { static: true }) themeDropdown: ElementRef @ViewChild('themeDropdown', { static: true }) themeDropdown: ElementRef
public isSng: FormControl<boolean> public isSng: FormControl<boolean>
public isCompactTable: FormControl<boolean>
updateAvailable: boolean | null = false updateAvailable: boolean | null = false
loginClicked = false loginClicked = false
@@ -29,6 +30,8 @@ export class SettingsComponent implements OnInit {
) { ) {
this.isSng = new FormControl<boolean>(settingsService.isSng, { nonNullable: true }) this.isSng = new FormControl<boolean>(settingsService.isSng, { nonNullable: true })
this.isSng.valueChanges.subscribe(value => settingsService.isSng = value) this.isSng.valueChanges.subscribe(value => settingsService.isSng = value)
this.isCompactTable = new FormControl<boolean>(settingsService.isCompactTable, { nonNullable: true })
this.isCompactTable.valueChanges.subscribe(value => settingsService.isCompactTable = value)
} }
async ngOnInit() { async ngOnInit() {

View File

@@ -82,4 +82,12 @@ export class SettingsService {
this.settings.isSng = value this.settings.isSng = value
this.saveSettings() this.saveSettings()
} }
get isCompactTable() {
return this.settings.isCompactTable
}
set isCompactTable(value: boolean) {
this.settings.isCompactTable = value
this.saveSettings()
}
} }

View File

@@ -3,12 +3,14 @@ import { Difficulty, Instrument } from 'scan-chart'
export const themes = [ export const themes = [
'business', 'business',
'dark', 'dark',
'halloween', 'dim',
'night', 'night',
'sunset',
'synthwave', 'synthwave',
'aqua', 'aqua',
'emerald', 'emerald',
'lemonade', 'lemonade',
'nord',
'valentine', 'valentine',
'winter', 'winter',
'aren', 'aren',
@@ -23,6 +25,7 @@ export interface Settings {
theme: typeof themes[number] // The name of the currently enabled UI theme theme: typeof themes[number] // The name of the currently enabled UI theme
libraryPath: string | undefined // The path to the user's library libraryPath: string | undefined // The path to the user's library
isSng: boolean // If the chart should be downloaded as a .sng file or as a chart folder isSng: boolean // If the chart should be downloaded as a .sng file or as a chart folder
isCompactTable: boolean // If the search result table should have reduced padding
instrument: Instrument | null // The instrument selected by default, or `null` for "Any Instrument" instrument: Instrument | null // The instrument selected by default, or `null` for "Any Instrument"
difficulty: Difficulty | null // The difficulty selected by default, or `null` for "Any Difficulty" difficulty: Difficulty | null // The difficulty selected by default, or `null` for "Any Difficulty"
} }
@@ -35,6 +38,7 @@ export const defaultSettings: Settings = {
theme: 'dark', theme: 'dark',
libraryPath: undefined, libraryPath: undefined,
isSng: false, isSng: false,
isCompactTable: false,
instrument: 'guitar', instrument: 'guitar',
difficulty: null, difficulty: null,
} }

View File

@@ -17,12 +17,14 @@ module.exports = {
themes: [ themes: [
'business', 'business',
'dark', 'dark',
'halloween', 'dim',
'night', 'night',
'sunset',
'synthwave', 'synthwave',
'aqua', 'aqua',
'emerald', 'emerald',
'lemonade', 'lemonade',
'nord',
'valentine', 'valentine',
'winter', 'winter',
{ {