From 18afa01e5c044213060c2c2e6c45fcb585fc07a7 Mon Sep 17 00:00:00 2001 From: Geomitron <22552797+Geomitron@users.noreply.github.com> Date: Wed, 11 Mar 2020 22:51:24 -0400 Subject: [PATCH] Refactor search service --- .../components/browse/browse.component.html | 2 +- src/app/components/browse/browse.component.ts | 10 ------ .../chart-sidebar/chart-sidebar.component.ts | 18 ++++++++-- .../result-table/result-table.component.ts | 32 +++++++++++------ .../search-bar/search-bar.component.html | 2 +- .../browse/search-bar/search-bar.component.ts | 12 +++---- .../browse/status-bar/status-bar.component.ts | 36 +++++++++++++------ src/app/core/directives/checkbox.directive.ts | 9 +++++ src/app/core/services/search.service.ts | 33 +++++++++++++++++ 9 files changed, 110 insertions(+), 44 deletions(-) create mode 100644 src/app/core/services/search.service.ts diff --git a/src/app/components/browse/browse.component.html b/src/app/components/browse/browse.component.html index a00b2b0..be73022 100644 --- a/src/app/components/browse/browse.component.html +++ b/src/app/components/browse/browse.component.html @@ -1,4 +1,4 @@ - +
diff --git a/src/app/components/browse/browse.component.ts b/src/app/components/browse/browse.component.ts index 12fb6c7..aa830fd 100644 --- a/src/app/components/browse/browse.component.ts +++ b/src/app/components/browse/browse.component.ts @@ -1,7 +1,6 @@ import { Component, ViewChild, AfterViewInit } from '@angular/core' import { ChartSidebarComponent } from './chart-sidebar/chart-sidebar.component' import { StatusBarComponent } from './status-bar/status-bar.component' -import { SongResult } from 'src/electron/shared/interfaces/search.interface' import { ResultTableComponent } from './result-table/result-table.component' @Component({ @@ -35,15 +34,6 @@ export class BrowseComponent implements AfterViewInit { }) } - onResultsUpdated(results: SongResult[]) { - this.resultTable.results = results - this.resultTable.onNewSearch() - this.resultTable.checkAll(false) - this.chartSidebar.selectVersion(undefined) - this.statusBar.resultCount = results.length - this.statusBar.selectedResults = [] - } - loadMoreResults() { // TODO: use the same query as the current search, but append more results if there are any more to be viewed } diff --git a/src/app/components/browse/chart-sidebar/chart-sidebar.component.ts b/src/app/components/browse/chart-sidebar/chart-sidebar.component.ts index 4eb7d88..f42b0b4 100644 --- a/src/app/components/browse/chart-sidebar/chart-sidebar.component.ts +++ b/src/app/components/browse/chart-sidebar/chart-sidebar.component.ts @@ -1,23 +1,35 @@ -import { Component } from '@angular/core' +import { Component, OnInit } from '@angular/core' import { SongResult } from '../../../../electron/shared/interfaces/search.interface' import { ElectronService } from '../../../core/services/electron.service' import { VersionResult } from '../../../../electron/shared/interfaces/songDetails.interface' import { AlbumArtService } from '../../../core/services/album-art.service' import { DownloadService } from '../../../core/services/download.service' import { groupBy } from 'src/electron/shared/UtilFunctions' +import { SearchService } from 'src/app/core/services/search.service' @Component({ selector: 'app-chart-sidebar', templateUrl: './chart-sidebar.component.html', styleUrls: ['./chart-sidebar.component.scss'] }) -export class ChartSidebarComponent { +export class ChartSidebarComponent implements OnInit { private songResult: SongResult selectedVersion: VersionResult charts: VersionResult[][] - constructor(private electronService: ElectronService, private albumArtService: AlbumArtService, private downloadService: DownloadService) { } + constructor( + private electronService: ElectronService, + private albumArtService: AlbumArtService, + private downloadService: DownloadService, + private searchService: SearchService + ) { } + + ngOnInit() { + this.searchService.onNewSearch(() => { + this.selectVersion(undefined) + }) + } /** * Displays the information for the selected song. diff --git a/src/app/components/browse/result-table/result-table.component.ts b/src/app/components/browse/result-table/result-table.component.ts index fa30db9..5d48fb4 100644 --- a/src/app/components/browse/result-table/result-table.component.ts +++ b/src/app/components/browse/result-table/result-table.component.ts @@ -1,24 +1,40 @@ -import { Component, Input, Output, EventEmitter, ViewChildren, QueryList, ViewChild } from '@angular/core' +import { Component, Output, EventEmitter, ViewChildren, QueryList, ViewChild, OnInit } from '@angular/core' import { SongResult } from '../../../../electron/shared/interfaces/search.interface' import { ResultTableRowComponent } from './result-table-row/result-table-row.component' import { CheckboxDirective } from 'src/app/core/directives/checkbox.directive' +import { SearchService } from 'src/app/core/services/search.service' @Component({ selector: 'app-result-table', templateUrl: './result-table.component.html', styleUrls: ['./result-table.component.scss'] }) -export class ResultTableComponent { - @Input() results: SongResult[] - +export class ResultTableComponent implements OnInit { + @Output() rowClicked = new EventEmitter() @Output() songChecked = new EventEmitter() @Output() songUnchecked = new EventEmitter() - + @ViewChild(CheckboxDirective, { static: true }) checkboxColumn: CheckboxDirective @ViewChildren('tableRow') tableRows: QueryList + + results: SongResult[] - constructor() { } + constructor(private searchService: SearchService) { } + + ngOnInit() { + this.searchService.onNewSearch(() => { + this.checkboxColumn.check(false) + this.checkAll(false) + }) + + this.searchService.onSearchChanged(results => { + this.results = results + if (this.checkboxColumn.isChecked) { + this.checkAll(true) + } + }) + } onRowClicked(result: SongResult) { this.rowClicked.emit(result) @@ -39,8 +55,4 @@ export class ResultTableComponent { onSongsDeselected(songs: SongResult['id'][]) { this.tableRows.forEach(row => row.check(!songs.includes(row.songID))) } - - onNewSearch() { - this.checkboxColumn.check(false) - } } \ No newline at end of file diff --git a/src/app/components/browse/search-bar/search-bar.component.html b/src/app/components/browse/search-bar/search-bar.component.html index b75e0e3..434839f 100644 --- a/src/app/components/browse/search-bar/search-bar.component.html +++ b/src/app/components/browse/search-bar/search-bar.component.html @@ -19,7 +19,7 @@ Charter
-
\ No newline at end of file diff --git a/src/app/components/browse/search-bar/search-bar.component.ts b/src/app/components/browse/search-bar/search-bar.component.ts index 2ace183..f35b35d 100644 --- a/src/app/components/browse/search-bar/search-bar.component.ts +++ b/src/app/components/browse/search-bar/search-bar.component.ts @@ -1,6 +1,5 @@ -import { Component, AfterViewInit, Output, EventEmitter } from '@angular/core' -import { ElectronService } from '../../../core/services/electron.service' -import { SearchType, SongResult } from '../../../../electron/shared/interfaces/search.interface' +import { Component, AfterViewInit } from '@angular/core' +import { SearchService } from 'src/app/core/services/search.service' @Component({ selector: 'app-search-bar', @@ -8,17 +7,14 @@ import { SearchType, SongResult } from '../../../../electron/shared/interfaces/s styleUrls: ['./search-bar.component.scss'] }) export class SearchBarComponent implements AfterViewInit { - @Output() resultsUpdated = new EventEmitter() - constructor(private electronService: ElectronService) { } + constructor(private searchService: SearchService) { } ngAfterViewInit() { $('.ui.dropdown').dropdown() } async onSearch(query: string) { - const results = await this.electronService.invoke('song-search', { query, type: SearchType.Any }) - - this.resultsUpdated.emit(results) + this.searchService.newSearch(query) } } \ No newline at end of file diff --git a/src/app/components/browse/status-bar/status-bar.component.ts b/src/app/components/browse/status-bar/status-bar.component.ts index 2dde2e6..6a6ba53 100644 --- a/src/app/components/browse/status-bar/status-bar.component.ts +++ b/src/app/components/browse/status-bar/status-bar.component.ts @@ -4,6 +4,7 @@ import { DownloadService } from 'src/app/core/services/download.service' import { ElectronService } from 'src/app/core/services/electron.service' import { groupBy } from 'src/electron/shared/UtilFunctions' import { VersionResult } from 'src/electron/shared/interfaces/songDetails.interface' +import { SearchService } from 'src/app/core/services/search.service' @Component({ selector: 'app-status-bar', @@ -21,12 +22,25 @@ export class StatusBarComponent { batchResults: VersionResult[] chartGroups: VersionResult[][] - constructor(private electronService: ElectronService, private downloadService: DownloadService, ref: ChangeDetectorRef) { + constructor( + private electronService: ElectronService, + private downloadService: DownloadService, + searchService: SearchService, + ref: ChangeDetectorRef + ) { downloadService.onDownloadUpdated(() => { this.downloading = downloadService.downloadCount > 0 this.percent = downloadService.totalPercent ref.detectChanges() }) + + searchService.onSearchChanged(() => { + this.resultCount = searchService.resultCount + }) + + searchService.onNewSearch(() => { + this.selectedResults = [] + }) } showDownloads() { @@ -60,11 +74,11 @@ export class StatusBarComponent { const downloadSong = this.selectedResults.find(song => song.id == downloadVersion.songID) this.downloadService.addDownload( downloadVersion.versionID, { - avTagName: downloadVersion.avTagName, - artist: downloadSong.artist, - charter: downloadVersion.charters, - links: JSON.parse(downloadVersion.downloadLink) - }) + avTagName: downloadVersion.avTagName, + artist: downloadSong.artist, + charter: downloadVersion.charters, + links: JSON.parse(downloadVersion.downloadLink) + }) } } else { $('#selectedModal').modal('show') @@ -78,11 +92,11 @@ export class StatusBarComponent { const downloadSong = this.selectedResults.find(song => song.id == version.songID) this.downloadService.addDownload( version.versionID, { - avTagName: version.avTagName, - artist: downloadSong.artist, - charter: version.charters, - links: JSON.parse(version.downloadLink) - }) + avTagName: version.avTagName, + artist: downloadSong.artist, + charter: version.charters, + links: JSON.parse(version.downloadLink) + }) } } diff --git a/src/app/core/directives/checkbox.directive.ts b/src/app/core/directives/checkbox.directive.ts index a2cd5f6..c8f027a 100644 --- a/src/app/core/directives/checkbox.directive.ts +++ b/src/app/core/directives/checkbox.directive.ts @@ -6,24 +6,33 @@ import { Directive, ElementRef, Output, EventEmitter, AfterViewInit } from '@ang export class CheckboxDirective implements AfterViewInit { @Output() checked = new EventEmitter() + _isChecked = false + constructor(private checkbox: ElementRef) { } ngAfterViewInit() { $(this.checkbox.nativeElement).checkbox({ onChecked: () => { this.checked.emit(true) + this._isChecked = true }, onUnchecked: () => { this.checked.emit(false) + this._isChecked = false } }) } check(isChecked: boolean) { + this._isChecked = isChecked if (isChecked) { $(this.checkbox.nativeElement).checkbox('check') } else { $(this.checkbox.nativeElement).checkbox('uncheck') } } + + get isChecked() { + return this._isChecked + } } \ No newline at end of file diff --git a/src/app/core/services/search.service.ts b/src/app/core/services/search.service.ts new file mode 100644 index 0000000..9443a31 --- /dev/null +++ b/src/app/core/services/search.service.ts @@ -0,0 +1,33 @@ +import { Injectable, EventEmitter } from '@angular/core' +import { ElectronService } from './electron.service' +import { SearchType, SongResult } from 'src/electron/shared/interfaces/search.interface' + +@Injectable({ + providedIn: 'root' +}) +export class SearchService { + + private resultsChangedEmitter = new EventEmitter() // For when any results change + private newResultsEmitter = new EventEmitter() // For when a new search happens + private results: SongResult[] = [] + + constructor(private electronService: ElectronService) { } + + async newSearch(query: string) { + this.results = await this.electronService.invoke('song-search', { query, type: SearchType.Any }) + this.newResultsEmitter.emit(this.results) + this.resultsChangedEmitter.emit(this.results) + } + + onSearchChanged(callback: (results: SongResult[]) => void) { + this.resultsChangedEmitter.subscribe(callback) + } + + onNewSearch(callback: (results: SongResult[]) => void) { + this.newResultsEmitter.subscribe(callback) + } + + get resultCount() { + return this.results.length + } +}