diff --git a/wowup-electron/src/app/pages/get-addons/get-addons.component.html b/wowup-electron/src/app/pages/get-addons/get-addons.component.html index fe7e3e25..a0722be0 100644 --- a/wowup-electron/src/app/pages/get-addons/get-addons.component.html +++ b/wowup-electron/src/app/pages/get-addons/get-addons.component.html @@ -11,30 +11,34 @@ -
- - - - {{'PAGES.GET_ADDONS.SEARCH_LABEL' | translate}} - - + +
+
+ - + +
-
- - -
+
+ + +
{{'PAGES.GET_ADDONS.TABLE.ADDON_COLUMN_HEADER' | translate}} @@ -44,7 +48,7 @@ - + {{'PAGES.GET_ADDONS.TABLE.PROVIDER_COLUMN_HEADER' | translate}} @@ -53,7 +57,7 @@ - + {{'PAGES.GET_ADDONS.TABLE.AUTHOR_COLUMN_HEADER' | translate}} diff --git a/wowup-electron/src/app/pages/get-addons/get-addons.component.scss b/wowup-electron/src/app/pages/get-addons/get-addons.component.scss index f15e8f4d..368a343a 100644 --- a/wowup-electron/src/app/pages/get-addons/get-addons.component.scss +++ b/wowup-electron/src/app/pages/get-addons/get-addons.component.scss @@ -10,14 +10,24 @@ flex-grow: 1; } - .button-container { + .right-container { display: flex; flex-direction: row; - align-items: center; - button { - &:not(:last-child) { - margin-right: 0.5em; + .search-container { + padding-top: 1em; + } + + .button-container { + display: flex; + flex-direction: row; + align-items: center; + margin-left: 1em; + + button { + &:not(:last-child) { + margin-right: 0.5em; + } } } } diff --git a/wowup-electron/src/app/pages/get-addons/get-addons.component.ts b/wowup-electron/src/app/pages/get-addons/get-addons.component.ts index aaea5e7a..81d01e24 100644 --- a/wowup-electron/src/app/pages/get-addons/get-addons.component.ts +++ b/wowup-electron/src/app/pages/get-addons/get-addons.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from "@angular/core"; +import { Component, OnDestroy, OnInit, ViewChild } from "@angular/core"; import { MatDialog } from "@angular/material/dialog"; import { AddonDetailComponent } from "app/components/addon-detail/addon-detail.component"; import { InstallFromUrlDialogComponent } from "app/components/install-from-url-dialog/install-from-url-dialog.component"; @@ -11,8 +11,11 @@ import { ElectronService } from "app/services"; import { AddonService } from "app/services/addons/addon.service"; import { SessionService } from "app/services/session/session.service"; import { WarcraftService } from "app/services/warcraft/warcraft.service"; -import { BehaviorSubject, Subscription } from "rxjs"; -import { map, tap } from "rxjs/operators"; +import { BehaviorSubject, Subject, Subscription } from "rxjs"; +import { map } from "rxjs/operators"; +import { MatTableDataSource } from '@angular/material/table'; +import { MatSort } from '@angular/material/sort'; +import * as _ from 'lodash'; @Component({ selector: "app-get-addons", @@ -20,13 +23,17 @@ import { map, tap } from "rxjs/operators"; styleUrls: ["./get-addons.component.scss"], }) export class GetAddonsComponent implements OnInit, OnDestroy { - private readonly _displayAddonsSrc = new BehaviorSubject( - [] - ); + + @ViewChild(MatSort) sort: MatSort; + + private readonly _displayAddonsSrc = new BehaviorSubject([]); + private readonly _destroyed$ = new Subject(); private subscriptions: Subscription[] = []; + public dataSource = new MatTableDataSource([]); + columns: ColumnState[] = [ - { name: "addon", display: "Addon", visible: true }, + { name: "name", display: "Addon", visible: true }, { name: "author", display: "Author", visible: true }, { name: "provider", display: "Provider", visible: true }, { name: "status", display: "Status", visible: true }, @@ -37,8 +44,6 @@ export class GetAddonsComponent implements OnInit, OnDestroy { } public query = ""; - public displayAddons$ = this._displayAddonsSrc.asObservable(); - public isBusy = false; public selectedClient = WowClientType.None; @@ -64,9 +69,17 @@ export class GetAddonsComponent implements OnInit, OnDestroy { }) ).subscribe(); + const displayAddonSubscription = this._displayAddonsSrc + .subscribe((items: PotentialAddon[]) => { + this.dataSource.data = items; + this.dataSource.sortingDataAccessor = _.get; + this.dataSource.sort = this.sort; + }); + this.subscriptions = [ selectedClientSubscription, - addonRemovedSubscription + addonRemovedSubscription, + displayAddonSubscription ]; } diff --git a/wowup-electron/src/app/pages/my-addons/my-addons.component.html b/wowup-electron/src/app/pages/my-addons/my-addons.component.html index b84a7f85..46a589e9 100644 --- a/wowup-electron/src/app/pages/my-addons/my-addons.component.html +++ b/wowup-electron/src/app/pages/my-addons/my-addons.component.html @@ -1,38 +1,42 @@
-
-
- - {{'PAGES.MY_ADDONS.CLIENT_TYPE_SELECT_LABEL' | translate}} - - - {{warcraftService.getClientDisplayName(clientType)}} - - - -
+
+ + {{'PAGES.MY_ADDONS.CLIENT_TYPE_SELECT_LABEL' | translate}} + + + {{warcraftService.getClientDisplayName(clientType)}} + + + +
+
- Filter - + {{'PAGES.MY_ADDONS.FILTER_LABEL' | translate}} + +
-
-
- - - +
+ + + +
diff --git a/wowup-electron/src/app/pages/my-addons/my-addons.component.scss b/wowup-electron/src/app/pages/my-addons/my-addons.component.scss index b18dbc5f..8685b878 100644 --- a/wowup-electron/src/app/pages/my-addons/my-addons.component.scss +++ b/wowup-electron/src/app/pages/my-addons/my-addons.component.scss @@ -5,29 +5,29 @@ flex-direction: row; padding: 0 1em 0 1em; - .left-container { + .select-container { + padding-top: 1em; + flex-grow: 1; + } + + .right-container { display: flex; flex-direction: row; - flex-grow: 1; - - .select-container { - padding-top: 1em; - margin-right: 1em; - } .filter-container { padding-top: 1em; } - } - .button-container { - display: flex; - flex-direction: row; - align-items: center; - - button { - &:not(:last-child) { - margin-right: 0.5em; + .button-container { + display: flex; + flex-direction: row; + align-items: center; + margin-left: 1em; + + button { + &:not(:last-child) { + margin-right: 0.5em; + } } } } diff --git a/wowup-electron/src/app/pages/my-addons/my-addons.component.ts b/wowup-electron/src/app/pages/my-addons/my-addons.component.ts index 58bbed2e..073c552c 100644 --- a/wowup-electron/src/app/pages/my-addons/my-addons.component.ts +++ b/wowup-electron/src/app/pages/my-addons/my-addons.component.ts @@ -1,7 +1,7 @@ -import { Component, NgZone, OnDestroy, OnInit, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core'; +import { Component, NgZone, OnDestroy, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; import { WowClientType } from '../../models/warcraft/wow-client-type'; -import { debounceTime, filter, first, map, take, takeUntil, tap } from 'rxjs/operators'; -import { from, BehaviorSubject, Observable, fromEvent, Subscription, Subject } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { from, BehaviorSubject, Subscription, Subject } from 'rxjs'; import { Addon } from 'app/entities/addon'; import { WarcraftService } from 'app/services/warcraft/warcraft.service'; import { AddonService } from 'app/services/addons/addon.service'; @@ -21,6 +21,7 @@ import { ConfirmDialogComponent } from 'app/components/confirm-dialog/confirm-di import { getEnumName } from 'app/utils/enum.utils'; import { MatTableDataSource } from '@angular/material/table'; import { MatSort } from '@angular/material/sort'; +import { stringIncludes } from 'app/utils/string.utils'; @Component({ selector: 'app-my-addons', @@ -38,13 +39,13 @@ export class MyAddonsComponent implements OnInit, OnDestroy { private readonly _destroyed$ = new Subject(); private subscriptions: Subscription[] = []; - private sub: Subscription; public spinnerMessage = 'Loading...'; contextMenuPosition = { x: '0px', y: '0px' }; public dataSource = new MatTableDataSource([]); + public filter = ''; columns: ColumnState[] = [ { name: 'addon.name', display: 'Addon', visible: true }, @@ -76,7 +77,7 @@ export class MyAddonsComponent implements OnInit, OnDestroy { private _dialog: MatDialog ) { - this.addonService.addonInstalled$.subscribe((evt) => { + const addonInstalledSubscription = this.addonService.addonInstalled$.subscribe((evt) => { console.log('UPDATE') let listItems: MyAddonsListItem[] = [].concat(this._displayAddonsSrc.value); const listItemIdx = listItems.findIndex(li => li.addon.id === evt.addon.id); @@ -98,7 +99,7 @@ export class MyAddonsComponent implements OnInit, OnDestroy { }); }); - this.addonService.addonRemoved$ + const addonRemovedSubscription = this.addonService.addonRemoved$ .subscribe((addonId) => { const addons: MyAddonsListItem[] = [].concat(this._displayAddonsSrc.value); const listItemIdx = addons.findIndex(li => li.addon.id === addonId); @@ -109,23 +110,24 @@ export class MyAddonsComponent implements OnInit, OnDestroy { }); }) - this._displayAddonsSrc - .pipe(takeUntil(this._destroyed$)) + const displayAddonSubscription = this._displayAddonsSrc .subscribe((items: MyAddonsListItem[]) => { this.dataSource.data = items; this.dataSource.sortingDataAccessor = _.get; this.dataSource.filterPredicate = (item: MyAddonsListItem, filter: string) => { - if (item.addon.name.trim().toLowerCase().indexOf(filter) >= 0) return true; - if (item.addon.latestVersion && item.addon.latestVersion.trim().toLowerCase().indexOf(filter) >= 0) return true; - if (item.addon.author && item.addon.author.trim().toLowerCase().indexOf(filter) >= 0) return true; + if (stringIncludes(item.addon.name, filter) || stringIncludes(item.addon.latestVersion, filter) || stringIncludes(item.addon.author, filter)) { + return true; + } return false; } this.dataSource.sort = this.sort; }); + + this.subscriptions.concat(...[addonInstalledSubscription, addonRemovedSubscription, displayAddonSubscription]); } ngOnInit(): void { - this._sessionService.selectedClientType$ + const selectedClientSubscription = this._sessionService.selectedClientType$ .pipe( map(clientType => { this.selectedClient = clientType; @@ -133,12 +135,12 @@ export class MyAddonsComponent implements OnInit, OnDestroy { }) ) .subscribe(); + + this.subscriptions.push(selectedClientSubscription); } ngOnDestroy(): void { this.subscriptions.forEach(sub => sub.unsubscribe()); - this._destroyed$.next(); - this._destroyed$.complete(); } onRefresh() { @@ -180,10 +182,13 @@ export class MyAddonsComponent implements OnInit, OnDestroy { }); } - filterAddons(event: Event) { - const filterValue = (event.target as HTMLInputElement).value; - console.log('filterValue:', filterValue); - this.dataSource.filter = filterValue.trim().toLowerCase(); + filterAddons(): void { + this.dataSource.filter = this.filter.trim().toLowerCase(); + } + + onClearFilter(): void { + this.filter = ''; + this.filterAddons(); } async onUpdateAll() { diff --git a/wowup-electron/src/app/utils/string.utils.ts b/wowup-electron/src/app/utils/string.utils.ts new file mode 100644 index 00000000..fca0232f --- /dev/null +++ b/wowup-electron/src/app/utils/string.utils.ts @@ -0,0 +1,6 @@ +export function stringIncludes(value: string, search: string) { + if (value == null) { + return false; + } + return value.trim().toLowerCase().indexOf(search.trim().toLowerCase()) >= 0; +} \ No newline at end of file diff --git a/wowup-electron/src/assets/i18n/en.json b/wowup-electron/src/assets/i18n/en.json index e0ce4a75..ba5f431a 100644 --- a/wowup-electron/src/assets/i18n/en.json +++ b/wowup-electron/src/assets/i18n/en.json @@ -29,6 +29,7 @@ "CHECK_UPDATES_BUTTON": "Check Updates", "CHECK_UPDATES_BUTTON_TOOLTIP": "Check for latest addon updates", "CLIENT_TYPE_SELECT_LABEL": "World of Warcraft", + "FILTER_LABEL": "Filter", "RESCAN_FOLDERS_BUTTON": "Re-Scan Folders", "RESCAN_FOLDERS_BUTTON_TOOLTIP": "Scan your client folder for installed addons", "UPDATE_ALL_BUTTON": "Update All",