This is an automated email from the ASF dual-hosted git repository. hshpak pushed a commit to branch feat/DATALAB-3008/support-autocomplete-for-sharing-dialog in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 14fb48ab2cb3c2494cf5513fdaff5893cdd13e53 Author: Hennadii_Shpak <[email protected]> AuthorDate: Thu Sep 15 15:08:55 2022 +0300 [DATALAB-3008] implemented logyc by request for input dropdown --- .../app/core/directives/click-outside.directive.ts | 2 +- .../app/core/services/user-images-page.service.ts | 22 ++- .../image-action-dialog.component.html | 4 +- .../image-action-dialog.component.scss | 4 - .../image-action-dialog.component.ts | 15 ++- .../image-action-dialog.module.ts | 4 +- .../image-action-dialog/image-action.model.ts | 5 + .../share-dialog/share-dialog.component.html | 96 ++++++------- .../share-dialog/share-dialog.component.scss | 40 ++++-- .../share-dialog/share-dialog.component.ts | 148 +++++++++++---------- .../share-dialog/share-dialog.service.ts | 91 +++++++++++++ .../share-user-data/share-user-data.component.html | 2 +- .../share-user-data/share-user-data.component.ts | 4 +- .../un-share-warning.component.html | 2 +- .../page-filter/page-filter.component.html | 32 ++--- .../page-filter/page-filter.component.ts | 20 +-- .../src/app/resources/images/images.component.html | 4 +- .../src/app/resources/images/images.component.ts | 16 +-- .../src/app/resources/images/images.config.ts | 5 + .../src/app/resources/images/images.model.ts | 2 +- .../src/app/resources/images/images.service.ts | 90 ++++++------- 21 files changed, 367 insertions(+), 241 deletions(-) diff --git a/services/self-service/src/main/resources/webapp/src/app/core/directives/click-outside.directive.ts b/services/self-service/src/main/resources/webapp/src/app/core/directives/click-outside.directive.ts index ad34ab242..e19f0cd0c 100644 --- a/services/self-service/src/main/resources/webapp/src/app/core/directives/click-outside.directive.ts +++ b/services/self-service/src/main/resources/webapp/src/app/core/directives/click-outside.directive.ts @@ -76,4 +76,4 @@ export class ClickOutsideDirective implements OnInit, OnDestroy { } return false; } -} \ No newline at end of file +} 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 5811202da..919af15a6 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 @@ -25,11 +25,11 @@ import { ErrorUtils } from '../util'; import { ApplicationServiceFacade } from './applicationServiceFacade.service'; import { ImageActionType, - ImageFilterFormValue, ImageModel, + ImageFilterFormValue, ProjectImagesInfo, - ImageParams + ImageParams, URL_Chunk } from '../../resources/images'; -import { UserData } from '../../resources/exploratory/image-action-dialog/image-action.model'; +import { ShareDialogData, UserData } from '../../resources/exploratory/image-action-dialog/image-action.model'; @Injectable() export class UserImagesPageService { @@ -69,9 +69,19 @@ export class UserImagesPageService { ); } - getImageShareInfo(image: ImageParams): Observable<UserData[]> { - const { imageName, projectName, endpoint} = image; - const url = `/sharing_info/${imageName}/${projectName}/${endpoint}/`; + getImageShareInfo(imageInfo: ImageParams): Observable<ShareDialogData> { + const { imageName, projectName, endpoint} = imageInfo; + const url = `/${URL_Chunk.sharingInfo}/${imageName}/${projectName}/${endpoint}/`; + return this.applicationServiceFacade + .buildGetImageShareInfo(url) + .pipe( + catchError(ErrorUtils.handleServiceError) + ); + } + + getUserDataForShareDropdown(imageInfo: ImageParams, userData: string): Observable<UserData[]> { + const { imageName, projectName, endpoint} = imageInfo; + const url = `/${URL_Chunk.autocomplete}/${imageName}/${projectName}/${endpoint}?value=${userData}`; return this.applicationServiceFacade .buildGetImageShareInfo(url) .pipe( diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.html index ea72dcaf3..c531d5423 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.html @@ -33,10 +33,10 @@ <div [hidden]="activeTabConfig && activeTabConfig.shareWith" class="text-center m-top-30 m-bott-10"> <button type="button" class="butt mat-raised-button" (click)="dialogRef.close()">No</button> <button - [disabled]="isApplyBtnDisabled" + [disabled]="isShareBtnDisabled" type="button" class="butt butt-success mat-raised-button" - (click)="dialogRef.close(responseObj)"> + (click)="dialogRef.close(sharingDataList)"> {{confirmBtnName}} </button> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.scss index 80ef60e42..ec94d5903 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.scss @@ -17,10 +17,6 @@ * under the License. */ -.dialog__wrapper { - height: 385px; -} - .content { max-height: 75vh; margin: 0; diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.ts index 79f7049b3..d07f7f47c 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.component.ts @@ -22,6 +22,11 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { ImageActions, ImageActionModalData } from '../../images'; import { DialogWindowTabConfig, UserData } from './image-action.model'; +const CONFIRM_BUTTON_CONFIG = { + share: 'Share', + terminate: 'Yes' +}; + @Component({ selector: 'datalab-image-action-dialog', templateUrl: './image-action-dialog.component.html', @@ -29,8 +34,8 @@ import { DialogWindowTabConfig, UserData } from './image-action.model'; }) export class ImageActionDialogComponent implements OnInit { @Input() activeTabConfig: DialogWindowTabConfig; - @Input() isApplyBtnDisabled: Boolean; - @Input() responseObj: UserData[] = []; + @Input() isShareBtnDisabled: Boolean; + @Input() sharingDataList: UserData[] = []; readonly actionType: typeof ImageActions = ImageActions; @@ -46,10 +51,6 @@ export class ImageActionDialogComponent implements OnInit { } private createConfirmBtnName(): void { - const btnNameObj = { - share: 'Share', - terminate: 'Yes' - }; - this.confirmBtnName = btnNameObj[this.data.actionType]; + this.confirmBtnName = CONFIRM_BUTTON_CONFIG[this.data.actionType]; } } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.module.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.module.ts index fc43e341d..a8e5b976e 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.module.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action-dialog.module.ts @@ -23,7 +23,7 @@ import { ImageActionDialogComponent } from './image-action-dialog.component'; import { MaterialModule } from '../../../shared/material.module'; import { TerminateDialogComponent } from './terminate-dialog/terminate-dialog.component'; import { ShareDialogComponent } from './share-dialog/share-dialog.component'; -import { FormsModule } from '@angular/forms'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ShareUserDataComponent } from './share-user-data/share-user-data.component'; import { UnShareWarningComponent } from './unshare-warning/un-share-warning.component'; @@ -37,7 +37,7 @@ import { UnShareWarningComponent } from './unshare-warning/un-share-warning.comp ShareUserDataComponent, UnShareWarningComponent ], - imports: [ CommonModule, MaterialModule, FormsModule ], + imports: [ CommonModule, MaterialModule, FormsModule, ReactiveFormsModule ], entryComponents: [TerminateDialogComponent , ShareDialogComponent, UnShareWarningComponent], exports: [ ImageActionDialogComponent ] }) diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action.model.ts index 8c16eecd5..42de04e41 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action.model.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/image-action.model.ts @@ -27,5 +27,10 @@ export interface UserData { type: UserDataType; } +export interface ShareDialogData { + canBeSharedWith: UserData[]; + sharedWith: UserData[]; +} + export type UserDataType = 'USER' | 'GROUP'; diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.html index fc2d6e7d1..e91d48890 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.html @@ -19,11 +19,14 @@ <datalab-image-action-dialog [activeTabConfig]="activeTabConfig" - [responseObj]="responseObj" - [isApplyBtnDisabled]="isApplyBtnDisabled" + [sharingDataList]="sharingDataList" + [isShareBtnDisabled]="!isShareBtnDisabled" > - <ng-container *ngIf="($getUserListData | async)"></ng-container> +<!-- Component subscription--> + <ng-container *ngIf="(getUserListDataSubscription$ | async)"></ng-container> + <ng-container *ngIf="(getUserListDataOnChangeSubscription$ | async)"></ng-container> + <ng-container *ngIf="(onInputSubscription$ | async)"></ng-container> <div datalab-share-dialog class="dialog__wrapper"> <ul class="title__list"> @@ -53,62 +56,61 @@ <div *ngIf="activeTabConfig.shareImage" class="search-input__wrapper"> -<!-- TODO REMOVE IT WHEN REMOVING THE RADIO BUTTON FROM APP--> - - <div class="radio__wrapper"> - <div class="radio-input__wrapper"> - <label> - user - <input - name="user-radio" - type="radio" - [(ngModel)]="userNameOrGroup" - [value]="userDataTypeConfig.user"> - </label> - <label> - user group - <input - name="group-radio" - type="radio" - [(ngModel)]="userNameOrGroup" - [value]="userDataTypeConfig.group"> - </label> - </div> - <span [hidden]="!isSearchUserTouched" class="error">Select with whom to share the image</span> - </div> <div class="input__wrapper"> <input + type="text" class="search-input" + panelClass="scrolling" [placeholder]="placeholder.groupOrNameSearchInput" - [(ngModel)]="searchInput" - #searchUser="ngModel" - (keydown.enter)="onAddUser()" - required - > - <button - class="add-person__btn" - mat-icon-button - [disabled]="isAddUserDataBtnDisabled" - (click)="onAddUser()" - > - <mat-icon> person_add </mat-icon> - </button> - <span [hidden]="!isUserInputEmpty" class="error">This field is required</span> - <span [hidden]="!isLongInputMessage" class="error">Length can`t be more than 25 symbols</span> + [formControl]="addUserDataControl" + (change)="onChange()" + (input)="onInputKeyDown()" + matInput + [matAutocomplete]="auto" + #searchUserData + /> + <mat-autocomplete #auto="matAutocomplete"> + <mat-option + *ngFor="let user of (searchUserDataDropdownList$ | async)" + (click)="addUserToTemporaryList(user)" + [value]="user.value"> + <mat-icon class="user-data__icon">{{user.type === 'GROUP' ? 'people' : 'person'}}</mat-icon> + {{user.value}} + </mat-option> + <mat-option *ngIf="!(searchUserDataDropdownList$ | async)?.length" class="multiple-select ml-10" disabled> + No results found + </mat-option> + </mat-autocomplete> + <span [hidden]="!isUserDataListEmpty" class="error"> + Please enter user login or group name + </span> </div> <div class="user-list__wrapper scrolling"> - <ul class="user-list"> - <li *ngFor="let entity of temporaryUserDataList" class="user-list__item"> - <datalab-share-user-data (removeUserData)="onRemoveUserData($event)" [userData]="entity"></datalab-share-user-data> + <ul class="user-list user-list__temporary"> + <li + *ngFor="let entity of (temporaryUserDataList$ | async)" + class="user-list__item" + > + <datalab-share-user-data + (removeUserData)="onRemoveUserData($event)" + [userData]="entity" + > + </datalab-share-user-data> </li> </ul> </div> </div> <div *ngIf="activeTabConfig.shareWith" class="share-with__wrapper"> - <div *ngIf="userDataList.length; else emptyUserList" class="user-list__wrapper scrolling"> - <ul class="user-list"> - <li *ngFor="let entity of userDataList" class="user-list__item"> + <div + *ngIf="(userDataList$ | async)?.length; else emptyUserList" + class="user-list__wrapper scrolling" + > + <ul class="user-list user-list__shared"> + <li + *ngFor="let entity of (userDataList$ | async)" + class="user-list__item" + > <datalab-share-user-data (removeUserData)="unShare($event)" [userData]="entity"></datalab-share-user-data> </li> </ul> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.scss b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.scss index 5d5aca78b..62748a486 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.scss +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.scss @@ -51,7 +51,13 @@ outline: none; &::placeholder { + font-size: 16px; color: #c6bcbc; + font-weight: 300; + } + + &__wrapper { + height: 149px; } } @@ -73,9 +79,16 @@ .user-list { display: flex; flex-wrap: wrap; - height: 80px; padding: 10px 0; + &__temporary { + height: 80px; + } + + &__shared { + height: 160px; + } + &__wrapper{ overflow-y: scroll; } @@ -103,19 +116,18 @@ color: #35afd5; } -// TODO REMOVE IT WHEN REMOVING THE RADIO BUTTON FROM APP -//start -.radio__wrapper { - margin-bottom: 20px; - padding-left: 10px; - text-align: start; -} -input[name="user-radio"] { - margin-right: 20px; +.share-with { + &__wrapper { + height: 225px; + } } -label { - font-weight: 300; +.user-data__icon { + width: 30px; + height: 30px; + padding-top: 2px; + text-align: center; + border-radius: 50%; + background-color: #E6E6E6; + color: white; } -//end - diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.ts index 08711f5b8..0cbbc035e 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.component.ts @@ -17,66 +17,94 @@ * under the License. */ -import { ChangeDetectionStrategy, Component, Inject, OnInit, ViewChild } from '@angular/core'; -import { SharePlaceholder, TabName, UserDataTypeConfig } from '../image-action.config'; -import { DialogWindowTabConfig, UserData, UserDataType } from '../image-action.model'; -import { NgModel } from '@angular/forms'; +import { Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { SharePlaceholder, TabName } from '../image-action.config'; +import { DialogWindowTabConfig, ShareDialogData, UserData } from '../image-action.model'; +import { FormControl } from '@angular/forms'; import { ImagesService } from '../../../images/images.service'; import { MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog'; -import { ImageActionModalData, ImageParams, ModalTitle, ProjectImagesInfo, Toaster_Message, UnShareModal } from '../../../images'; +import { + ImageActionModalData, + ModalTitle, + Toaster_Message, + UnShareModal, +} from '../../../images'; import { switchMap, tap } from 'rxjs/operators'; -import { EMPTY, Observable } from 'rxjs'; +import { Observable, timer } from 'rxjs'; import { UnShareWarningComponent } from '../unshare-warning/un-share-warning.component'; import { ToastrService } from 'ngx-toastr'; +import { ShareDialogService } from './share-dialog.service'; @Component({ selector: 'datalab-share-dialog', templateUrl: './share-dialog.component.html', styleUrls: ['./share-dialog.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush }) -export class ShareDialogComponent implements OnInit { - @ViewChild('searchUser') searchUser: NgModel; + +export class ShareDialogComponent implements OnInit, OnDestroy { + @ViewChild('searchUserData') searchUserData: ElementRef; readonly placeholder: typeof SharePlaceholder = SharePlaceholder; readonly tabsName: typeof TabName = TabName; - readonly userDataTypeConfig: typeof UserDataTypeConfig = UserDataTypeConfig; - userDataList: UserData[] = []; - temporaryUserDataList: UserData[] = []; - userNameOrGroup: UserDataType; + searchUserDataDropdownList$: Observable<UserData[]>; + userDataList$!: Observable<UserData[]>; + temporaryUserDataList$!: Observable<UserData[]>; + sharingDataList: UserData[] = []; activeTabConfig: DialogWindowTabConfig = { shareImage: true, shareWith: false }; - searchInput = ''; + addUserDataControl: FormControl = new FormControl(''); - $getUserListData: Observable<UserData[]>; + onInputSubscription$: Observable<UserData[]>; + getUserListDataSubscription$: Observable<ShareDialogData>; + getUserListDataOnChangeSubscription$: Observable<UserData[]>; constructor( + public toastr: ToastrService, private imagesService: ImagesService, @Inject(MAT_DIALOG_DATA) public data: ImageActionModalData, private dialog: MatDialog, - public toastr: ToastrService, + private shareDialogService: ShareDialogService ) { } ngOnInit(): void { - this.initUserList(); + this.getImageParams(); + this.getUserListDataSubscription$ = this.shareDialogService.getImageShareInfo(); + this.initUserData(); + this.initSearchDropdownList(); + this.initTemporaryUserDataList(); + } + + ngOnDestroy(): void { + this.shareDialogService.clearTemporaryList(); + } + + onInputKeyDown(): void { + this.onInputSubscription$ = timer(300).pipe( + switchMap(() => this.shareDialogService.getUserDataForShareDropdown(this.addUserDataControl.value)) + ); + } + + onChange(): void { + this.addUserDataControl.setValue(''); + // We need a timer because the click event cannot have time to select userData from the dropdown list. + this.getUserListDataOnChangeSubscription$ = timer(300).pipe( + switchMap(() => this.shareDialogService.getUserDataForShareDropdown()) + ); } - onAddUser(): void { - if (!this.searchInput) { + addUserToTemporaryList(user: UserData): void { + if (!user) { return; } - const newUserEntity: UserData = { - value: this.searchInput.trim(), - type: this.userNameOrGroup - }; - this.temporaryUserDataList = [...this.temporaryUserDataList, newUserEntity] - .sort((a, b) => a.value < b.value ? 1 : -1) - .sort((a, b) => a.type > b.type ? 1 : -1); - this.searchInput = ''; + this.shareDialogService.addToTemporaryList(user); + this.addUserDataControl.setValue(''); + this.searchUserData.nativeElement.blur(); + this.sharingDataList = this.shareDialogService.getSharingUserDataList(); + this.shareDialogService.filterSearchDropdown(); } onTabTitle(tabName: keyof DialogWindowTabConfig): void { @@ -84,75 +112,51 @@ export class ShareDialogComponent implements OnInit { this.activeTabConfig = {...this.activeTabConfig, [tabName]: true}; } - onRemoveUserData(userName: string): void { - this.temporaryUserDataList = this.temporaryUserDataList.filter(({value}) => value !== userName); + onRemoveUserData(userData: UserData): void { + this.shareDialogService.removeUserFromTemporaryList(userData); + this.shareDialogService.filterSearchDropdown(); } - unShare(userName: string): void { + unShare(userData: UserData): void { const data: UnShareModal = { - userName, + userData, title: ModalTitle.unShare }; - const filteredList = this.userDataList.filter(({value}) => value !== userName); + const filteredList = this.shareDialogService.filterSharingList(userData); const imageInfo = this.imagesService.createImageRequestInfo(this.data.image, filteredList); - this.$getUserListData = this.dialog.open(UnShareWarningComponent, { + this.getUserListDataSubscription$ = this.dialog.open(UnShareWarningComponent, { data, panelClass: 'modal-sm' }).afterClosed() .pipe( - switchMap((isShare) => this.sendShareRequest(isShare, imageInfo)), - switchMap(() => this.getSharingUserList()), + switchMap((isShare) => this.shareDialogService.sendShareRequest(isShare, imageInfo)), + switchMap(() => this.shareDialogService.getImageShareInfo()), tap(() => this.toastr.success(Toaster_Message.successUnShare, Toaster_Message.successTitle)) ); } - private sendShareRequest(flag: boolean, imageInfo: ImageParams): Observable<ProjectImagesInfo> { - if (!flag) { - return EMPTY; - } - return this.imagesService.shareImageAllUsers(imageInfo); - } - - private initUserList(): void { - this.$getUserListData = this.getSharingUserList(); - } - - private getSharingUserList(): Observable<UserData[]> { - const { name, project, endpoint} = this.data.image; - const imageParams = { - imageName: name, - projectName: project, - endpoint - }; - return this.imagesService.getImageShareInfo(imageParams).pipe( - tap(userListData => this.userDataList = userListData) - ); - } - - get responseObj(): UserData[] { - return [...this.temporaryUserDataList, ...this.userDataList]; + private getImageParams(): void { + this.shareDialogService.imageInfo = this.imagesService.createImageRequestInfo(this.data.image); } - get isApplyBtnDisabled(): boolean { - return this.searchInput.length > 25 || !Boolean(this.temporaryUserDataList.length); + private initUserData(): void { + this.userDataList$ = this.shareDialogService.userDataList$; } - get isAddUserDataBtnDisabled(): boolean { - return !Boolean(this.userNameOrGroup) || this.searchInput.length > 25 || !Boolean(this.searchInput.length); + private initSearchDropdownList(): void { + this.searchUserDataDropdownList$ = this.shareDialogService.searchUserDataDropdownList$; } - get isSearchUserTouched(): boolean { - return this.searchUser?.control.touched && !Boolean(this.userNameOrGroup); + private initTemporaryUserDataList(): void { + this.temporaryUserDataList$ = this.shareDialogService.temporaryUserDataList$; } - get isUserInputEmpty(): boolean { - return this.searchUser?.control.touched - && !Boolean(this.searchInput.length) - && !Boolean(this.temporaryUserDataList.length); + get isShareBtnDisabled(): boolean { + return !this.shareDialogService.isTemporaryListEmpty(); } - get isLongInputMessage() { - return this.searchInput.length > 25; + get isUserDataListEmpty(): boolean { + return this.addUserDataControl.touched && this.shareDialogService.isTemporaryListEmpty(); } } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.service.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.service.ts new file mode 100644 index 000000000..40a8aabf4 --- /dev/null +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-dialog/share-dialog.service.ts @@ -0,0 +1,91 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, EMPTY, Observable } from 'rxjs'; +import { take, tap } from 'rxjs/operators'; + +import isEqual from 'lodash.isequal'; + +import { ImagesService } from '../../../images/images.service'; +import { ImageActionDialogModule } from '../image-action-dialog.module'; +import { ImageParams, ProjectImagesInfo } from '../../../images'; +import { ShareDialogData, UserData } from '../image-action.model'; +import { UserImagesPageService } from '../../../../core/services'; + +@Injectable({ + providedIn: ImageActionDialogModule +}) +export class ShareDialogService { + private searchUserDataDropdownList$$: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]); + private userDataList$$: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]); + private temporaryUserDataList$$: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]); + private cashedUserDataDropdownList: UserData[]; + + searchUserDataDropdownList$: Observable<UserData[]> = this.searchUserDataDropdownList$$.asObservable(); + userDataList$: Observable<UserData[]> = this.userDataList$$.asObservable(); + temporaryUserDataList$: Observable<UserData[]> = this.temporaryUserDataList$$.asObservable(); + imageInfo: ImageParams; + + constructor( + private imagesService: ImagesService, + private userImagesPageService: UserImagesPageService + ) { } + + getUserDataForShareDropdown(userData: string = ''): Observable<UserData[]> { + return this.userImagesPageService.getUserDataForShareDropdown(this.imageInfo, userData) + .pipe( + tap(response => this.filterSearchDropdown(response)) + ); + } + + sendShareRequest(flag: boolean, imageInfo: ImageParams): Observable<ProjectImagesInfo> { + if (!flag) { + return EMPTY; + } + return this.imagesService.shareImageAllUsers(imageInfo); + } + + getImageShareInfo(): Observable<ShareDialogData> { + return this.userImagesPageService.getImageShareInfo(this.imageInfo).pipe( + tap(({canBeSharedWith, sharedWith}) => { + this.cashedUserDataDropdownList = canBeSharedWith; + this.searchUserDataDropdownList$$.next(canBeSharedWith); + this.userDataList$$.next(sharedWith); + }), + take(1) + ); + } + + filterSharingList(userData: UserData): UserData[] { + return this.userDataList$$.value.filter(item => !isEqual(item, userData)); + } + + getSharingUserDataList(): UserData[] { + return [...this.userDataList$$.value, ...this.temporaryUserDataList$$.value]; + } + + addToTemporaryList(user: UserData): void { + const filteredList = [...this.temporaryUserDataList$$.value, user] + .sort((a, b) => a.value < b.value ? 1 : -1) + .sort((a, b) => a.type > b.type ? 1 : -1); + this.temporaryUserDataList$$.next(filteredList); + } + + isTemporaryListEmpty(): boolean { + return !Boolean(this.temporaryUserDataList$$.value.length); + } + + clearTemporaryList(): void { + this.temporaryUserDataList$$.next([]); + } + + removeUserFromTemporaryList(userData: UserData): void { + const filteredList = this.temporaryUserDataList$$.value.filter(item => !isEqual(item, userData)); + this.temporaryUserDataList$$.next(filteredList); + } + + filterSearchDropdown(userData: UserData[] = this.cashedUserDataDropdownList): void { + const filteredDropdownList = userData.filter(item => !this.getSharingUserDataList() + .some(temporaryDataItem => isEqual(item, temporaryDataItem)) + ); + this.searchUserDataDropdownList$$.next(filteredDropdownList); + } +} diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.html index aa647e824..f8c8a580b 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.html @@ -20,6 +20,6 @@ <div class="user-data__wrapper"> <span><mat-icon class="user-data__icon">{{userData.type === 'GROUP' ? 'people' : 'person'}}</mat-icon></span> <span class="user-data__name">{{userData.value}} - <button type="button" (click)="removeUser(userData.value)" class="close-btn">×</button> + <button type="button" (click)="removeUser(userData)" class="close-btn">×</button> </span> </div> diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.ts index 9468d21ed..ba52a47fd 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.ts +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/share-user-data/share-user-data.component.ts @@ -28,9 +28,9 @@ import { UserData } from '../image-action.model'; export class ShareUserDataComponent { @Input() userData: UserData; - @Output() removeUserData: EventEmitter<string> = new EventEmitter<string>(); + @Output() removeUserData: EventEmitter<UserData> = new EventEmitter<UserData>(); - removeUser(userData: string): void { + removeUser(userData: UserData): void { this.removeUserData.emit(userData); } } diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/unshare-warning/un-share-warning.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/unshare-warning/un-share-warning.component.html index 073d20067..b1c9cfabd 100644 --- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/unshare-warning/un-share-warning.component.html +++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/image-action-dialog/unshare-warning/un-share-warning.component.html @@ -24,7 +24,7 @@ <button type="button" class="close" (click)="dialogRef.close()">×</button> </header> <section class="content"> - <p class="modal__text">User <span class="user__name">{{data.userName}}</span> will no longer have an access to the image.</p> + <p class="modal__text"><span>{{data.userData.type | titlecase}} </span> <span class="user__name">{{data.userData.value}}</span> will no longer have an access to the image.</p> <p class="question center"> Do you want proceed? </p> 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 818a8a5b2..62fce4380 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 @@ -19,8 +19,8 @@ <div class="dialog-content selection"> - <ng-container *ngIf="$setFilterValueObservable | async"></ng-container> - <ng-container *ngIf="$changeIsApplyBtnDisabledObservable | async"></ng-container> + <ng-container *ngIf="setFilterValueObservable$ | async"></ng-container> + <ng-container *ngIf="changeIsApplyBtnDisabledObservable$ | async"></ng-container> <div id="scrolling" class="mat-reset"> <form class="filter-table__wrapper" [formGroup]="filterForm"> @@ -35,7 +35,7 @@ [matAutocomplete]="auto" /> <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"> - <mat-option *ngFor="let option of ($filterDropdownData | async).imageNames" [value]="option"> + <mat-option *ngFor="let option of (filterDropdownData$ | async).imageNames" [value]="option"> {{option}} </mat-option> </mat-autocomplete> @@ -57,7 +57,7 @@ {{statuses.value | normalizeDropdownMultiValue: selectAllValue | titlecase}} </mat-select-trigger> <mat-option - *ngIf="($filterDropdownData | async).statuses.length > 1" + *ngIf="(filterDropdownData$ | async).statuses.length > 1" #allStatusesSelected [value]="selectAllValue" (click)="onClickAll(statuses, allStatusesSelected, dropdownFieldNames.statuses)" @@ -65,8 +65,8 @@ All </mat-option> <mat-option - *ngFor="let status of ($filterDropdownData | async).statuses" - [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" + *ngFor="let status of (filterDropdownData$ | async).statuses" + [ngClass]="{'single-option': (filterDropdownData$ | async).statuses.length === 1}" [value]="status" > {{ status | titlecase }} @@ -96,7 +96,7 @@ {{endpoints.value | normalizeDropdownMultiValue: selectAllValue}} </mat-select-trigger> <mat-option - *ngIf="($filterDropdownData | async).endpoints.length > 1" + *ngIf="(filterDropdownData$ | async).endpoints.length > 1" #allEndpointsSelected [value]="selectAllValue" (click)="onClickAll(endpoints, allEndpointsSelected, dropdownFieldNames.endpoints)" @@ -104,8 +104,8 @@ All </mat-option> <mat-option - *ngFor="let endpoint of ($filterDropdownData | async).endpoints" - [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" + *ngFor="let endpoint of (filterDropdownData$ | async).endpoints" + [ngClass]="{'single-option': (filterDropdownData$ | async).statuses.length === 1}" [value]="endpoint" > {{ endpoint }} @@ -135,7 +135,7 @@ {{templateNames.value | normalizeDropdownMultiValue: selectAllValue}} </mat-select-trigger> <mat-option - *ngIf="($filterDropdownData | async).templateNames.length > 1" + *ngIf="(filterDropdownData$ | async).templateNames.length > 1" #allTemplatesSelected [value]="selectAllValue" (click)="onClickAll(templateNames, allTemplatesSelected, dropdownFieldNames.templateNames)" @@ -143,8 +143,8 @@ All </mat-option> <mat-option - *ngFor="let template of ($filterDropdownData | async).templateNames" - [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" + *ngFor="let template of (filterDropdownData$ | async).templateNames" + [ngClass]="{'single-option': (filterDropdownData$ | async).statuses.length === 1}" [value]="template" > {{ template }} @@ -174,7 +174,7 @@ {{sharingStatuses.value | normalizeDropdownMultiValue: selectAllValue | titlecase}} </mat-select-trigger> <mat-option - *ngIf="($filterDropdownData | async).sharingStatuses.length > 1" + *ngIf="(filterDropdownData$ | async).sharingStatuses.length > 1" #allSharingStatusesSelected [value]="selectAllValue" (click)="onClickAll(sharingStatuses, allSharingStatusesSelected, dropdownFieldNames.sharingStatuses)" @@ -182,8 +182,8 @@ All </mat-option> <mat-option - *ngFor="let status of ($filterDropdownData | async).sharingStatuses" - [ngClass]="{'single-option': ($filterDropdownData | async).statuses.length === 1}" + *ngFor="let status of (filterDropdownData$ | async).sharingStatuses" + [ngClass]="{'single-option': (filterDropdownData$ | async).statuses.length === 1}" [value]="status" > {{ status | titlecase }} @@ -201,7 +201,7 @@ <button type="button" class="butt" mat-raised-button (click)="cancelFilter()" >Cancel</button> <button type="button" - [disabled]="($isApplyBtnDisabled | async)" + [disabled]="(isApplyBtnDisabled$ | async)" class="butt butt-success" mat-raised-button (click)="confirmFilter()" 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 0c7961786..5a5803b1c 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 @@ -40,8 +40,8 @@ import { styleUrls: ['./page-filter.component.scss'] }) export class PageFilterComponent implements OnInit { - @Input() $filterDropdownData: Observable<ImageFilterFormDropdownData>; - @Input() $filterFormStartValue: Observable<ImageFilterFormValue>; + @Input() filterDropdownData$: Observable<ImageFilterFormDropdownData>; + @Input() filterFormStartValue$: Observable<ImageFilterFormValue>; @Output() filterFormValue: EventEmitter<ImageFilterFormValue> = new EventEmitter<ImageFilterFormValue>(); @Output() closeFilter: EventEmitter<any> = new EventEmitter<any>(); @@ -53,13 +53,13 @@ export class PageFilterComponent implements OnInit { readonly controlNames: typeof FilterFormControlNames = FilterFormControlNames; readonly selectAllValue = DropdownSelectAllValue; - private $$isApplyBtnDisabled: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); + private isApplyBtnDisabled$$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); private filterFormStartValue: ImageFilterFormValue; filterForm: FormGroup; - $setFilterValueObservable: Observable<ImageFilterFormValue>; - $changeIsApplyBtnDisabledObservable: Observable<ImageFilterFormValue>; - $isApplyBtnDisabled: Observable<boolean> = this.$$isApplyBtnDisabled.asObservable(); + setFilterValueObservable$: Observable<ImageFilterFormValue>; + changeIsApplyBtnDisabledObservable$: Observable<ImageFilterFormValue>; + isApplyBtnDisabled$: Observable<boolean> = this.isApplyBtnDisabled$$.asObservable(); constructor( private fb: FormBuilder @@ -93,7 +93,7 @@ export class PageFilterComponent implements OnInit { onClickAll(control: FormControl, allSelected: MatOption, key: DropdownFieldNames ): void { if (allSelected.selected) { - this.$filterDropdownData.pipe( + this.filterDropdownData$.pipe( tap(value => control.patchValue([...value[key], this.selectAllValue])), take(1) ).subscribe(); @@ -113,7 +113,7 @@ export class PageFilterComponent implements OnInit { } private setFilterValue(): void { - this.$setFilterValueObservable = this.$filterFormStartValue.pipe( + this.setFilterValueObservable$ = this.filterFormStartValue$.pipe( tap(value => this.updateFilterForm(value)) ); } @@ -124,8 +124,8 @@ export class PageFilterComponent implements OnInit { } private isFilterFormChanged(): void { - this.$changeIsApplyBtnDisabledObservable = this.filterForm.valueChanges.pipe( - tap(formValue => this.$$isApplyBtnDisabled.next(isEqual(formValue, this.filterFormStartValue))) + this.changeIsApplyBtnDisabledObservable$ = this.filterForm.valueChanges.pipe( + tap(formValue => this.isApplyBtnDisabled$$.next(isEqual(formValue, this.filterFormStartValue))) ); } 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 508e3c1b2..12321aba0 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 @@ -107,8 +107,8 @@ <div *ngIf="isFilterOpened | async" class="filer__component--wrapper"> <datalab-page-filter - [$filterDropdownData]="$filterDropdownData" - [$filterFormStartValue]="$filterFormValue" + [filterDropdownData$]="$filterDropdownData" + [filterFormStartValue$]="$filterFormValue" (filterFormValue)="onFilterApplyClick($event)" (closeFilter)="onFilterCancelClick()" (onValueChanges)="onControlChanges(dropdownFieldNames.imageNames, $event)" 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 3ab7dd033..66f2425f2 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 @@ -264,7 +264,7 @@ export class ImagesComponent implements OnInit, OnDestroy { } private initFilteredColumnState(): void { - this.$filteredColumnState = this.imagesService.$filteredColumnState; + this.$filteredColumnState = this.imagesService.filteredColumnState$; } private getUserImagePageInfo(): void { @@ -276,8 +276,8 @@ export class ImagesComponent implements OnInit, OnDestroy { } private initImageTable(): void { - this.dataSource = this.imagesService.$imageList; - this.projectSource = this.imagesService.$projectList; + this.dataSource = this.imagesService.imageList$; + this.projectSource = this.imagesService.projectList$; } private getProjectList(imagePageList: ProjectModel[]): void { @@ -296,22 +296,22 @@ export class ImagesComponent implements OnInit, OnDestroy { } private initFilterBtn(): void { - this.isFilterOpened = this.imagesService.$isFilterOpened; + this.isFilterOpened = this.imagesService.isFilterOpened$; } private getDropdownList(): void { - this.$filterDropdownData = this.imagesService.$filterDropdownData; + this.$filterDropdownData = this.imagesService.filterDropdownData$; } private getFilterFormValue(): void { - this.$filterFormValue = this.imagesService.$filterFormValue; + this.$filterFormValue = this.imagesService.filterFormValue$; } private getIsProjectListEmpty(): void { - this.$isProjectListEmpty = this.imagesService.$isProjectListEmpty; + this.$isProjectListEmpty = this.imagesService.isProjectListEmpty$; } private initIsImageListFiltered(): void { - this.$isFiltered = this.imagesService.$isImageListFiltered; + this.$isFiltered = this.imagesService.isImageListFiltered$; } } 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 82c4a65e3..fb5e0860e 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 @@ -124,3 +124,8 @@ export enum ModalTitle { terminate = 'Terminate image', unShare = '! Warning' } + +export enum URL_Chunk { + sharingInfo = 'sharing_info', + autocomplete = 'share_autocomplete' +} 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 25eaa7f72..4f874ecc5 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 @@ -128,6 +128,6 @@ export interface FilteredColumnList { export type FilterFormItemType = [string, string[] | string]; export interface UnShareModal { - userName: string; + userData: UserData; title: ModalTitle; } 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 469086713..f37650960 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 @@ -25,26 +25,26 @@ import { UserData } from '../exploratory/image-action-dialog/image-action.model' providedIn: 'root' }) export class ImagesService { - private $$projectList: BehaviorSubject<ProjectModel[]> = new BehaviorSubject<ProjectModel[]>([]); - private $$isProjectListEmpty: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); - private $$cashedProjectList: BehaviorSubject<ProjectModel[]> = new BehaviorSubject<ProjectModel[]>([]); - private $$imageList: BehaviorSubject<ImageModel[]> = new BehaviorSubject<ImageModel[]>([]); - private $$isFilterOpened: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); + private projectList$$: BehaviorSubject<ProjectModel[]> = new BehaviorSubject<ProjectModel[]>([]); + private isProjectListEmpty$$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); + private cashedProjectList$$: BehaviorSubject<ProjectModel[]> = new BehaviorSubject<ProjectModel[]>([]); + private imageList$$: BehaviorSubject<ImageModel[]> = new BehaviorSubject<ImageModel[]>([]); + private isFilterOpened$$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); // tslint:disable-next-line:max-line-length - private $$filterDropdownData: BehaviorSubject<ImageFilterFormDropdownData> = new BehaviorSubject<ImageFilterFormDropdownData>({} as ImageFilterFormDropdownData); - private $$filterFormValue: BehaviorSubject<ImageFilterFormValue> = new BehaviorSubject<ImageFilterFormValue>(FilterFormInitialValue); - private $$filteredColumnState: BehaviorSubject<FilteredColumnList> = new BehaviorSubject<FilteredColumnList>(ChangedColumnStartValue); - private $$isImageListFiltered: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); + private filterDropdownData$$: BehaviorSubject<ImageFilterFormDropdownData> = new BehaviorSubject<ImageFilterFormDropdownData>({} as ImageFilterFormDropdownData); + private filterFormValue$$: BehaviorSubject<ImageFilterFormValue> = new BehaviorSubject<ImageFilterFormValue>(FilterFormInitialValue); + private filteredColumnState$$: BehaviorSubject<FilteredColumnList> = new BehaviorSubject<FilteredColumnList>(ChangedColumnStartValue); + private isImageListFiltered$$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); private dropdownStartValue: ImageFilterFormDropdownData; - $projectList = this.$$projectList.asObservable(); - $isProjectListEmpty = this.$$isProjectListEmpty.asObservable(); - $imageList = this.$$imageList.asObservable(); - $isFilterOpened = this.$$isFilterOpened.asObservable(); - $filterDropdownData = this.$$filterDropdownData.asObservable(); - $filterFormValue = this.$$filterFormValue.asObservable(); - $filteredColumnState = this.$$filteredColumnState.asObservable(); - $isImageListFiltered = this.$$isImageListFiltered.asObservable(); + projectList$ = this.projectList$$.asObservable(); + isProjectListEmpty$ = this.isProjectListEmpty$$.asObservable(); + imageList$ = this.imageList$$.asObservable(); + isFilterOpened$ = this.isFilterOpened$$.asObservable(); + filterDropdownData$ = this.filterDropdownData$$.asObservable(); + filterFormValue$ = this.filterFormValue$$.asObservable(); + filteredColumnState$ = this.filteredColumnState$$.asObservable(); + isImageListFiltered$ = this.isImageListFiltered$$.asObservable(); constructor( private applicationServiceFacade: ApplicationServiceFacade, @@ -82,19 +82,15 @@ export class ImagesService { ); } - getImageShareInfo(imageInfo: ImageParams): Observable<UserData[]> { - return this.userImagesPageService.getImageShareInfo(imageInfo); - } - getActiveProject(projectName: string): void { - const projectList = this.$$cashedProjectList.getValue(); + const projectList = this.cashedProjectList$$.getValue(); if (!projectName) { this.updateProjectList(projectList); - this.$$isProjectListEmpty.next(this.isProjectListEmpty(projectList)); + this.isProjectListEmpty$$.next(this.isProjectListEmpty(projectList)); } else { const currentProject = projectList.find(({project}) => project === projectName); this.updateProjectList([currentProject]); - this.$$isProjectListEmpty.next(this.isProjectListEmpty([currentProject])); + this.isProjectListEmpty$$.next(this.isProjectListEmpty([currentProject])); } } @@ -103,37 +99,37 @@ export class ImagesService { } updateImageList(imageList: ImageModel[]): void { - this.$$imageList.next(imageList); + this.imageList$$.next(imageList); } updateProjectList(projectList: ProjectModel[]): void { - this.$$projectList.next(projectList); + this.projectList$$.next(projectList); } changeCheckboxValue(value: boolean): void { - const updatedImageList = this.$$imageList.value.map(image => { + const updatedImageList = this.imageList$$.value.map(image => { image.isSelected = value; return image; }); - this.$$imageList.next(updatedImageList); + this.imageList$$.next(updatedImageList); } openFilter(): void { - this.$$isFilterOpened.next(true); + this.isFilterOpened$$.next(true); } closeFilter(): void { - this.$$isFilterOpened.next(false); + this.isFilterOpened$$.next(false); } filterDropdownField(field: keyof ImageFilterFormDropdownData, value: string, ): void { const filteredDropdownList = this.dropdownStartValue[field].filter(item => item.toLowerCase().includes(value)); - this.addFilterDropdownData({...this.$$filterDropdownData.value, imageNames: filteredDropdownList}); + this.addFilterDropdownData({...this.filterDropdownData$$.value, imageNames: filteredDropdownList}); } resetFilterField(field: keyof ImageFilterFormValue, exceptionValue: string = ''): void { const droppedFieldValue = this.getDroppedFieldValue(field); - const updatedFilterFormValue = {...this.$$filterFormValue.value, [field]: droppedFieldValue}; + const updatedFilterFormValue = {...this.filterFormValue$$.value, [field]: droppedFieldValue}; const normalizeFormValue = this.normalizeFilterFormValue(updatedFilterFormValue, exceptionValue); this.setFilterFormValue(updatedFilterFormValue); this.updateFilterColumnState(normalizeFormValue); @@ -142,15 +138,15 @@ export class ImagesService { } setFilterFormValue(value: ImageFilterFormValue): void { - this.$$filterFormValue.next(value); + this.filterFormValue$$.next(value); } showImage(flag: boolean, field: keyof ImageModel, comparedValue: string): void { - const projectList = this.$$cashedProjectList.getValue(); + const projectList = this.cashedProjectList$$.getValue(); if (flag) { this.updateProjectList(projectList); } else { - const filteredImageList = this.filterByCondition(this.$$projectList.getValue(), field, comparedValue); + const filteredImageList = this.filterByCondition(this.projectList$$.getValue(), field, comparedValue); this.updateProjectList(filteredImageList); } } @@ -167,28 +163,32 @@ export class ImagesService { const columnStateList = (<any>Object).entries(filterFormValue) .reduce((acc, fieldItem) => this.checkColumnState(acc, fieldItem), <FilteredColumnList>{}); - this.$$filteredColumnState.next(columnStateList); + this.filteredColumnState$$.next(columnStateList); } getDroppedFieldValue(field: keyof ImageFilterFormValue): string | [] { - return typeof this.$$filterFormValue.value[field] === 'string' + return typeof this.filterFormValue$$.value[field] === 'string' ? '' : []; } checkIsPageFiltered(): void { - const isImageListFiltered = (<any>Object).values(this.$$filteredColumnState.value).some(item => Boolean(item)); - this.$$isImageListFiltered.next(isImageListFiltered); + const isImageListFiltered = (<any>Object).values(this.filteredColumnState$$.value).some(item => Boolean(item)); + this.isImageListFiltered$$.next(isImageListFiltered); } - createImageRequestInfo(image: ImageModel, userDataList: UserData[]): ImageParams { + createImageRequestInfo(image: ImageModel, userDataList?: UserData[]): ImageParams { const { name, project, endpoint } = image; - return { + const imageParams = { imageName: name, projectName: project, endpoint: endpoint, - sharedWith: userDataList }; + + if (userDataList) { + imageParams['sharedWith'] = userDataList; + } + return imageParams; } createActionDialogConfig(image: ImageModel, actionType: ImageActionType): ImageActionModalData { @@ -259,7 +259,7 @@ export class ImagesService { } private updateCashedProjectList(projectList: ProjectModel[]): void { - this.$$cashedProjectList.next(projectList); + this.cashedProjectList$$.next(projectList); } private getDropdownDataList(dropdownList: ImageFilterFormDropdownData): void { @@ -268,7 +268,7 @@ export class ImagesService { } private addFilterDropdownData(data: ImageFilterFormDropdownData): void { - this.$$filterDropdownData.next(data); + this.filterDropdownData$$.next(data); } private getImagePageData(imagePageData: ProjectModel[]): void { @@ -276,7 +276,7 @@ export class ImagesService { this.updateProjectList(imagePageData); this.updateImageList(imageList); this.updateCashedProjectList(imagePageData); - this.$$isProjectListEmpty.next(this.isProjectListEmpty(imagePageData)); + this.isProjectListEmpty$$.next(this.isProjectListEmpty(imagePageData)); } private isProjectListEmpty(imagePageData: ProjectModel[]): boolean { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
