From e894bb1149e4cbad66b450b050cf2b1ce5e9efde Mon Sep 17 00:00:00 2001 From: Jalinson Diaz Date: Tue, 29 Aug 2023 14:19:00 -0300 Subject: [PATCH] Fix #25926: Template Builder fixing wrong classes deletion (#25928) * dev (add style classes module): refactor to support remove any class * fix (template builder story): console error due to missing import --- .../add-style-classes-dialog.component.html | 2 +- ...add-style-classes-dialog.component.spec.ts | 6 ++-- .../add-style-classes-dialog.component.ts | 4 +-- .../add-style-classes-dialog.store.spec.ts | 30 ++++++++++------ .../store/add-style-classes-dialog.store.ts | 35 +++++++++++++------ .../template-builder/models/models.ts | 1 + .../template-builder.component.stories.ts | 4 ++- 7 files changed, 54 insertions(+), 28 deletions(-) diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.html b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.html index 3307322a48f3..007c68c281e5 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.html +++ b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.html @@ -9,7 +9,7 @@ [size]="446" [tabindex]="1" (onSelect)="onSelect($event)" - (onUnselect)="onUnselect()" + (onUnselect)="onUnselect($event)" (completeMethod)="filterClasses($event)" (onKeyUp)="onKeyUp($event)" dataKey="cssClass" diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.spec.ts b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.spec.ts index 75510ce9c3bb..332d1a36f5fa 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.spec.ts +++ b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.spec.ts @@ -110,16 +110,16 @@ describe('AddStyleClassesDialogComponent', () => { expect(addClassMock).toHaveBeenCalled(); }); - it('should trigger removeLastClass when autocomplete emits onUnselect', () => { + it('should trigger removeClass when autocomplete emits onUnselect', () => { const autoComplete = spectator.query('p-autocomplete'); - const removeLastClassMock = jest.spyOn(store, 'removeLastClass'); + const removeClass = jest.spyOn(store, 'removeClass'); spectator.dispatchFakeEvent(autoComplete, 'onUnselect'); spectator.detectChanges(); - expect(removeLastClassMock).toHaveBeenCalled(); + expect(removeClass).toHaveBeenCalled(); }); it('should trigger saveClass when clicking on update-btn', () => { diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.ts b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.ts index a5bac9cd0aa3..f06ae5b19ad4 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.ts +++ b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/add-style-classes-dialog.component.ts @@ -100,8 +100,8 @@ export class AddStyleClassesDialogComponent implements OnInit, AfterViewInit, On * * @memberof AddStyleClassesDialogComponent */ - onUnselect(): void { - this.store.removeLastClass(); + onUnselect(deletedClass: StyleClassModel): void { + this.store.removeClass(deletedClass); } /** diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.spec.ts b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.spec.ts index 0174784c3347..1b79198adcd0 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.spec.ts +++ b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.spec.ts @@ -7,6 +7,10 @@ import { DotAddStyleClassesDialogStore } from './add-style-classes-dialog.store' import { MOCK_STYLE_CLASSES_FILE } from '../../../utils/mocks'; +jest.mock('uuid', () => ({ + v4: () => 'test-id' +})); + describe('DotAddStyleClassesDialogStore', () => { let service: DotAddStyleClassesDialogStore; let httpTestingController: HttpTestingController; @@ -25,7 +29,10 @@ describe('DotAddStyleClassesDialogStore', () => { it('should have selected style classes on init when passed classes', (done) => { service.init({ selectedClasses: ['class1', 'class2'] }); service.state$.subscribe((state) => { - expect(state.selectedClasses).toEqual([{ cssClass: 'class1' }, { cssClass: 'class2' }]); + expect(state.selectedClasses).toEqual([ + { cssClass: 'class1', id: 'test-id' }, + { cssClass: 'class2', id: 'test-id' } + ]); done(); }); }); @@ -40,7 +47,7 @@ describe('DotAddStyleClassesDialogStore', () => { it('should add a class to selected ', (done) => { service.init({ selectedClasses: [] }); - service.addClass({ cssClass: 'class1' }); + service.addClass({ cssClass: 'class1', id: 'test-id' }); service.state$.subscribe((state) => { expect(state.selectedClasses.length).toBe(1); @@ -48,13 +55,16 @@ describe('DotAddStyleClassesDialogStore', () => { }); }); - it('should remove last class from selected ', (done) => { - service.init({ selectedClasses: ['class1', 'class2'] }); + it('should remove a class from selected that have the same id', (done) => { + service.init({ selectedClasses: ['class1'] }); - service.removeLastClass(); + service.removeClass({ + cssClass: 'class1', + id: 'test-id' + }); service.state$.subscribe((state) => { - expect(state.selectedClasses).toEqual([{ cssClass: 'class1' }]); + expect(state.selectedClasses).toEqual([]); done(); }); }); @@ -66,7 +76,7 @@ describe('DotAddStyleClassesDialogStore', () => { req.flush(MOCK_STYLE_CLASSES_FILE); service.state$.subscribe((state) => { expect(state.styleClasses).toEqual( - MOCK_STYLE_CLASSES_FILE.classes.map((cssClass) => ({ cssClass })) + MOCK_STYLE_CLASSES_FILE.classes.map((cssClass) => ({ cssClass, id: 'test-id' })) ); done(); }); @@ -106,7 +116,7 @@ describe('DotAddStyleClassesDialogStore', () => { service.filterClasses(query); service.state$.subscribe((state) => { - expect(state.selectedClasses).toEqual([{ cssClass: 'align' }]); + expect(state.selectedClasses).toEqual([{ cssClass: 'align', id: 'test-id' }]); done(); }); }); @@ -117,7 +127,7 @@ describe('DotAddStyleClassesDialogStore', () => { service.filterClasses(query); service.state$.subscribe((state) => { - expect(state.selectedClasses).toEqual([{ cssClass: 'align' }]); + expect(state.selectedClasses).toEqual([{ cssClass: 'align', id: 'test-id' }]); done(); }); }); @@ -128,7 +138,7 @@ describe('DotAddStyleClassesDialogStore', () => { service.filterClasses(query); service.state$.subscribe((state) => { - expect(state.filteredClasses).toEqual([{ cssClass: query }]); + expect(state.filteredClasses).toEqual([{ cssClass: query, id: 'test-id' }]); done(); }); }); diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.ts b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.ts index 72e4f98b4d5d..66330b88774f 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.ts +++ b/core-web/libs/template-builder/src/lib/components/template-builder/components/add-style-classes-dialog/store/add-style-classes-dialog.store.ts @@ -1,5 +1,6 @@ import { ComponentStore, tapResponse } from '@ngrx/component-store'; import { Observable } from 'rxjs'; +import { v4 as uuid } from 'uuid'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @@ -7,7 +8,6 @@ import { Injectable } from '@angular/core'; import { switchMap } from 'rxjs/operators'; import { DotAddStyleClassesDialogState, StyleClassModel } from '../../../models/models'; - export const STYLE_CLASSES_FILE_URL = '/application/templates/classes.json'; const COMMA_SPACES_REGEX = /(,|\s)(.*)/; @@ -34,9 +34,7 @@ export class DotAddStyleClassesDialogStore extends ComponentStore { return { ...state, - selectedClasses: selectedClasses.map((cssClass) => ({ - cssClass - })) + selectedClasses: selectedClasses.map((cssClass) => this.buildStyleClass(cssClass)) }; }); @@ -55,9 +53,9 @@ export class DotAddStyleClassesDialogStore extends ComponentStore { this.patchState({ - styleClasses: classes.map((cssClass) => ({ - cssClass - })) + styleClasses: classes.map((cssClass) => + this.buildStyleClass(cssClass) + ) }); }, // Here is the error, if it fails for any reason I just fill the state with an empty array @@ -92,7 +90,7 @@ export class DotAddStyleClassesDialogStore extends ComponentStore { + readonly removeClass = this.updater((state, { id }: StyleClassModel) => { return { ...state, - selectedClasses: state.selectedClasses.slice(0, -1) + selectedClasses: state.selectedClasses.filter((classObj) => classObj.id !== id) }; }); @@ -185,7 +183,7 @@ export class DotAddStyleClassesDialogStore extends ComponentStore cssClass === classObj.cssClass); } + + /** + * @description This method builds a StyleClassModel + * + * @private + * @param {string} cssClass + * @return {*} {StyleClassModel} + * @memberof DotAddStyleClassesDialogStore + */ + private buildStyleClass(cssClass: string): StyleClassModel { + return { + cssClass, + id: uuid() + }; + } } diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/models/models.ts b/core-web/libs/template-builder/src/lib/components/template-builder/models/models.ts index 2e691a9460cd..e21c83827127 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/models/models.ts +++ b/core-web/libs/template-builder/src/lib/components/template-builder/models/models.ts @@ -117,6 +117,7 @@ export interface DotTemplateLayoutProperties { */ export interface StyleClassModel { cssClass: string; + id: string; } /** diff --git a/core-web/libs/template-builder/src/lib/components/template-builder/template-builder.component.stories.ts b/core-web/libs/template-builder/src/lib/components/template-builder/template-builder.component.stories.ts index 9c7639e5953a..63204f077512 100644 --- a/core-web/libs/template-builder/src/lib/components/template-builder/template-builder.component.stories.ts +++ b/core-web/libs/template-builder/src/lib/components/template-builder/template-builder.component.stories.ts @@ -3,6 +3,7 @@ import { of } from 'rxjs'; import { AsyncPipe, NgClass, NgFor, NgIf } from '@angular/common'; import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { ButtonModule } from 'primeng/button'; @@ -54,7 +55,8 @@ export default { ButtonModule, ToolbarModule, DividerModule, - DropdownModule + DropdownModule, + FormsModule ], providers: [ DotTemplateBuilderStore,