diff --git a/lib/process-services-cloud/src/lib/i18n/en.json b/lib/process-services-cloud/src/lib/i18n/en.json index 238da5542d9..e0c1f9a9b83 100644 --- a/lib/process-services-cloud/src/lib/i18n/en.json +++ b/lib/process-services-cloud/src/lib/i18n/en.json @@ -50,7 +50,8 @@ "MAXIMUM_LENGTH": "Length exceeded, {{characters}} characters max.", "SPACE_VALIDATOR": "Cannot begin or end with a space." } - } + }, + "LOADING": "Loading" }, "ADF_CLOUD_TASK_LIST": { "START_TASK": { @@ -97,7 +98,8 @@ "SUBTITLE": "Create a new task that you want to easily find later", "NONE": "No task lists found" } - } + }, + "LOADING": "Loading" }, "ADF_CLOUD_SERVICE_TASK_LIST": { "PROPERTIES": { diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.html b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.html index 2db08e2d7a1..955b1b33436 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.html +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.html @@ -1,37 +1,40 @@ - - - - - -
- -
-
-
+ @if (showIcons) { +
+ } + +} @else { +
+ +
+} + diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.scss b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.scss index 3efc7991595..ff20dac6b61 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.scss @@ -1,35 +1,18 @@ -.adf-process-filters { - margin-right: calc(-1 * var(--adf-theme-spacing)); - - &__entry { - font-size: var(--theme-body-1-font-size); - color: var(--adf-theme-foreground-text-color-054); - display: flex; - align-items: center; - justify-content: space-between; - flex: 1; - height: 100%; - gap: var(--adf-theme-spacing); - - &:hover { - color: var(--theme-primary-color); - } +@use '@angular/material' as mat; - &-counter { - padding: 0 5px; - border-radius: 15px; +.adf-process-filters { + &__entry-counter { + padding: 0 5px; + border-radius: var(--mat-sys-corner-large, 15px); - &.adf-active { - background-color: var(--theme-accent-color); - color: var(--theme-accent-color-default-contrast); - font-size: smaller; - } - } - } + &.adf-active { + background-color: var(--mat-sys-secondary, var(--theme-accent-color)); - .adf-active { - .adf-process-filters__entry { - color: var(--theme-primary-color); + @include mat.list-overrides( + ( + list-item-trailing-supporting-text-color: var(--mat-sys-on-secondary, var(--theme-accent-color-default-contrast)) + ) + ); } } } diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.spec.ts index 7b0309ca6fc..7a6ad2e62f1 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { SimpleChange } from '@angular/core'; +import { Component, SimpleChange } from '@angular/core'; import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing'; import { first, of, throwError } from 'rxjs'; import { ProcessFilterCloudService } from '../../services/process-filter-cloud.service'; @@ -30,6 +30,11 @@ import { ApolloTestingModule } from 'apollo-angular/testing'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatIconHarness } from '@angular/material/icon/testing'; +import { ActivatedRoute, provideRouter, Router } from '@angular/router'; +import { RouterTestingHarness } from '@angular/router/testing'; + +@Component({ selector: 'adf-cloud-dummy', template: '' }) +class DummyComponent {} const ProcessFilterCloudServiceMock = { getProcessFilters: () => of(mockProcessFilters), @@ -44,8 +49,9 @@ describe('ProcessFiltersCloudComponent', () => { let getProcessFiltersSpy: jasmine.Spy; let getProcessNotificationSubscriptionSpy: jasmine.Spy; let loader: HarnessLoader; + let router: Router; - const configureTestingModule = (searchApiMethod: 'GET' | 'POST') => { + const configureTestingModule = async (searchApiMethod: 'GET' | 'POST') => { TestBed.configureTestingModule({ imports: [ProcessFiltersCloudComponent, ApolloTestingModule], providers: [ @@ -58,7 +64,21 @@ describe('ProcessFiltersCloudComponent', () => { getProcessListCount: () => of(10) } }, - { provide: ProcessFilterCloudService, useValue: ProcessFilterCloudServiceMock } + { provide: ProcessFilterCloudService, useValue: ProcessFilterCloudServiceMock }, + provideRouter([{ path: 'process-list-cloud', component: DummyComponent }]), + { + provide: ActivatedRoute, + useValue: { + queryParamMap: of({ + get: (param: string) => { + if (param === 'filterId') { + return 'fake-process-filter-id'; + } + return null; + } + }) + } + } ] }); fixture = TestBed.createComponent(ProcessFiltersCloudComponent); @@ -67,6 +87,9 @@ describe('ProcessFiltersCloudComponent', () => { component.searchApiMethod = searchApiMethod; processFilterService = TestBed.inject(ProcessFilterCloudService); + TestBed.inject(ActivatedRoute); + router = TestBed.inject(Router); + await RouterTestingHarness.create(); getProcessFiltersSpy = spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(mockProcessFilters)); getProcessNotificationSubscriptionSpy = spyOn(processFilterService, 'getProcessNotificationSubscription').and.returnValue(of([])); }; @@ -76,8 +99,8 @@ describe('ProcessFiltersCloudComponent', () => { }); describe('searchApiMethod set to GET', () => { - beforeEach(() => { - configureTestingModule('GET'); + beforeEach(async () => { + await configureTestingModule('GET'); }); it('should attach specific icon for each filter if hasIcon is true', async () => { @@ -182,20 +205,6 @@ describe('ProcessFiltersCloudComponent', () => { describe('Highlight Selected Filter', () => { const allProcessesFilterKey = mockProcessFilters[0].key; - const runningProcessesFilterKey = mockProcessFilters[1].key; - const completedProcessesFilterKey = mockProcessFilters[2].key; - - const getActiveFilterElement = (filterKey: string): Element => { - const activeFilter = fixture.debugElement.query(By.css(`.adf-active`)); - return activeFilter.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`); - }; - - const clickOnFilter = async (filterKey: string) => { - const button = fixture.debugElement.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`); - button.click(); - fixture.detectChanges(); - await fixture.whenStable(); - }; it('should apply active CSS class on filter click', async () => { component.enableNotifications = true; @@ -205,36 +214,20 @@ describe('ProcessFiltersCloudComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - await clickOnFilter(allProcessesFilterKey); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeDefined(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeNull(); - - await clickOnFilter(runningProcessesFilterKey); - fixture.detectChanges(); - await fixture.whenStable(); + const link = fixture.debugElement.query(By.css(`[data-automation-id="${allProcessesFilterKey}_filter"]`)).nativeElement; + expect(link.getAttribute('href')).toBe('/process-list-cloud?filterId=10'); - expect(getActiveFilterElement(allProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeDefined(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeNull(); - - await clickOnFilter(completedProcessesFilterKey); + link.click(); fixture.detectChanges(); await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeDefined(); + expect(router.url).toBe('/process-list-cloud?filterId=10'); }); }); }); describe('searchApiMethod set to POST', () => { - beforeEach(() => { - configureTestingModule('POST'); + beforeEach(async () => { + await configureTestingModule('POST'); }); it('should attach specific icon for each filter if hasIcon is true', async () => { @@ -336,62 +329,11 @@ describe('ProcessFiltersCloudComponent', () => { expect(component.currentFilter).toEqual(mockProcessFilters[0]); expect(filterClickedSpy).toHaveBeenCalledWith(mockProcessFilters[0]); }); - - describe('Highlight Selected Filter', () => { - const allProcessesFilterKey = mockProcessFilters[0].key; - const runningProcessesFilterKey = mockProcessFilters[1].key; - const completedProcessesFilterKey = mockProcessFilters[2].key; - - const getActiveFilterElement = (filterKey: string): Element => { - const activeFilter = fixture.debugElement.query(By.css(`.adf-active`)); - return activeFilter.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`); - }; - - const clickOnFilter = async (filterKey: string) => { - const button = fixture.debugElement.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`); - button.click(); - fixture.detectChanges(); - await fixture.whenStable(); - }; - - it('should apply active CSS class on filter click', async () => { - component.enableNotifications = true; - component.appName = 'mock-app-name'; - const appNameChange = new SimpleChange(null, 'mock-app-name', true); - component.ngOnChanges({ appName: appNameChange }); - fixture.detectChanges(); - await fixture.whenStable(); - - await clickOnFilter(allProcessesFilterKey); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeDefined(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeNull(); - - await clickOnFilter(runningProcessesFilterKey); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeDefined(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeNull(); - - await clickOnFilter(completedProcessesFilterKey); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeDefined(); - }); - }); }); describe('API agnostic', () => { - beforeEach(() => { - configureTestingModule('GET'); + beforeEach(async () => { + await configureTestingModule('GET'); }); it('should emit an error with a bad response', () => { @@ -549,43 +491,7 @@ describe('ProcessFiltersCloudComponent', () => { }); describe('Highlight Selected Filter', () => { - const allProcessesFilterKey = mockProcessFilters[0].key; - const runningProcessesFilterKey = mockProcessFilters[1].key; - const completedProcessesFilterKey = mockProcessFilters[2].key; - - const getActiveFilterElement = (filterKey: string): Element => { - const activeFilter = fixture.debugElement.query(By.css(`.adf-active`)); - return activeFilter.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`); - }; - - it('Should apply active CSS class when filterParam input changed', async () => { - fixture.detectChanges(); - component.ngOnChanges({ filterParam: new SimpleChange(null, { key: allProcessesFilterKey }, true) }); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeDefined(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeNull(); - - component.ngOnChanges({ filterParam: new SimpleChange(null, { key: runningProcessesFilterKey }, true) }); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeDefined(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeNull(); - - component.ngOnChanges({ filterParam: new SimpleChange(null, { key: completedProcessesFilterKey }, true) }); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(allProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(runningProcessesFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedProcessesFilterKey)).toBeDefined(); - }); - - it('should made sbscription', () => { + it('should make subscription', () => { component.enableNotifications = true; component.appName = 'mock-app-name'; const appNameChange = new SimpleChange(null, 'mock-app-name', true); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.ts index 4eda8cf60fb..fd5b0018588 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/process-filters/process-filters-cloud.component.ts @@ -15,29 +15,30 @@ * limitations under the License. */ -import { Component, DestroyRef, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { Component, DestroyRef, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { Observable } from 'rxjs'; import { ProcessFilterCloudService } from '../../services/process-filter-cloud.service'; import { ProcessFilterCloudModel } from '../../models/process-filter-cloud.model'; import { AppConfigService, IconModule, TranslationService } from '@alfresco/adf-core'; import { FilterParamsModel } from '../../../../task/task-filters/models/filter-cloud.model'; -import { debounceTime, tap } from 'rxjs/operators'; +import { debounceTime, map, tap } from 'rxjs/operators'; import { ProcessListCloudService } from '../../../process-list/services/process-list-cloud.service'; import { ProcessFilterCloudAdapter } from '../../../process-list/models/process-cloud-query-request.model'; -import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; import { TranslatePipe } from '@ngx-translate/core'; -import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; +import { AsyncPipe } from '@angular/common'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatListModule } from '@angular/material/list'; +import { ActivatedRoute, RouterLink } from '@angular/router'; @Component({ selector: 'adf-cloud-process-filters', - imports: [TranslatePipe, IconModule, NgIf, MatProgressSpinnerModule, NgForOf, MatListModule, AsyncPipe], + imports: [TranslatePipe, IconModule, MatProgressSpinnerModule, MatListModule, AsyncPipe, RouterLink], templateUrl: './process-filters-cloud.component.html', - styleUrls: ['./process-filters-cloud.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./process-filters-cloud.component.scss'] }) export class ProcessFiltersCloudComponent implements OnInit, OnChanges { + protected readonly PROCESSES_ROUTE = '/process-list-cloud'; /** (required) The application name */ @Input() appName: string = ''; @@ -87,6 +88,8 @@ export class ProcessFiltersCloudComponent implements OnInit, OnChanges { private readonly translationService = inject(TranslationService); private readonly appConfigService = inject(AppConfigService); private readonly processListCloudService = inject(ProcessListCloudService); + private readonly activatedRoute = inject(ActivatedRoute); + protected readonly currentRouteFilterId = toSignal(this.activatedRoute.queryParamMap.pipe(map((params) => params.get('filterId')))); ngOnInit() { this.enableNotifications = this.appConfigService.get('notifications', true); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.html b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.html index c3b2b43c446..909caffa19c 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.html +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.html @@ -1,35 +1,39 @@ - - - - - -
- -
-
-
+ @if (showIcons) { +
+ } + +} @else { +
+ +
+} diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.scss b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.scss index 4533107f4a3..7a3d157df46 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.scss +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.scss @@ -1,39 +1,18 @@ -.adf-task-filters { - margin-right: calc(-1 * var(--adf-theme-spacing)); - - &__entry { - font-size: var(--theme-body-1-font-size); - color: var(--adf-theme-foreground-text-color-054); - display: flex; - justify-content: space-between; - align-items: center; - flex: 1; - height: 100%; - - &:hover { - color: var(--theme-primary-color); - } - } - - &__entry-label { - display: flex; - flex: 1; - align-items: center; - gap: var(--adf-theme-spacing); - } +@use '@angular/material' as mat; +.adf-task-filters { &__entry-counter { padding: 0 5px; - border-radius: 15px; + border-radius: var(--mat-sys-corner-large, 15px); &.adf-active { - background-color: var(--theme-accent-color); - color: var(--theme-accent-color-default-contrast); - font-size: smaller; - } - } + background-color: var(--mat-sys-secondary, var(--theme-accent-color)); - .adf-active .adf-task-filters__entry-label { - color: var(--theme-primary-color); + @include mat.list-overrides( + ( + list-item-trailing-supporting-text-color: var(--mat-sys-on-secondary, var(--theme-accent-color-default-contrast)) + ) + ); + } } } diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.spec.ts index f5a831f7134..d6162fd0bbd 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.spec.ts @@ -16,7 +16,7 @@ */ import { AppConfigService, NoopAuthModule } from '@alfresco/adf-core'; -import { SimpleChange } from '@angular/core'; +import { Component, SimpleChange } from '@angular/core'; import { ComponentFixture, TestBed, fakeAsync, flush } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { first, of, throwError } from 'rxjs'; @@ -27,12 +27,17 @@ import { TaskFilterCloudService } from '../../services/task-filter-cloud.service import { TaskFiltersCloudComponent } from './task-filters-cloud.component'; import { TaskListCloudService } from '../../../task-list/services/task-list-cloud.service'; import { HarnessLoader } from '@angular/cdk/testing'; -import { MatActionListItemHarness } from '@angular/material/list/testing'; +import { MatNavListItemHarness } from '@angular/material/list/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { TaskFilterCloudAdapter } from '../../../../models/filter-cloud-model'; import { ApolloTestingModule } from 'apollo-angular/testing'; import { TaskFilterCloudModel } from '../../models/filter-cloud.model'; import { MatIconHarness } from '@angular/material/icon/testing'; +import { ActivatedRoute, provideRouter, Router } from '@angular/router'; +import { RouterTestingHarness } from '@angular/router/testing'; + +@Component({ selector: 'adf-cloud-dummy', template: '' }) +class DummyComponent {} describe('TaskFiltersCloudComponent', () => { let loader: HarnessLoader; @@ -45,11 +50,28 @@ describe('TaskFiltersCloudComponent', () => { let getTaskFilterCounterSpy: jasmine.Spy; let getTaskListFiltersSpy: jasmine.Spy; let getTaskListCountSpy: jasmine.Spy; + let router: Router; - const configureTestingModule = (searchApiMethod: 'GET' | 'POST') => { + const configureTestingModule = async (searchApiMethod: 'GET' | 'POST') => { TestBed.configureTestingModule({ imports: [NoopAuthModule, TaskFiltersCloudComponent, ApolloTestingModule], - providers: [{ provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }] + providers: [ + { provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }, + provideRouter([{ path: 'task-list-cloud', component: DummyComponent }]), + { + provide: ActivatedRoute, + useValue: { + queryParamMap: of({ + get: (param: string) => { + if (param === 'filter') { + return 'fake-task-filter-id'; + } + return null; + } + }) + } + } + ] }); taskFilterService = TestBed.inject(TaskFilterCloudService); taskListService = TestBed.inject(TaskListCloudService); @@ -65,6 +87,9 @@ describe('TaskFiltersCloudComponent', () => { loader = TestbedHarnessEnvironment.loader(fixture); component.searchApiMethod = searchApiMethod; + TestBed.inject(ActivatedRoute); + router = TestBed.inject(Router); + await RouterTestingHarness.create(); }; afterEach(() => { @@ -72,8 +97,8 @@ describe('TaskFiltersCloudComponent', () => { }); describe('searchApiMethod set to GET', () => { - beforeEach(() => { - configureTestingModule('GET'); + beforeEach(async () => { + await configureTestingModule('GET'); }); it('should attach specific icon for each filter if hasIcon is true', async () => { @@ -295,7 +320,7 @@ describe('TaskFiltersCloudComponent', () => { const spy = spyOn(component.filterClicked, 'emit'); const filterButton = await loader.getHarness( - MatActionListItemHarness.with({ selector: `[data-automation-id="${fakeGlobalFilter[0].key}_filter"]` }) + MatNavListItemHarness.with({ selector: `[data-automation-id="${fakeGlobalFilter[0].key}_filter"]` }) ); await filterButton.click(); @@ -353,7 +378,7 @@ describe('TaskFiltersCloudComponent', () => { fixture.detectChanges(); const filterButton = await loader.getHarness( - MatActionListItemHarness.with({ selector: `[data-automation-id="${fakeGlobalFilter[0].key}_filter"]` }) + MatNavListItemHarness.with({ selector: `[data-automation-id="${fakeGlobalFilter[0].key}_filter"]` }) ); await filterButton.click(); @@ -577,19 +602,6 @@ describe('TaskFiltersCloudComponent', () => { describe('Highlight Selected Filter', () => { const assignedTasksFilterKey = defaultTaskFiltersMock[1].key; - const queuedTasksFilterKey = defaultTaskFiltersMock[0].key; - const completedTasksFilterKey = defaultTaskFiltersMock[2].key; - - const getActiveFilterElement = (filterKey: string): Element => { - const activeFilter = fixture.debugElement.query(By.css(`.adf-active`)); - return activeFilter.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`); - }; - - const clickOnFilter = async (filterKey: string) => { - fixture.debugElement.nativeElement.querySelector(`[data-automation-id="${filterKey}_filter"]`).click(); - fixture.detectChanges(); - await fixture.whenStable(); - }; it('Should highlight task filter on filter click', async () => { getTaskListFiltersSpy.and.returnValue(of(defaultTaskFiltersMock)); @@ -599,52 +611,12 @@ describe('TaskFiltersCloudComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - await clickOnFilter(assignedTasksFilterKey); - - expect(getActiveFilterElement(assignedTasksFilterKey)).toBeDefined(); - expect(getActiveFilterElement(queuedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedTasksFilterKey)).toBeNull(); - - await clickOnFilter(queuedTasksFilterKey); - - expect(getActiveFilterElement(assignedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(queuedTasksFilterKey)).toBeDefined(); - expect(getActiveFilterElement(completedTasksFilterKey)).toBeNull(); - - await clickOnFilter(completedTasksFilterKey); - - expect(getActiveFilterElement(assignedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(queuedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedTasksFilterKey)).toBeDefined(); - }); - - it('Should highlight task filter when filterParam input changed', async () => { - getTaskListFiltersSpy.and.returnValue(of(defaultTaskFiltersMock)); - fixture.detectChanges(); - - component.ngOnChanges({ filterParam: new SimpleChange(null, { key: assignedTasksFilterKey }, true) }); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(assignedTasksFilterKey)).toBeDefined(); - expect(getActiveFilterElement(queuedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedTasksFilterKey)).toBeNull(); - - component.ngOnChanges({ filterParam: new SimpleChange(null, { key: queuedTasksFilterKey }, true) }); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(getActiveFilterElement(assignedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(queuedTasksFilterKey)).toBeDefined(); - expect(getActiveFilterElement(completedTasksFilterKey)).toBeNull(); - - component.ngOnChanges({ filterParam: new SimpleChange(null, { key: completedTasksFilterKey }, true) }); + const filterLink = fixture.debugElement.query(By.css(`[data-automation-id="${assignedTasksFilterKey}_filter"]`)); + filterLink.nativeElement.click(); fixture.detectChanges(); await fixture.whenStable(); - expect(getActiveFilterElement(assignedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(queuedTasksFilterKey)).toBeNull(); - expect(getActiveFilterElement(completedTasksFilterKey)).toBeDefined(); + expect(router.url).toBe('/task-list-cloud?filter=2'); }); }); }); diff --git a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.ts b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.ts index 0a786102032..917f0bbeb14 100644 --- a/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/task/task-filters/components/task-filters/task-filters-cloud.component.ts @@ -15,31 +15,33 @@ * limitations under the License. */ -import { Component, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { Component, EventEmitter, inject, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { Observable } from 'rxjs'; import { TaskFilterCloudService } from '../../services/task-filter-cloud.service'; import { FilterParamsModel, TaskFilterCloudModel } from '../../models/filter-cloud.model'; import { AppConfigService, IconModule, TranslationService } from '@alfresco/adf-core'; -import { debounceTime, tap } from 'rxjs/operators'; +import { debounceTime, map, tap } from 'rxjs/operators'; import { BaseTaskFiltersCloudComponent } from '../base-task-filters-cloud.component'; import { TaskDetailsCloudModel } from '../../../models/task-details-cloud.model'; import { TaskCloudEngineEvent } from '../../../../models/engine-event-cloud.model'; import { TaskListCloudService } from '../../../task-list/services/task-list-cloud.service'; import { TaskFilterCloudAdapter } from '../../../../models/filter-cloud-model'; -import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { TranslatePipe } from '@ngx-translate/core'; -import { CommonModule } from '@angular/common'; import { MatListModule } from '@angular/material/list'; +import { ActivatedRoute, RouterLink } from '@angular/router'; +import { AsyncPipe } from '@angular/common'; @Component({ selector: 'adf-cloud-task-filters', - imports: [CommonModule, MatProgressSpinnerModule, TranslatePipe, IconModule, MatListModule], + imports: [AsyncPipe, MatProgressSpinnerModule, TranslatePipe, MatListModule, RouterLink, IconModule], templateUrl: './task-filters-cloud.component.html', - styleUrls: ['./task-filters-cloud.component.scss'], - encapsulation: ViewEncapsulation.None + styleUrls: ['./task-filters-cloud.component.scss'] }) export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent implements OnInit, OnChanges { + protected readonly TASKS_ROUTE = '/task-list-cloud'; + /** (optional) From Activiti 8.7.0 forward, use the 'POST' method to get the task count. */ @Input() searchApiMethod: 'GET' | 'POST' = 'GET'; @@ -70,6 +72,8 @@ export class TaskFiltersCloudComponent extends BaseTaskFiltersCloudComponent imp private readonly taskListCloudService = inject(TaskListCloudService); private readonly translationService = inject(TranslationService); private readonly appConfigService = inject(AppConfigService); + private readonly activatedRoute = inject(ActivatedRoute); + readonly currentRouteFilterId = toSignal(this.activatedRoute.queryParamMap.pipe(map((params) => params.get('filter')))); ngOnInit() { this.enableNotifications = this.appConfigService.get('notifications', true);