AAE-23976 Fix not able to delete custom filter if the name is the same as default filter (#9991)

This commit is contained in:
Kasia Biernat 2024-07-31 10:31:31 +02:00 committed by GitHub
parent fcd9d640d2
commit 6f2255faaa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 84 additions and 86 deletions

View File

@ -8,7 +8,7 @@
<span *ngIf="showTitle"> {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE' | translate}}</span>
<div *ngIf="showFilterActions" class="adf-cloud-edit-process-filter-actions">
<ng-container *ngIf="toggleFilterActions">
<button *ngFor="let filterAction of processFilterActions" mat-icon-button title="{{ filterAction.tooltip | translate}}" [attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType" [disabled]="isDisabledAction(filterAction)" (click)="executeFilterActions($event, filterAction)">
<button *ngFor="let filterAction of processFilterActions" mat-icon-button [title]="filterAction.tooltip | translate" [attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType" [disabled]="isDisabledAction(filterAction)" (click)="executeFilterActions($event, filterAction)">
<adf-icon [value]="filterAction.icon"></adf-icon>
</button>
</ng-container>

View File

@ -6,12 +6,12 @@
<mat-card-content class="adf-process-filter-dialog-card-content">
<form [formGroup]="filterForm">
<mat-form-field class="adf-process-filter-name" [floatLabel]="'auto'">
<input matInput placeholder="{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.FILTER_NAME' | translate }}" formControlName="name" id="adf-filter-name-id">
<input matInput placeholder="{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.FILTER_NAME' | translate }}" [formControl]="filterForm.controls.name" id="adf-filter-name-id">
</mat-form-field>
</form>
</mat-card-content>
<mat-card-actions class='adf-process-filter-dialog-actions'>
<button mat-button (click)="onSaveClick()" id="adf-save-button-id" [disabled]="!isValid()">
<button mat-button (click)="onSaveClick()" id="adf-save-button-id" [disabled]="!filterForm.valid">
{{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.DIALOG.SAVE' | translate}}
</button>
<button mat-button (click)="onCancelClick()" id="adf-cancel-button-id">

View File

@ -107,7 +107,6 @@ describe('ProcessFilterDialogCloudComponent', () => {
});
it('should able close dialog on click of cancel button', () => {
component.data = { data: { name: '' } };
const cancelButton = fixture.debugElement.nativeElement.querySelector('#adf-cancel-button-id');
fixture.detectChanges();
cancelButton.click();

View File

@ -15,53 +15,37 @@
* limitations under the License.
*/
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
@Component({
selector: 'adf-cloud-process-filter-dialog-cloud',
templateUrl: './process-filter-dialog-cloud.component.html',
styleUrls: ['./process-filter-dialog-cloud.component.scss'],
encapsulation: ViewEncapsulation.None
selector: 'adf-cloud-process-filter-dialog-cloud',
templateUrl: './process-filter-dialog-cloud.component.html',
styleUrls: ['./process-filter-dialog-cloud.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
})
export class ProcessFilterDialogCloudComponent implements OnInit {
export class ProcessFilterDialogCloudComponent {
public readonly dialogRef = inject(MatDialogRef<ProcessFilterDialogCloudComponent>);
public readonly data = inject(MAT_DIALOG_DATA);
// eslint-disable-next-line @typescript-eslint/naming-convention
public static ACTION_SAVE = 'SAVE';
defaultIcon = 'inbox';
filterForm: UntypedFormGroup;
constructor(
private fb: UntypedFormBuilder,
public dialogRef: MatDialogRef<ProcessFilterDialogCloudComponent>,
@Inject(MAT_DIALOG_DATA) public data) {
}
ngOnInit() {
this.filterForm = this.fb.group({
name: [this.data.name, Validators.required]
});
}
filterForm = new FormGroup({
name: new FormControl(this.data.name, [Validators.required])
});
onSaveClick() {
this.dialogRef.close({
action: ProcessFilterDialogCloudComponent.ACTION_SAVE,
icon: this.defaultIcon,
name: this.nameController.value
name: this.filterForm.controls.name.value
});
}
onCancelClick() {
this.dialogRef.close();
}
get nameController(): AbstractControl {
return this.filterForm.get('name');
}
isValid(): boolean {
return this.filterForm.valid;
}
}

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { ProcessFilterCloudService } from '../services/process-filter-cloud.service';
import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model';
@ -59,12 +59,13 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
error = new EventEmitter<any>();
filters$: Observable<ProcessFilterCloudModel[]>;
currentFilter: ProcessFilterCloudModel;
currentFilter?: ProcessFilterCloudModel;
filters: ProcessFilterCloudModel[] = [];
private onDestroy$ = new Subject<boolean>();
constructor(private processFilterCloudService: ProcessFilterCloudService, private translationService: TranslationService) {}
private readonly processFilterCloudService = inject(ProcessFilterCloudService);
private readonly translationService = inject(TranslationService);
ngOnInit() {
if (this.appName === '') {
@ -90,17 +91,17 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
getFilters(appName: string): void {
this.filters$ = this.processFilterCloudService.getProcessFilters(appName);
this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe(
(res) => {
this.filters$.pipe(takeUntil(this.onDestroy$)).subscribe({
next: (res) => {
this.resetFilter();
this.filters = res || [];
this.selectFilterAndEmit(this.filterParam);
this.success.emit(res);
},
(err: any) => {
error: (err: any) => {
this.error.emit(err);
}
);
});
}
/**
@ -109,15 +110,20 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges, OnDestro
* @param paramFilter filter model
*/
selectFilter(paramFilter: FilterParamsModel) {
if (paramFilter) {
this.currentFilter = this.filters.find(
if (!paramFilter) {
return;
}
const preferredFilter = this.filters.find((filter) => paramFilter.id === filter.id);
this.currentFilter =
preferredFilter ??
this.filters.find(
(filter, index) =>
paramFilter.id === filter.id ||
(paramFilter.name && this.checkFilterNamesEquality(paramFilter.name, filter.name)) ||
(paramFilter.key && paramFilter.key === filter.key) ||
paramFilter.index === index
);
}
); // fallback to preserve the previous behavior
}
/**

View File

@ -53,7 +53,7 @@ describe('ProcessFilterCloudService', () => {
});
service = TestBed.inject(ProcessFilterCloudService);
const preferenceCloudService = service.preferenceService;
const preferenceCloudService = TestBed.inject(PROCESS_FILTERS_SERVICE_TOKEN);
const identityUserService = TestBed.inject(IdentityUserService);
createPreferenceSpy = spyOn(preferenceCloudService, 'createPreference').and.returnValue(of(fakeProcessCloudFilters));

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Injectable, Inject } from '@angular/core';
import { Injectable, inject } from '@angular/core';
import { Observable, of, BehaviorSubject } from 'rxjs';
import { ProcessFilterCloudModel } from '../models/process-filter-cloud.model';
import { switchMap, map } from 'rxjs/operators';
@ -29,10 +29,10 @@ export class ProcessFilterCloudService {
private filtersSubject: BehaviorSubject<ProcessFilterCloudModel[]>;
filters$: Observable<ProcessFilterCloudModel[]>;
constructor(
@Inject(PROCESS_FILTERS_SERVICE_TOKEN) public preferenceService: PreferenceCloudServiceInterface,
private identityUserService: IdentityUserService
) {
private readonly preferenceService = inject<PreferenceCloudServiceInterface>(PROCESS_FILTERS_SERVICE_TOKEN);
private readonly identityUserService = inject(IdentityUserService);
constructor() {
this.filtersSubject = new BehaviorSubject([]);
this.filters$ = this.filtersSubject.asObservable();
}

View File

@ -10,7 +10,7 @@
<ng-container *ngIf="toggleFilterActions">
<button *ngFor="let filterAction of taskFilterActions"
mat-icon-button
title="{{ filterAction.tooltip | translate}}"
[title]="filterAction.tooltip | translate"
[attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType"
[disabled]="isDisabledAction(filterAction)"
(click)="executeFilterActions(filterAction)">
@ -62,7 +62,7 @@
(keyup)="onDateChanged($any($event).target.value, taskFilterProperty)"
(dateChange)="onDateChanged($event.value, taskFilterProperty)"
[matDatepicker]="dateController"
placeholder="{{taskFilterProperty.label | translate}}"
[placeholder]="taskFilterProperty.label | translate"
[attr.data-automation-id]="'adf-cloud-edit-task-property-' + taskFilterProperty.key">
<mat-datepicker-toggle matSuffix
[for]="dateController"

View File

@ -15,13 +15,13 @@
* limitations under the License.
*/
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { FilterParamsModel, ServiceTaskFilterCloudModel } from '../models/filter-cloud.model';
import { TranslationService } from '@alfresco/adf-core';
import { takeUntil } from 'rxjs/operators';
import { BaseTaskFiltersCloudComponent } from './base-task-filters-cloud.component';
import { ServiceTaskFilterCloudService } from '../services/service-task-filter-cloud.service';
import { TranslationService } from '@alfresco/adf-core';
@Component({
selector: 'adf-cloud-service-task-filters',
@ -30,7 +30,6 @@ import { ServiceTaskFilterCloudService } from '../services/service-task-filter-c
encapsulation: ViewEncapsulation.None
})
export class ServiceTaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent implements OnInit, OnChanges {
/** Emitted when a filter is being selected based on the filterParam input. */
@Output()
filterSelected = new EventEmitter<ServiceTaskFilterCloudModel>();
@ -43,10 +42,8 @@ export class ServiceTaskFiltersCloudComponent extends BaseTaskFiltersCloudCompon
filters: ServiceTaskFilterCloudModel[] = [];
currentFilter: ServiceTaskFilterCloudModel;
constructor(private serviceTaskFilterCloudService: ServiceTaskFilterCloudService,
private translationService: TranslationService) {
super();
}
private readonly serviceTaskFilterCloudService = inject(ServiceTaskFilterCloudService);
private readonly translationService = inject(TranslationService);
ngOnInit() {
this.getFilters(this.appName);
@ -89,15 +86,21 @@ export class ServiceTaskFiltersCloudComponent extends BaseTaskFiltersCloudCompon
* @param paramFilter filter model
*/
selectFilter(paramFilter: FilterParamsModel) {
if (paramFilter) {
this.currentFilter = this.filters.find((filter, index) =>
paramFilter.index === index ||
paramFilter.key === filter.key ||
paramFilter.id === filter.id ||
(paramFilter.name &&
(paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
));
if (!paramFilter) {
return;
}
const preferredFilter = this.filters.find((filter) => filter.id === paramFilter.id);
this.currentFilter =
preferredFilter ??
this.filters.find(
(filter, index) =>
paramFilter.index === index ||
paramFilter.key === filter.key ||
paramFilter.id === filter.id ||
(paramFilter.name && paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
); // fallback to preserve the previous behavior
}
public selectFilterAndEmit(newParamFilter: FilterParamsModel) {

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, OnInit, ViewEncapsulation, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { TaskFilterCloudService } from '../services/task-filter-cloud.service';
import { TaskFilterCloudModel, FilterParamsModel } from '../models/filter-cloud.model';
@ -32,7 +32,6 @@ import { TaskCloudEngineEvent } from '../../../models/engine-event-cloud.model';
encapsulation: ViewEncapsulation.None
})
export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent implements OnInit, OnChanges {
/** Emitted when a filter is being selected based on the filterParam input. */
@Output()
filterSelected = new EventEmitter<TaskFilterCloudModel>();
@ -50,11 +49,9 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
currentFilter: TaskFilterCloudModel;
enableNotifications: boolean;
constructor(private taskFilterCloudService: TaskFilterCloudService,
private translationService: TranslationService,
private appConfigService: AppConfigService) {
super();
}
private readonly taskFilterCloudService = inject(TaskFilterCloudService);
private readonly translationService = inject(TranslationService);
private readonly appConfigService = inject(AppConfigService);
ngOnInit() {
this.enableNotifications = this.appConfigService.get('notifications', true);
@ -106,7 +103,8 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
initFilterCounterNotifications() {
if (this.appName && this.enableNotifications) {
this.taskFilterCloudService.getTaskNotificationSubscription(this.appName)
this.taskFilterCloudService
.getTaskNotificationSubscription(this.appName)
.pipe(debounceTime(1000))
.subscribe((result: TaskCloudEngineEvent[]) => {
result.map((taskEvent: TaskCloudEngineEvent) => {
@ -128,20 +126,28 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp
}
isFilterPresent(filter: TaskFilterCloudModel, filterNotification: TaskDetailsCloudModel): boolean {
return filter.status === filterNotification.status
&& (filter.assignee === filterNotification.assignee || filterNotification.assignee === undefined);
return (
filter.status === filterNotification.status &&
(filter.assignee === filterNotification.assignee || filterNotification.assignee === undefined)
);
}
public selectFilter(paramFilter: FilterParamsModel) {
if (paramFilter) {
this.currentFilter = this.filters.find((filter, index) =>
paramFilter.index === index ||
paramFilter.key === filter.key ||
paramFilter.id === filter.id ||
(paramFilter.name &&
(paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
));
if (!paramFilter) {
return;
}
const preferredFilter = this.filters.find((filter) => filter.id === paramFilter.id);
this.currentFilter =
preferredFilter ??
this.filters.find(
(filter, index) =>
paramFilter.index === index ||
paramFilter.key === filter.key ||
paramFilter.id === filter.id ||
(paramFilter.name && paramFilter.name.toLocaleLowerCase() === this.translationService.instant(filter.name).toLocaleLowerCase())
); // fallback to preserve the previous behavior
}
public selectFilterAndEmit(newParamFilter: FilterParamsModel) {