diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json index b35c75f2f4..28d7504421 100644 --- a/demo-shell/src/app.config.json +++ b/demo-shell/src/app.config.json @@ -1205,7 +1205,8 @@ "status", "sort", "order", - "processName" + "processName", + "name" ], "sortProperties": [ "id", diff --git a/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts index c730897de4..be461e1cfb 100644 --- a/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts +++ b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts @@ -116,7 +116,10 @@ export class ProcessesCloudDemoComponent implements OnInit, OnDestroy { } onFilterChange(filter: ProcessFilterCloudModel) { - const queryParams = this.cloudProcessFiltersService.writeQueryParams(filter, this.appName, this.filterId); + const queryParams = { + ...this.cloudProcessFiltersService.writeQueryParams(filter, this.appName, filter.id), + filterId: filter.id + }; this.router.navigate([`/cloud/${this.appName}/processes/`], {queryParams}); } diff --git a/e2e/process-services-cloud/task-list/edit-process-filters-component.e2e.ts b/e2e/process-services-cloud/task-list/edit-process-filters-component.e2e.ts index 5e78ff023b..095c5373d3 100644 --- a/e2e/process-services-cloud/task-list/edit-process-filters-component.e2e.ts +++ b/e2e/process-services-cloud/task-list/edit-process-filters-component.e2e.ts @@ -88,11 +88,14 @@ describe('Edit process filters cloud', () => { await editProcessFilter.openFilter(); await editProcessFilter.setSortFilterDropDown('Start Date'); await expect(await editProcessFilter.getSortFilterDropDownValue()).toEqual('Start Date'); + await expect(await editProcessFilter.getOrderFilterDropDownValue()).toEqual('Descending'); + await expect(await editProcessFilter.getStateFilterDropDownValue()).toEqual('All'); await editProcessFilter.checkSaveButtonIsDisplayed(); await editProcessFilter.checkSaveAsButtonIsDisplayed(); await editProcessFilter.checkDeleteButtonIsDisplayed(); + await expect(await editProcessFilter.isCustomFilterNameDisplayed('New')).toEqual(true); await expect(await editProcessFilter.checkSaveButtonIsEnabled()).toEqual(true); await expect(await editProcessFilter.checkSaveAsButtonIsEnabled()).toEqual(true); await expect(await editProcessFilter.checkDeleteButtonIsEnabled()).toEqual(true); @@ -143,7 +146,6 @@ describe('Edit process filters cloud', () => { it('[C291810] Process filter should not be created when process filter dialog is closed', async () => { await editProcessFilter.setSortFilterDropDown('Id'); - await processFilter.clickAllProcessesFilter(); await editProcessFilter.clickSaveAsButton(); await editProcessFilter.editProcessFilterDialog().setFilterName('Cancel'); await expect(await editProcessFilter.editProcessFilterDialog().getFilterName()).toEqual('Cancel'); @@ -164,6 +166,7 @@ describe('Edit process filters cloud', () => { await editProcessFilter.clickSaveAsButton(); const dialog = editProcessFilter.editProcessFilterDialog(); + await dialog.clearFilterName(); await expect(await dialog.getFilterName()).toEqual(''); await expect(await dialog.checkSaveButtonIsEnabled()).toEqual(false); @@ -176,6 +179,7 @@ describe('Edit process filters cloud', () => { await editProcessFilter.clickSaveAsButton(); const dialog = editProcessFilter.editProcessFilterDialog(); + await dialog.clearFilterName(); await expect(await dialog.checkCancelButtonIsEnabled()).toEqual(true); await expect(await dialog.checkSaveButtonIsEnabled()).toEqual(false); diff --git a/e2e/protractor.excludes.json b/e2e/protractor.excludes.json index 298d0c0d46..bbf805fd31 100644 --- a/e2e/protractor.excludes.json +++ b/e2e/protractor.excludes.json @@ -1,6 +1,4 @@ { "C269081": "https://alfresco.atlassian.net/browse/ADF-5385", - "C272819": "https://alfresco.atlassian.net/browse/ADF-5385", - "C291811": "https://alfresco.atlassian.net/browse/ADF-5405", - "C291809": "https://alfresco.atlassian.net/browse/ADF-5405" + "C272819": "https://alfresco.atlassian.net/browse/ADF-5385" } diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts index 1da0257a69..e5fa48d65e 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.spec.ts @@ -238,9 +238,82 @@ describe('EditProcessFilterCloudComponent', () => { const deleteButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-delete"]'); expect(deleteButton.disabled).toEqual(false); }); + + it('should enable save button if the filter is changed for custom process filters', (done) => { + component.toggleFilterActions = true; + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + expansionPanel.click(); + fixture.detectChanges(); + + component.editProcessFilterForm.valueChanges + .pipe(debounceTime(500)) + .subscribe(() => { + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); + fixture.detectChanges(); + expect(saveButton.disabled).toBe(false); + done(); + }); + + const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger'); + stateElement.click(); + fixture.detectChanges(); + + const stateOptions = fixture.debugElement.queryAll(By.css('.mat-option-text')); + stateOptions[2].nativeElement.click(); + fixture.detectChanges(); + }); + + it('should disable save button if the filter is not changed for custom filter', async () => { + component.toggleFilterActions = true; + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + expansionPanel.click(); + + fixture.detectChanges(); + await fixture.whenStable(); + + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); + expect(saveButton.disabled).toBe(true); + }); }); describe('SaveAs Button', () => { + + it('should disable saveAs button if the process filter is not changed for default filter', async () => { + getProcessFilterByIdSpy.and.returnValue(of({ + id: 'filter-id', + name: 'ADF_CLOUD_PROCESS_FILTERS.RUNNING_PROCESSES', + sort: 'my-custom-sort', + processDefinitionId: 'process-definition-id', + priority: '12' + })); + + const processFilterIdChange = new SimpleChange(null, 'filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); + fixture.detectChanges(); + + component.toggleFilterActions = true; + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + expansionPanel.click(); + + fixture.detectChanges(); + await fixture.whenStable(); + + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + expect(saveButton.disabled).toEqual(true); + }); + + it('should disable saveAs button if the process filter is not changed for custom filter', async () => { + component.toggleFilterActions = true; + const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); + expansionPanel.click(); + + fixture.detectChanges(); + await fixture.whenStable(); + + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + expect(saveButton.disabled).toEqual(true); + }); + it('should enable saveAs button if the filter values are changed for default filter', (done) => { getProcessFilterByIdSpy.and.returnValue(of({ id: 'filter-id', @@ -710,36 +783,33 @@ describe('EditProcessFilterCloudComponent', () => { fixture.destroy(); }); - it('should emit save event and save the filter on click save button', async () => { + it('should emit save event and save the filter on click save button', (done) => { component.toggleFilterActions = true; const saveFilterSpy = spyOn(service, 'updateFilter').and.returnValue(of([fakeFilter])); const saveSpy: jasmine.Spy = spyOn(component.action, 'emit'); - - fixture.detectChanges(); - await fixture.whenStable(); - const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - fixture.detectChanges(); - await fixture.whenStable(); + + component.editProcessFilterForm.valueChanges + .pipe(debounceTime(500)) + .subscribe(() => { + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); + fixture.detectChanges(); + expect(saveButton.disabled).toBe(false); + saveButton.click(); + expect(saveFilterSpy).toHaveBeenCalled(); + expect(saveSpy).toHaveBeenCalled(); + done(); + }); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger'); stateElement.click(); - fixture.detectChanges(); - await fixture.whenStable(); - const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-save"]'); const stateOptions = fixture.debugElement.queryAll(By.css('.mat-option-text')); stateOptions[2].nativeElement.click(); - saveButton.click(); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(saveFilterSpy).toHaveBeenCalled(); - expect(saveSpy).toHaveBeenCalled(); }); it('should emit delete event and delete the filter on click of delete button', async () => { @@ -772,37 +842,34 @@ describe('EditProcessFilterCloudComponent', () => { expect(deleteSpy).toHaveBeenCalled(); }); - it('should emit saveAs event and add filter on click saveAs button', async () => { + it('should emit saveAs event and add filter on click saveAs button', (done) => { component.toggleFilterActions = true; const saveAsFilterSpy = spyOn(service, 'addFilter').and.callThrough(); const saveAsSpy = spyOn(component.action, 'emit'); - - fixture.detectChanges(); - await fixture.whenStable(); - const expansionPanel = fixture.debugElement.nativeElement.querySelector('mat-expansion-panel-header'); expansionPanel.click(); - fixture.detectChanges(); - await fixture.whenStable(); + + component.editProcessFilterForm.valueChanges + .pipe(debounceTime(500)) + .subscribe(() => { + const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); + fixture.detectChanges(); + expect(saveButton.disabled).toBe(false); + saveButton.click(); + expect(saveAsFilterSpy).toHaveBeenCalled(); + expect(saveAsSpy).toHaveBeenCalled(); + expect(dialog.open).toHaveBeenCalled(); + done(); + }); const stateElement = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-cloud-edit-process-property-status"] .mat-select-trigger'); stateElement.click(); - fixture.detectChanges(); - await fixture.whenStable(); - const saveButton = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-filter-action-saveAs"]'); const stateOptions = fixture.debugElement.queryAll(By.css('.mat-option-text')); stateOptions[2].nativeElement.click(); - saveButton.click(); - fixture.detectChanges(); - await fixture.whenStable(); - - expect(saveAsFilterSpy).toHaveBeenCalled(); - expect(saveAsSpy).toHaveBeenCalled(); - expect(dialog.open).toHaveBeenCalled(); }); it('should display default filter actions', async () => { @@ -867,8 +934,8 @@ describe('EditProcessFilterCloudComponent', () => { it('should set the correct lastModifiedTo date', (done) => { component.appName = 'fake'; component.filterProperties = ['appName', 'processInstanceId', 'priority', 'lastModified']; - const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); - component.ngOnChanges({ 'id': taskFilterIdChange }); + const processFilterIdChange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); fixture.detectChanges(); const date = moment(); @@ -890,8 +957,8 @@ describe('EditProcessFilterCloudComponent', () => { it('should set date range filter type when range is selected', (done) => { component.appName = 'fake'; component.filterProperties = ['appName', 'processInstanceId', 'priority', 'completedDateRange']; - const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); - component.ngOnChanges({ 'id': taskFilterIdChange }); + const processFilterIdChange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); fixture.detectChanges(); component.filterChange.subscribe(() => { @@ -924,8 +991,8 @@ describe('EditProcessFilterCloudComponent', () => { it('should set the correct started date range when date range option is changed', (done) => { component.appName = 'fake'; component.filterProperties = ['appName', 'processInstanceId', 'priority', 'completedDateRange']; - const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); - component.ngOnChanges({ 'id': taskFilterIdChange }); + const processFilterIdChange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); fixture.detectChanges(); component.filterChange.subscribe(() => { @@ -945,8 +1012,8 @@ describe('EditProcessFilterCloudComponent', () => { it('should update form on date range value is updated', (done) => { component.appName = 'fake'; component.filterProperties = ['appName', 'processInstanceId', 'priority', 'completedDateRange']; - const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); - component.ngOnChanges({ 'id': taskFilterIdChange }); + const processFilterIdChange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); fixture.detectChanges(); const dateFilter = { @@ -1035,8 +1102,8 @@ describe('EditProcessFilterCloudComponent', () => { it('should build initiator as object array', () => { component.appName = 'fake'; component.filterProperties = ['appName', 'initiator']; - const taskFilterIdChange = new SimpleChange(undefined, 'mock-task-filter-id', true); - component.ngOnChanges({ 'id': taskFilterIdChange }); + const processFilterIdChange = new SimpleChange(undefined, 'mock-process-filter-id', true); + component.ngOnChanges({ 'id': processFilterIdChange }); fixture.detectChanges(); expect(component.initiatorOptions).toEqual([ { username: 'user1' }, { username: 'user2'} ]); diff --git a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts index fa6051f413..734e7a2bb5 100644 --- a/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts +++ b/lib/process-services-cloud/src/lib/process/process-filters/components/edit-process-filter-cloud.component.ts @@ -97,6 +97,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes action = new EventEmitter(); private _filter: ProcessFilterCloudModel; + protected filterHasBeenChanged = false; get processFilter() { return this._filter; @@ -220,6 +221,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes .getFilterById(this.appName, this.id) .pipe(finalize(() => this.isLoading = false)) .subscribe(response => { + this.filterHasBeenChanged = false; this.processFilter = new ProcessFilterCloudModel( Object.assign({}, response || {}, this.processFilter || {}) ); @@ -246,6 +248,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes const newValue = new ProcessFilterCloudModel(Object.assign({}, this.processFilter, formValues)); const changed = !this.compareFilters(newValue, this.processFilter); + this.filterHasBeenChanged = changed; if (changed) { this._filter = newValue; @@ -430,6 +433,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes .updateFilter(this.processFilter) .subscribe(() => { saveAction.filter = this.processFilter; + this.filterHasBeenChanged = false; this.action.emit(saveAction); }); } @@ -476,6 +480,7 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes .addFilter(resultFilter) .subscribe(() => { saveAsAction.filter = resultFilter; + this.filterHasBeenChanged = false; this.action.emit(saveAsAction); }); } @@ -516,7 +521,13 @@ export class EditProcessFilterCloudComponent implements OnInit, OnChanges, OnDes return ( this.processFilterCloudService.isDefaultFilter(this.processFilter.name) && this.actionDisabledForDefault.includes(action.actionType) - ); + ) ? true : this.hasFilterChanged(action); + } + + hasFilterChanged(action: ProcessFilterAction): boolean { + return action.actionType === EditProcessFilterCloudComponent.ACTION_SAVE || + action.actionType === EditProcessFilterCloudComponent.ACTION_SAVE_AS ? + !this.filterHasBeenChanged : false; } private setLastModifiedToFilter(formValues: ProcessFilterCloudModel) { diff --git a/lib/testing/src/lib/protractor/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts b/lib/testing/src/lib/protractor/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts index e8da62a341..dccf7a3936 100644 --- a/lib/testing/src/lib/protractor/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts +++ b/lib/testing/src/lib/protractor/process-services-cloud/pages/dialog/edit-process-filter-dialog.page.ts @@ -36,7 +36,7 @@ export class EditProcessFilterDialogPage { async checkSaveButtonIsEnabled(): Promise { await BrowserVisibility.waitUntilElementIsVisible(this.componentElement.$(this.saveButtonLocator)); - return this.componentElement.element(this.saveButtonLocator).isEnabled(); + return this.componentElement.$(this.saveButtonLocator).isEnabled(); } async clickOnCancelButton(): Promise { diff --git a/lib/testing/src/lib/protractor/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts b/lib/testing/src/lib/protractor/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts index 7a8815bc2f..2ff9e6780f 100644 --- a/lib/testing/src/lib/protractor/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts +++ b/lib/testing/src/lib/protractor/process-services-cloud/pages/edit-process-filter-cloud-component.page.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { browser, $$, $ } from 'protractor'; +import { browser, $$, $, by, element } from 'protractor'; import { EditProcessFilterDialogPage } from './dialog/edit-process-filter-dialog.page'; import { BrowserVisibility } from '../../core/utils/browser-visibility'; import { BrowserActions } from '../../core/utils/browser-actions'; @@ -268,4 +268,9 @@ export class EditProcessFilterCloudComponentPage { if (props.suspendedDateRange) { await this.setSuspendedDateRangeDropDown(props.suspendedDateRange); } await this.closeFilter(); } + + async isCustomFilterNameDisplayed(name: string): Promise { + const title = element(by.cssContainingText(`[id='adf-edit-process-filter-title-id']`, name)); + return BrowserVisibility.waitUntilElementIsVisible(title); + } }