This is an automated email from the ASF dual-hosted git repository. hshpak pushed a commit to branch feat/DATALAB-2881/filter-function-to-Images-page in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 141a2b15960eaa827fdeb667d3b338c4f0817e1d Author: Hennadii_Shpak <[email protected]> AuthorDate: Fri Jul 29 09:55:57 2022 +0300 second commit --- .../page-filter/page-filter.component.html | 16 ++++---- .../page-filter/page-filter.component.ts | 26 +++++++++---- .../exploratory/page-filter/page-filter.config.ts | 2 +- .../src/app/resources/images/images.component.html | 2 + .../src/app/resources/images/images.component.ts | 21 +++++++++-- .../src/app/resources/images/images.config.ts | 17 ++++++++- .../src/app/resources/images/images.model.ts | 8 ++-- .../src/app/resources/images/images.service.ts | 43 ++++++++++++++++++++-- 8 files changed, 107 insertions(+), 28 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.html index 287f9db8e..066ee44b6 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.html @@ -26,7 +26,7 @@ matInput [matAutocomplete]="auto"> <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"> - <mat-option *ngFor="let option of filteredOptions" [value]="option"> + <mat-option *ngFor="let option of ($filterDropdownData | async).imageNames" [value]="option"> {{option}} </mat-option> </mat-autocomplete> @@ -46,7 +46,7 @@ (click)="onSelectClick()" > <mat-option - *ngFor="let status of statuses" + *ngFor="let status of ($filterDropdownData | async).imageStatuses" [value]="status" > {{ status }} @@ -61,7 +61,7 @@ </div> <div class="control-group"> - <label class="label">Provider</label> + <label class="label">Endpoint</label> <div class="control selector-wrapper"> <span class="form-field-wrapper"> <mat-form-field> @@ -69,15 +69,15 @@ formControlName="cloudProviders" disableOptionCentering panelClass="create-resources-dialog scrolling" - [placeholder]="placeholders.provider" + [placeholder]="placeholders.endpoint" multiple (click)="onSelectClick()" > <mat-option - *ngFor="let provider of cloudProviders" - [value]="provider" + *ngFor="let endpoint of ($filterDropdownData | async).endpoints" + [value]="endpoint" > - {{ provider }} + {{ endpoint }} </mat-option> </mat-select> <button class="caret"> @@ -102,7 +102,7 @@ (click)="onSelectClick()" > <mat-option - *ngFor="let template of templates" + *ngFor="let template of ($filterDropdownData | async).templateNames" [value]="template" > {{ template }} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.ts index 7ed77c714..edc9d4ce7 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.ts @@ -17,10 +17,13 @@ * under the License. */ -import {Component, EventEmitter, OnInit, Output} from '@angular/core'; -import {FormBuilder, FormGroup} from '@angular/forms'; +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {AbstractControl, FormBuilder, FormControl, FormGroup} from '@angular/forms'; import {FilterFormPlaceholders} from './page-filter.config'; +import {DropdownFieldNames, FilterDropdownValue} from '../../images'; +import {Observable} from 'rxjs'; +import {tap} from 'rxjs/operators'; @Component({ selector: 'datalab-page-filter', @@ -28,15 +31,15 @@ import {FilterFormPlaceholders} from './page-filter.config'; styleUrls: ['./page-filter.component.scss'] }) export class PageFilterComponent implements OnInit { - @Output() filterFormValue: EventEmitter<any> = new EventEmitter<any>(); + @Input() $filterDropdownData: Observable<FilterDropdownValue>; + + @Output() filterFormValue: EventEmitter<FilterDropdownValue> = new EventEmitter<FilterDropdownValue>(); @Output() closeFilter: EventEmitter<any> = new EventEmitter<any>(); + @Output() imageNameValue: EventEmitter<string> = new EventEmitter<string>(); + @Output() onValueChanges: EventEmitter<string> = new EventEmitter<string>(); readonly placeholders: typeof FilterFormPlaceholders = FilterFormPlaceholders; - filteredOptions = []; - templates = ['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato']; - statuses = ['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato']; - cloudProviders = ['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato']; filterForm: FormGroup; constructor( @@ -45,6 +48,7 @@ export class PageFilterComponent implements OnInit { ngOnInit(): void { this.initFilterForm(); + this.onControlChange(DropdownFieldNames.imageName); } initFilterForm(): void { @@ -68,4 +72,12 @@ export class PageFilterComponent implements OnInit { cancelFilter(): void { this.closeFilter.emit(); } + + onControlChange(fieldName: keyof FilterDropdownValue): void { + console.log(this.filterForm.get(fieldName)); + this.filterForm.get(fieldName)?.valueChanges.pipe( + tap((inputValue: string) => this.onValueChanges.emit(inputValue)) + ).subscribe(); + + } } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.config.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.config.ts index b647ea02d..399d70c6f 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.config.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.config.ts @@ -20,7 +20,7 @@ export enum FilterFormPlaceholders { imageName = 'Enter image name', status = 'Select status', - provider = 'Select provider', + endpoint = 'Select endpoint', templateName = 'Select template name', sharing = 'Select sharing status' } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.html index ab03ccd93..49a106309 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.html @@ -97,8 +97,10 @@ </button> <div *ngIf="isFilterOpened | async" class="filer__wrapper"> <datalab-page-filter + [$filterDropdownData]="$filterDropdownData" (filterFormValue)="onFilterApplyClick($event)" (closeFilter)="onFilterCancelClick()" + (onValueChanges)="onControlChanges(dropdownFieldNames.imageNames, $event)" > </datalab-page-filter> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.ts index bf7d6d34c..64d02cf60 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.component.ts @@ -26,7 +26,7 @@ import { ToastrService } from 'ngx-toastr'; import { GeneralEnvironmentStatus } from '../../administration/management/management.model'; import { HealthStatusService } from '../../core/services'; -import { ImageModel, ProjectModel } from './images.model'; +import {FilterDropdownValue, ImageModel, ProjectModel} from './images.model'; import { TooltipStatuses, Image_Table_Column_Headers, @@ -34,7 +34,7 @@ import { ImageStatuses, Localstorage_Key, Placeholders, - Shared_Status, + Shared_Status, DropdownFieldNames, } from './images.config'; import { ShareImageDialogComponent } from '../exploratory/share-image/share-image-dialog.component'; import { ImagesService } from './images.service'; @@ -59,6 +59,7 @@ export class ImagesComponent implements OnInit, OnDestroy { readonly sharedStatus: typeof Shared_Status = Shared_Status; readonly imageStatus: typeof ImageStatuses = ImageStatuses; readonly tooltipStatuses: typeof TooltipStatuses = TooltipStatuses; + readonly dropdownFieldNames: typeof DropdownFieldNames = DropdownFieldNames; isActionsOpen: boolean = false; healthStatus: GeneralEnvironmentStatus; @@ -69,6 +70,7 @@ export class ImagesComponent implements OnInit, OnDestroy { userName!: string; isProjectsMoreThanOne: boolean; isFilterOpened: Observable<boolean>; + $filterDropdownData: Observable<FilterDropdownValue>; constructor( private healthStatusService: HealthStatusService, @@ -82,10 +84,10 @@ export class ImagesComponent implements OnInit, OnDestroy { ngOnInit(): void { this.getEnvironmentHealthStatus(); this.getUserImagePageInfo(); - this.getUserName(); this.initImageTable(); this.initFilterBtn(); + this.getDropdownList(); } ngOnDestroy(): void { @@ -150,6 +152,15 @@ export class ImagesComponent implements OnInit, OnDestroy { this.imagesService.closeFilter(); } + onControlChanges(controlName: keyof FilterDropdownValue, inputValue: string): void { + this.imagesService.filterDropdownField(DropdownFieldNames.imageName, inputValue); + } + + // onImageNameChange1(inputValue: string): void { + // this.imagesService.filterDropdownField(inputValue); + // console.log(inputValue); + // } + private getEnvironmentHealthStatus(): void { this.healthStatusService.getEnvironmentHealthStatus().subscribe( (result: GeneralEnvironmentStatus) => { @@ -189,6 +200,10 @@ export class ImagesComponent implements OnInit, OnDestroy { this.isFilterOpened = this.imagesService.$isFilterOpened; } + private getDropdownList(): void { + this.$filterDropdownData = this.imagesService.$filterDropdownData; + } + get isImageSelected(): boolean { return this.imagesService.isImageSelected(); } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.config.ts b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.config.ts index b9c958aa0..3db199434 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.config.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.config.ts @@ -24,7 +24,6 @@ export enum Image_Table_Column_Headers { imageStatus = 'Image status', sharedStatus = 'Shared status', templateName = 'Template name', - instanceName = 'Instance name', actions = 'Actions', endpoint = 'Endpoint', } @@ -68,3 +67,19 @@ export enum TooltipStatuses { creatorOnly = 'Images may be shared by creators only', unableTerminate = 'Unable to terminate notebook because at least one compute is in progress' } + +export enum DropdownFieldNames { + imageName = 'imageName', + imageStatuses = 'imageStatuses', + endpoints = 'endpoints', + templateNames = 'templateNames', + sharingStatuses = 'sharingStatuses' +} + +export enum ImageModelNames { + name = 'name', + status = 'status', + endpoint = 'endpoint', + templateName = 'templateName', + shared = 'shared' +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.model.ts index 7bd30a1df..f1fe519c9 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.model.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.model.ts @@ -51,8 +51,8 @@ export interface ClusterConfig { export interface FilterDropdownValue { imageName: string[]; - imageStatus: string[]; - provider: string[]; - templateName: string[]; - sharingStatus: string[]; + imageStatuses: string[]; + endpoints: string[]; + templateNames: string[]; + sharingStatuses: string[]; } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.service.ts b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.service.ts index 56a48bb62..054e45bf7 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/images/images.service.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/images/images.service.ts @@ -1,9 +1,10 @@ import { Injectable } from '@angular/core'; -import {tap} from 'rxjs/operators'; -import {BehaviorSubject, Observable} from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { BehaviorSubject, Observable } from 'rxjs'; -import { ImageModel, ProjectModel, ShareImageAllUsersParams } from './images.model'; -import {ApplicationServiceFacade, UserImagesPageService} from '../../core/services'; +import { FilterDropdownValue, ImageModel, ProjectModel, ShareImageAllUsersParams } from './images.model'; +import { ApplicationServiceFacade, UserImagesPageService } from '../../core/services'; +import {ImageModelNames} from './images.config'; @Injectable({ providedIn: 'root' @@ -12,9 +13,12 @@ export class ImagesService { private $$projectList: BehaviorSubject<ProjectModel[]> = new BehaviorSubject<ProjectModel[]>([]); private $$imageList: BehaviorSubject<ImageModel[]> = new BehaviorSubject<ImageModel[]>([]); private $$isFilterOpened: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); + private $$filterDropdownData: BehaviorSubject<FilterDropdownValue> = new BehaviorSubject<FilterDropdownValue>({} as FilterDropdownValue); + private dropdownStartValue: FilterDropdownValue; $imageList = this.$$imageList.asObservable(); $isFilterOpened = this.$$isFilterOpened.asObservable(); + $filterDropdownData = this.$$filterDropdownData.asObservable(); constructor( private applicationServiceFacade: ApplicationServiceFacade, @@ -78,9 +82,40 @@ export class ImagesService { this.$$isFilterOpened.next(false); } + filterDropdownField(field: keyof FilterDropdownValue, value: string, ) { + const filteredDropdownList = this.dropdownStartValue[field].filter(item => item.toLowerCase().includes(value)); + this.addFilterDropdownData({...this.$$filterDropdownData.value, imageName: filteredDropdownList}); + } + + private getDropdownDataList(): void { + const dropdownList = { + imageName: this.getDropdownDataItem(ImageModelNames.name), + imageStatuses: this.getDropdownDataItem(ImageModelNames.status), + endpoints: this.getDropdownDataItem(ImageModelNames.endpoint), + templateNames: this.getDropdownDataItem(ImageModelNames.templateName), + sharingStatuses: this.getDropdownDataItem(ImageModelNames.shared), + }; + + this.addFilterDropdownData(dropdownList); + this.dropdownStartValue = dropdownList; + } + + private getDropdownDataItem(key: keyof ImageModel): string[] { + const dropdownItem = this.$$imageList.value.reduce((acc: Set<string>, item) => { + acc.add(item[key].toString()); + return acc; + }, new Set<string>()); + return [...dropdownItem]; + } + + private addFilterDropdownData(data: FilterDropdownValue): void { + this.$$filterDropdownData.next(data); + } + private getImagePageData(imagePageData: ProjectModel[]): void { const imageList = imagePageData.reduce((acc: ImageModel[], {images}) => [...acc, ...images], []); this.updateProjectList(imagePageData); this.updateImageList(imageList); + this.getDropdownDataList(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
