Browse Source

feat(admin-ui): Implement search/filtering of Assets

Closes #58
Michael Bromley 7 years ago
parent
commit
d1e9d8f85d

+ 9 - 0
admin-ui/src/app/catalog/components/asset-list/asset-list.component.html

@@ -1,4 +1,13 @@
 <vdr-action-bar>
 <vdr-action-bar>
+    <vdr-ab-left>
+        <input
+            type="text"
+            name="searchTerm"
+            [formControl]="searchTerm"
+            [placeholder]="'catalog.search-asset-name' | translate"
+            class="clr-input search-input"
+        />
+    </vdr-ab-left>
     <vdr-ab-right>
     <vdr-ab-right>
         <vdr-asset-file-input
         <vdr-asset-file-input
             (selectFiles)="filesSelected($event)"
             (selectFiles)="filesSelected($event)"

+ 4 - 0
admin-ui/src/app/catalog/components/asset-list/asset-list.component.scss

@@ -16,3 +16,7 @@ vdr-asset-gallery {
     display: flex;
     display: flex;
     justify-content: space-between;
     justify-content: space-between;
 }
 }
+
+.search-input {
+    min-width: 300px;
+}

+ 20 - 1
admin-ui/src/app/catalog/components/asset-list/asset-list.component.ts

@@ -1,8 +1,9 @@
 import { Component, OnInit } from '@angular/core';
 import { Component, OnInit } from '@angular/core';
+import { FormControl } from '@angular/forms';
 import { ActivatedRoute, Router } from '@angular/router';
 import { ActivatedRoute, Router } from '@angular/router';
 import { PaginationInstance } from 'ngx-pagination';
 import { PaginationInstance } from 'ngx-pagination';
 import { combineLatest, Observable } from 'rxjs';
 import { combineLatest, Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { debounceTime, map, takeUntil } from 'rxjs/operators';
 import { GetAssetList } from 'shared/generated-types';
 import { GetAssetList } from 'shared/generated-types';
 
 
 import { BaseListComponent } from '../../../common/base-list.component';
 import { BaseListComponent } from '../../../common/base-list.component';
@@ -17,6 +18,7 @@ import { DataService } from '../../../data/providers/data.service';
 })
 })
 export class AssetListComponent extends BaseListComponent<GetAssetList.Query, GetAssetList.Items>
 export class AssetListComponent extends BaseListComponent<GetAssetList.Query, GetAssetList.Items>
     implements OnInit {
     implements OnInit {
+    searchTerm = new FormControl('');
     paginationConfig$: Observable<PaginationInstance>;
     paginationConfig$: Observable<PaginationInstance>;
 
 
     constructor(
     constructor(
@@ -29,6 +31,17 @@ export class AssetListComponent extends BaseListComponent<GetAssetList.Query, Ge
         super.setQueryFn(
         super.setQueryFn(
             (...args: any[]) => this.dataService.product.getAssetList(...args),
             (...args: any[]) => this.dataService.product.getAssetList(...args),
             data => data.assets,
             data => data.assets,
+            (skip, take) => ({
+                options: {
+                    skip,
+                    take,
+                    filter: {
+                        name: {
+                            contains: this.searchTerm.value,
+                        },
+                    },
+                },
+            }),
         );
         );
     }
     }
 
 
@@ -37,6 +50,12 @@ export class AssetListComponent extends BaseListComponent<GetAssetList.Query, Ge
         this.paginationConfig$ = combineLatest(this.itemsPerPage$, this.currentPage$, this.totalItems$).pipe(
         this.paginationConfig$ = combineLatest(this.itemsPerPage$, this.currentPage$, this.totalItems$).pipe(
             map(([itemsPerPage, currentPage, totalItems]) => ({ itemsPerPage, currentPage, totalItems })),
             map(([itemsPerPage, currentPage, totalItems]) => ({ itemsPerPage, currentPage, totalItems })),
         );
         );
+        this.searchTerm.valueChanges
+            .pipe(
+                debounceTime(250),
+                takeUntil(this.destroy$),
+            )
+            .subscribe(() => this.refresh());
     }
     }
 
 
     filesSelected(files: File[]) {
     filesSelected(files: File[]) {

+ 7 - 1
admin-ui/src/app/catalog/components/asset-picker-dialog/asset-picker-dialog.component.html

@@ -7,7 +7,13 @@
         ></vdr-asset-file-input>
         ></vdr-asset-file-input>
     </div>
     </div>
 </ng-template>
 </ng-template>
-
+<input
+    type="text"
+    name="searchTerm"
+    [formControl]="searchTerm"
+    [placeholder]="'catalog.search-asset-name' | translate"
+    class="clr-input search-input"
+/>
 <vdr-asset-gallery
 <vdr-asset-gallery
     [assets]="assets$ | async | paginate: paginationConfig"
     [assets]="assets$ | async | paginate: paginationConfig"
     [multiSelect]="true"
     [multiSelect]="true"

+ 5 - 0
admin-ui/src/app/catalog/components/asset-picker-dialog/asset-picker-dialog.component.scss

@@ -3,6 +3,7 @@
 :host {
 :host {
     display: flex;
     display: flex;
     flex-direction: column;
     flex-direction: column;
+    height: 90vh;
 }
 }
 
 
 .title-row {
 .title-row {
@@ -11,6 +12,10 @@
     justify-content: space-between;
     justify-content: space-between;
 }
 }
 
 
+vdr-asset-gallery {
+    flex: 1;
+}
+
 .paging-controls {
 .paging-controls {
     padding-top: 6px;
     padding-top: 6px;
     border-top: 1px solid $color-grey-2;
     border-top: 1px solid $color-grey-2;

+ 41 - 7
admin-ui/src/app/catalog/components/asset-picker-dialog/asset-picker-dialog.component.ts

@@ -1,7 +1,8 @@
-import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
+import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
+import { FormControl } from '@angular/forms';
 import { PaginationInstance } from 'ngx-pagination';
 import { PaginationInstance } from 'ngx-pagination';
-import { Observable } from 'rxjs';
-import { map, tap } from 'rxjs/operators';
+import { Observable, Subject } from 'rxjs';
+import { debounceTime, map, takeUntil, tap } from 'rxjs/operators';
 import { Asset, GetAssetList } from 'shared/generated-types';
 import { Asset, GetAssetList } from 'shared/generated-types';
 
 
 import { _ } from '../../../core/providers/i18n/mark-for-extraction';
 import { _ } from '../../../core/providers/i18n/mark-for-extraction';
@@ -19,7 +20,7 @@ import { Dialog } from '../../../shared/providers/modal/modal.service';
     styleUrls: ['./asset-picker-dialog.component.scss'],
     styleUrls: ['./asset-picker-dialog.component.scss'],
     changeDetection: ChangeDetectionStrategy.OnPush,
     changeDetection: ChangeDetectionStrategy.OnPush,
 })
 })
