This is an automated email from the ASF dual-hosted git repository. hshpak pushed a commit to branch feat/DATALAB-2960/refresh-button-should-not-impact-on-filtered-options in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 305bee5e8314fc00d73c1577719fee06657213be Author: Hennadii_Shpak <[email protected]> AuthorDate: Wed Aug 10 00:05:02 2022 +0300 fixed image page logic for new model of responce --- .../app/core/services/image-page-resolve.guard.ts | 16 +++---- .../app/core/services/user-images-page.service.ts | 12 +++-- .../page-filter/page-filter.component.html | 16 ++++--- .../page-filter/page-filter.component.scss | 6 +++ .../page-filter/page-filter.component.ts | 18 +++++--- .../src/app/resources/images/images.component.html | 4 +- .../src/app/resources/images/images.component.ts | 6 +-- .../src/app/resources/images/images.config.ts | 10 ++++- .../src/app/resources/images/images.model.ts | 10 ++++- .../src/app/resources/images/images.service.ts | 51 ++++++++-------------- 10 files changed, 83 insertions(+), 66 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/image-page-resolve.guard.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/image-page-resolve.guard.ts index 4f89ede57..cadeeb7cb 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/services/image-page-resolve.guard.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/image-page-resolve.guard.ts @@ -1,23 +1,23 @@ import { Injectable } from '@angular/core'; -import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router'; -import {EMPTY, Observable, of} from 'rxjs'; +import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; +import { Observable, of } from 'rxjs'; -import {ImagesService} from '../../resources/images/images.service'; -import {ProjectModel} from '../../resources/images'; -import {switchMap, take} from 'rxjs/operators'; +import { ImagesService } from '../../resources/images/images.service'; +import { ProjectImagesInfo } from '../../resources/images'; +import { switchMap, take } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) -export class ImagePageResolveGuard implements Resolve<ProjectModel[]> { +export class ImagePageResolveGuard implements Resolve<ProjectImagesInfo> { constructor( private router: Router, private imagesService: ImagesService ) {} - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ProjectModel[]> { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ProjectImagesInfo> { return this.imagesService.getImagePageInfo().pipe( - switchMap((projectList: ProjectModel[]) => of(projectList)), + switchMap((imagePageData: ProjectImagesInfo) => of(imagePageData)), take(1) ); } diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/user-images-page.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/user-images-page.service.ts index 198e8c8ee..f1933619d 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/services/user-images-page.service.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/services/user-images-page.service.ts @@ -23,7 +23,11 @@ import { catchError } from 'rxjs/operators'; import { ErrorUtils } from '../util'; import { ApplicationServiceFacade } from './applicationServiceFacade.service'; -import {ImageFilterFormDropdownData, ImageFilterFormValue, ProjectModel, ShareImageAllUsersParams} from '../../resources/images'; +import { + ImageFilterFormValue, + ProjectImagesInfo, + ShareImageAllUsersParams +} from '../../resources/images'; @Injectable() export class UserImagesPageService { @@ -32,21 +36,21 @@ export class UserImagesPageService { ) { } - getFilterImagePage(): Observable<ProjectModel[]> { + getFilterImagePage(): Observable<ProjectImagesInfo> { return this.applicationServiceFacade.buildGetUserImagePage() .pipe( catchError(ErrorUtils.handleServiceError) ); } - filterImagePage(params: ImageFilterFormValue): Observable<ProjectModel[]> { + filterImagePage(params: ImageFilterFormValue): Observable<ProjectImagesInfo> { return this.applicationServiceFacade.buildFilterUserImagePage(params) .pipe( catchError(ErrorUtils.handleServiceError) ); } - shareImagesAllUser(shareParams: ShareImageAllUsersParams): Observable<ProjectModel[]> { + shareImagesAllUser(shareParams: ShareImageAllUsersParams): Observable<ProjectImagesInfo> { return this.applicationServiceFacade.buildShareImageAllUsers(shareParams) .pipe( catchError(ErrorUtils.handleServiceError) 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 b85d4cee1..818a8a5b2 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 @@ -30,12 +30,12 @@ type="text" class="form-control" [placeholder]="placeholders.imageName" - [formControlName]="dropdownFieldNames.imageName" + [formControlName]="controlNames.imageName" matInput [matAutocomplete]="auto" /> <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"> - <mat-option *ngFor="let option of ($filterDropdownData | async).imageName" [value]="option"> + <mat-option *ngFor="let option of ($filterDropdownData | async).imageNames" [value]="option"> {{option}} </mat-option> </mat-autocomplete> @@ -51,7 +51,7 @@ disableOptionCentering panelClass="create-resources-dialog scrolling" [placeholder]="placeholders.status" - [multiple]="($filterDropdownData | async).statuses.length > 1" + multiple > <mat-select-trigger class="select__value"> {{statuses.value | normalizeDropdownMultiValue: selectAllValue | titlecase}} @@ -66,6 +66,7 @@ </mat-option> <mat-option *ngFor="let status of ($filterDropdownData | async).statuses" + [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" [value]="status" > {{ status | titlecase }} @@ -89,7 +90,7 @@ disableOptionCentering panelClass="create-resources-dialog scrolling" [placeholder]="placeholders.endpoint" - [multiple]="($filterDropdownData | async).endpoints.length > 1" + multiple > <mat-select-trigger class="select__value"> {{endpoints.value | normalizeDropdownMultiValue: selectAllValue}} @@ -104,6 +105,7 @@ </mat-option> <mat-option *ngFor="let endpoint of ($filterDropdownData | async).endpoints" + [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" [value]="endpoint" > {{ endpoint }} @@ -127,7 +129,7 @@ disableOptionCentering panelClass="create-resources-dialog scrolling" [placeholder]="placeholders.templateName" - [multiple]="($filterDropdownData | async).templateNames.length > 1" + multiple > <mat-select-trigger class="select__value"> {{templateNames.value | normalizeDropdownMultiValue: selectAllValue}} @@ -142,6 +144,7 @@ </mat-option> <mat-option *ngFor="let template of ($filterDropdownData | async).templateNames" + [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" [value]="template" > {{ template }} @@ -165,7 +168,7 @@ disableOptionCentering panelClass="create-resources-dialog scrolling" [placeholder]="placeholders.sharing" - [multiple]="($filterDropdownData | async).sharingStatuses.length > 1" + multiple > <mat-select-trigger class="select__value"> {{sharingStatuses.value | normalizeDropdownMultiValue: selectAllValue | titlecase}} @@ -180,6 +183,7 @@ </mat-option> <mat-option *ngFor="let status of ($filterDropdownData | async).sharingStatuses" + [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" [value]="status" > {{ status | titlecase }} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.scss index 3754ff17a..343e7763f 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/page-filter/page-filter.component.scss @@ -56,6 +56,12 @@ } } +::ng-deep .cdk-overlay-pane.normalized-dropdown-position { + & .mat-option:first-child.single-option .mat-pseudo-checkbox { + display: none; + } +} + .select__value { color: #607d8b; } 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 61a614fd7..01cee6637 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 @@ -19,6 +19,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { MatOption } from '@angular/material/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { take, tap } from 'rxjs/operators'; @@ -28,10 +29,10 @@ import { FilterFormPlaceholders } from './page-filter.config'; import { DropdownFieldNames, DropdownSelectAllValue, + FilterFormControlNames, ImageFilterFormDropdownData, ImageFilterFormValue } from '../../images'; -import { MatOption } from '@angular/material/core'; @Component({ selector: 'datalab-page-filter', @@ -49,6 +50,7 @@ export class PageFilterComponent implements OnInit { readonly placeholders: typeof FilterFormPlaceholders = FilterFormPlaceholders; readonly dropdownFieldNames: typeof DropdownFieldNames = DropdownFieldNames; + readonly controlNames: typeof FilterFormControlNames = FilterFormControlNames; readonly selectAllValue = DropdownSelectAllValue; private $$isApplyBtnDisabled: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); @@ -65,7 +67,7 @@ export class PageFilterComponent implements OnInit { ngOnInit(): void { this.createFilterForm(); - this.onControlChange(DropdownFieldNames.imageName); + this.onControlChange(FilterFormControlNames.imageName); this.setFilterValue(); this.isFilterFormChanged(); } @@ -83,7 +85,7 @@ export class PageFilterComponent implements OnInit { this.closeFilter.emit(); } - onControlChange(fieldName: keyof ImageFilterFormDropdownData): void { + onControlChange(fieldName: keyof ImageFilterFormValue): void { this.filterForm.get(fieldName)?.valueChanges.pipe( tap((inputValue: string) => this.onValueChanges.emit(inputValue)) ).subscribe(); @@ -112,9 +114,13 @@ export class PageFilterComponent implements OnInit { private setFilterValue(): void { this.$setFilterValueObservable = this.$filterFormStartValue.pipe( - tap(value => this.filterFormStartValue = value), - tap(value => this.filterForm.patchValue(value) - )); + tap(value => this.updateFilterForm(value)) + ); + } + + private updateFilterForm(value: ImageFilterFormValue): void { + this.filterFormStartValue = value; + this.filterForm.patchValue(value); } private isFilterFormChanged(): void { 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 7eb49c4bb..0003c4413 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 @@ -111,7 +111,7 @@ [$filterFormStartValue]="$filterFormValue" (filterFormValue)="onFilterApplyClick($event)" (closeFilter)="onFilterCancelClick()" - (onValueChanges)="onControlChanges(dropdownFieldNames.imageName, $event)" + (onValueChanges)="onControlChanges(dropdownFieldNames.imageNames, $event)" > </datalab-page-filter> </div> @@ -179,7 +179,7 @@ *ngIf="($filteredColumnState | async)?.imageName" type="button" class="close__btn header__close--btn" - (click)="onResetColumn(dropdownFieldNames.imageName)" + (click)="onResetColumn(dropdownFieldNames.imageNames)" > × </button> 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 9eb9cd37a..e679857cb 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 @@ -176,7 +176,7 @@ export class ImagesComponent implements OnInit, OnDestroy { onControlChanges(controlName: keyof ImageFilterFormDropdownData, inputValue: string): void { const normalizedInputValue = inputValue.toLowerCase(); - this.imagesService.filterDropdownField(DropdownFieldNames.imageName, normalizedInputValue); + this.imagesService.filterDropdownField(DropdownFieldNames.imageNames, normalizedInputValue); } toggleShowActive(): void { @@ -222,9 +222,7 @@ export class ImagesComponent implements OnInit, OnDestroy { private getUserImagePageInfo(): void { this.route.data.pipe( map(data => data['projectList']), - tap(projectList => { - return this.getProjectList(projectList); - }) + tap(({projectImagesInfos}) => this.getProjectList(projectImagesInfos)) ).subscribe(); } 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 06867d403..4f419b7d8 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 @@ -70,6 +70,14 @@ export enum TooltipStatuses { } export enum DropdownFieldNames { + imageNames = 'imageNames', + endpoints = 'endpoints', + templateNames = 'templateNames', + statuses = 'statuses', + sharingStatuses = 'sharingStatuses' +} + +export enum FilterFormControlNames { imageName = 'imageName', endpoints = 'endpoints', templateNames = 'templateNames', @@ -95,7 +103,7 @@ export const FilterFormInitialValue = { export const ChangedColumnStartValue = { endpoints: false, - imageName: false, + imageNames: false, statuses: false, templateNames: false, sharingStatuses: false, 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 e89098834..830f911b8 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 @@ -1,3 +1,9 @@ +export interface ProjectImagesInfo { + filterData: ImageFilterFormDropdownData; + imageFilter: ImageFilterFormValue; + projectImagesInfos: ProjectModel[]; +} + export interface ProjectModel { project: string; images: ImageModel[]; @@ -50,7 +56,7 @@ export interface ClusterConfig { } export interface ImageFilterFormDropdownData { - imageName: string[]; + imageNames: string[]; statuses: string[]; endpoints: string[]; templateNames: string[]; @@ -72,7 +78,7 @@ export interface LibraryInfoItem { } export interface FilteredColumnList { - imageName: boolean; + imageNames: boolean; statuses: boolean; endpoints: boolean; templateNames: boolean; 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 2c0a30f33..bf9c87930 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 @@ -8,12 +8,12 @@ import { ImageFilterFormDropdownData, ImageFilterFormValue, ImageModel, + ProjectImagesInfo, ProjectModel, ShareImageAllUsersParams } from './images.model'; import { ApplicationServiceFacade, UserImagesPageService } from '../../core/services'; -import { ChangedColumnStartValue, FilterFormInitialValue, ImageModelNames } from './images.config'; -import { caseInsensitiveSortUtil } from '../../core/util'; +import { ChangedColumnStartValue, FilterFormInitialValue } from './images.config'; @Injectable({ providedIn: 'root' @@ -45,23 +45,22 @@ export class ImagesService { private userImagesPageService: UserImagesPageService ) { } - getImagePageInfo(): Observable<ProjectModel[]> { + getImagePageInfo(): Observable<ProjectImagesInfo> { return this.userImagesPageService.getFilterImagePage() .pipe( - tap(value => this.getImagePageData(value)), - take(1) + tap(imagePageInfo => this.initImagePageInfo(imagePageInfo)) ); } - filterImagePageInfo(params: ImageFilterFormValue): Observable<ProjectModel[]> { + filterImagePageInfo(params: ImageFilterFormValue): Observable<ProjectImagesInfo> { return this.userImagesPageService.filterImagePage(params) .pipe( - tap(value => this.getImagePageData(value)), + tap(value => this.getImagePageData(value.projectImagesInfos)), take(1) ); } - shareImageAllUsers(image: ImageModel): Observable<ProjectModel[]> { + shareImageAllUsers(image: ImageModel): Observable<ProjectImagesInfo> { const shareParams: ShareImageAllUsersParams = { imageName: image.name, projectName: image.project, @@ -70,7 +69,7 @@ export class ImagesService { return this.userImagesPageService.shareImagesAllUser(shareParams) .pipe( - tap(value => this.getImagePageData(value)), + tap(value => this.getImagePageData(value.projectImagesInfos)), take(1) ); } @@ -107,10 +106,6 @@ export class ImagesService { this.$$imageList.next(updatedImageList); } - isImageSelected(): boolean { - return this.$$imageList.value.some(image => image.isSelected); - } - openFilter(): void { this.$$isFilterOpened.next(true); } @@ -121,7 +116,7 @@ export class ImagesService { filterDropdownField(field: keyof ImageFilterFormDropdownData, value: string, ): void { const filteredDropdownList = this.dropdownStartValue[field].filter(item => item.toLowerCase().includes(value)); - this.addFilterDropdownData({...this.$$filterDropdownData.value, imageName: filteredDropdownList}); + this.addFilterDropdownData({...this.$$filterDropdownData.value, imageNames: filteredDropdownList}); } resetFilterField(field: keyof ImageFilterFormDropdownData, exceptionValue: string = ''): void { @@ -174,6 +169,14 @@ export class ImagesService { this.$$isImageListFiltered.next(isImageListFiltered); } + private initImagePageInfo(imagePageInfo: ProjectImagesInfo): void { + this.getImagePageData(imagePageInfo.projectImagesInfos); + this.getDropdownDataList(imagePageInfo.filterData); + this.setFilterFormValue(imagePageInfo.imageFilter); + this.updateFilterColumnState(imagePageInfo.imageFilter); + this.checkIsPageFiltered(); + } + private checkColumnState(acc: FilteredColumnList, fieldItem: FilterFormItemType): FilteredColumnList { const [ fieldName, fieldValue ] = fieldItem; let isColumnFiltered: boolean; @@ -204,28 +207,11 @@ export class ImagesService { this.$$cashedProjectList.next(projectList); } - private getDropdownDataList(): void { - const dropdownList = { - imageName: this.getDropdownDataItem(ImageModelNames.name), - statuses: this.getDropdownDataItem(ImageModelNames.status), - endpoints: this.getDropdownDataItem(ImageModelNames.endpoint), - templateNames: this.getDropdownDataItem(ImageModelNames.templateName), - sharingStatuses: this.getDropdownDataItem(ImageModelNames.sharingStatus), - }; + private getDropdownDataList(dropdownList: ImageFilterFormDropdownData): void { this.addFilterDropdownData(dropdownList); this.dropdownStartValue = dropdownList; } - private getDropdownDataItem(key: keyof ImageModel): string[] { - const dropdownItem = this.$$imageList.value.reduce((acc: Set<string>, item) => { - if (item) { - acc.add(<string>item[key]); - } - return acc; - }, new Set<string>()); - return caseInsensitiveSortUtil([...dropdownItem]); - } - private addFilterDropdownData(data: ImageFilterFormDropdownData): void { this.$$filterDropdownData.next(data); } @@ -235,7 +221,6 @@ export class ImagesService { this.updateProjectList(imagePageData); this.updateImageList(imageList); this.updateCashedProjectList(imagePageData); - this.getDropdownDataList(); this.$$isProjectListEmpty.next(this.isProjectListEmpty(imagePageData)); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