-export class AssetPickerDialogComponent implements OnInit, Dialog<Asset[]> {
+export class AssetPickerDialogComponent implements OnInit, OnDestroy, Dialog<Asset[]> {
     assets$: Observable<Asset[]>;
     assets$: Observable<Asset[]>;
     paginationConfig: PaginationInstance = {
     paginationConfig: PaginationInstance = {
         currentPage: 1,
         currentPage: 1,
@@ -29,7 +30,9 @@ export class AssetPickerDialogComponent implements OnInit, Dialog<Asset[]> {
 
 
     resolveWith: (result?: Asset[]) => void;
     resolveWith: (result?: Asset[]) => void;
     selection: Asset[] = [];
     selection: Asset[] = [];
+    searchTerm = new FormControl('');
     private listQuery: QueryResult<GetAssetList.Query, GetAssetList.Variables>;
     private listQuery: QueryResult<GetAssetList.Query, GetAssetList.Variables>;
+    private destroy$ = new Subject<void>();
 
 
     constructor(private dataService: DataService, private notificationService: NotificationService) {}
     constructor(private dataService: DataService, private notificationService: NotificationService) {}
 
 
@@ -39,6 +42,23 @@ export class AssetPickerDialogComponent implements OnInit, Dialog<Asset[]> {
             tap(result => (this.paginationConfig.totalItems = result.assets.totalItems)),
             tap(result => (this.paginationConfig.totalItems = result.assets.totalItems)),
             map(result => result.assets.items),
             map(result => result.assets.items),
         );
         );
+        this.searchTerm.valueChanges
+            .pipe(
+                debounceTime(250),
+                takeUntil(this.destroy$),
+            )
+            .subscribe(searchTerm => {
+                this.fetchPage(
+                    this.paginationConfig.currentPage,
+                    this.paginationConfig.itemsPerPage,
+                    searchTerm,
+                );
+            });
+    }
+
+    ngOnDestroy(): void {
+        this.destroy$.next();
+        this.destroy$.complete();
     }
     }
 
 
     pageChange(page: number) {
     pageChange(page: number) {
@@ -62,7 +82,11 @@ export class AssetPickerDialogComponent implements OnInit, Dialog<Asset[]> {
     createAssets(files: File[]) {
     createAssets(files: File[]) {
         if (files.length) {
         if (files.length) {
             this.dataService.product.createAssets(files).subscribe(res => {
             this.dataService.product.createAssets(files).subscribe(res => {
-                this.fetchPage(this.paginationConfig.currentPage, this.paginationConfig.itemsPerPage);
+                this.fetchPage(
+                    this.paginationConfig.currentPage,
+                    this.paginationConfig.itemsPerPage,
+                    this.searchTerm.value,
+                );
                 this.notificationService.success(_('catalog.notify-create-assets-success'), {
                 this.notificationService.success(_('catalog.notify-create-assets-success'), {
                     count: files.length,
                     count: files.length,
                 });
                 });
@@ -70,9 +94,19 @@ export class AssetPickerDialogComponent implements OnInit, Dialog<Asset[]> {
         }
         }
     }
     }
 
 
-    private fetchPage(currentPage: number, itemsPerPage: number) {
+    private fetchPage(currentPage: number, itemsPerPage: number, searchTerm?: string) {
         const take = +itemsPerPage;
         const take = +itemsPerPage;
         const skip = (currentPage - 1) * +itemsPerPage;
         const skip = (currentPage - 1) * +itemsPerPage;
-        this.listQuery.ref.refetch({ options: { skip, take } });
+        this.listQuery.ref.refetch({
+            options: {
+                skip,
+                take,
+                filter: {
+                    name: {
+                        contains: searchTerm,
+                    },
+                },
+            },
+        });
     }
     }
 }
 }

+ 1 - 0
admin-ui/src/i18n-messages/en.json

@@ -63,6 +63,7 @@
     "product-name": "Product name",
     "product-name": "Product name",
     "product-variants": "Product variants",
     "product-variants": "Product variants",
     "remove-asset": "Remove asset",
     "remove-asset": "Remove asset",
+    "search-asset-name": "Search assets by name",
     "search-product-name-or-code": "Search by product name or code",
     "search-product-name-or-code": "Search by product name or code",
     "select-assets": "Select assets",
     "select-assets": "Select assets",
     "select-option-group": "Select option group",
     "select-option-group": "Select option group",