diff --git a/lib/content-services/src/lib/assets/images/custom_filter.svg b/lib/content-services/src/lib/assets/images/custom_filter.svg new file mode 100644 index 0000000000..ee6c492335 --- /dev/null +++ b/lib/content-services/src/lib/assets/images/custom_filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/content-services/src/lib/assets/images/custom_filter_filled.svg b/lib/content-services/src/lib/assets/images/custom_filter_filled.svg new file mode 100644 index 0000000000..40ce03cec9 --- /dev/null +++ b/lib/content-services/src/lib/assets/images/custom_filter_filled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.html b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.html index 45f744d5c0..f6a65479d4 100644 --- a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.html +++ b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.html @@ -12,12 +12,9 @@ [title]="getTooltipTranslation(col?.title)" > diff --git a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts index 51ec29cf57..e7c5c16dfd 100644 --- a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts @@ -19,16 +19,17 @@ import { Subject } from 'rxjs'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SearchService } from '../../services/search.service'; import { SearchHeaderQueryBuilderService } from '../../services/search-header-query-builder.service'; -import { By } from '@angular/platform-browser'; +import { By, DomSanitizer } from '@angular/platform-browser'; import { SearchFilterContainerComponent } from './search-filter-container.component'; import { SearchCategory } from '../../models/search-category.interface'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatMenuHarness } from '@angular/material/menu/testing'; import { MatButtonHarness } from '@angular/material/button/testing'; -import { MatBadgeHarness } from '@angular/material/badge/testing'; import { MatInputHarness } from '@angular/material/input/testing'; import { provideRouter } from '@angular/router'; +import { IconComponent, UnitTestingUtils } from '@alfresco/adf-core'; +import { MatIconRegistry } from '@angular/material/icon'; const mockCategory: SearchCategory = { id: 'queryName', @@ -51,6 +52,9 @@ describe('SearchFilterContainerComponent', () => { let fixture: ComponentFixture; let component: SearchFilterContainerComponent; let queryBuilder: SearchHeaderQueryBuilderService; + let unitTestingUtils: UnitTestingUtils; + let matIconRegistry: MatIconRegistry; + let sanitizer: DomSanitizer; const searchMock: any = { dataLoaded: new Subject() @@ -68,6 +72,9 @@ describe('SearchFilterContainerComponent', () => { spyOn(queryBuilder, 'getCategoryForColumn').and.returnValue(mockCategory); fixture.detectChanges(); loader = TestbedHarnessEnvironment.loader(fixture); + unitTestingUtils = new UnitTestingUtils(fixture.debugElement, loader); + matIconRegistry = TestBed.inject(MatIconRegistry); + sanitizer = TestBed.inject(DomSanitizer); }); afterEach(() => { @@ -79,7 +86,7 @@ describe('SearchFilterContainerComponent', () => { await fixture.whenStable(); fixture.detectChanges(); expect(queryBuilder.isFilterServiceActive()).toBe(true); - const element = fixture.nativeElement.querySelector('.adf-filter'); + const element = unitTestingUtils.getByCSS('.adf-filter'); expect(element).not.toBeNull(); expect(element).not.toBeUndefined(); }); @@ -142,26 +149,30 @@ describe('SearchFilterContainerComponent', () => { expect(eventRaised).toBe(true); }); - it('should hide the red dot after the filter is cleared', async () => { - const badge = await loader.getHarness(MatBadgeHarness); - expect(await badge.isHidden()).toBe(true); - - const menu = await loader.getHarness(MatMenuHarness); - await menu.open(); - - component.widgetContainer.componentRef.instance.value = 'searchText'; - const widgetContainer = fixture.debugElement.query(By.css('adf-search-widget-container')); - widgetContainer.triggerEventHandler('keypress', { key: 'Enter' }); + it('should display correct icon based on active state of the filter', () => { + component.isActive = () => false; fixture.detectChanges(); - await fixture.whenStable(); - expect(await badge.isHidden()).toBe(false); - await menu.open(); + const inactiveIcon: IconComponent = unitTestingUtils.getByCSS('.adf-filter-icon').componentInstance; + expect(inactiveIcon.value).toBe('adf:custom_filter'); - const clearButton = await menu.getHarness(MatButtonHarness.with({ selector: '#clear-filter-button' })); - await clearButton.click(); + component.isActive = () => true; + fixture.detectChanges(); - expect(await badge.isHidden()).toBe(true); + const activeIcon: IconComponent = unitTestingUtils.getByCSS('.adf-filter-icon').componentInstance; + expect(activeIcon.value).toBe('adf:custom_filter_filled'); + }); + + it('should register custom icons when component is initialized', () => { + spyOn(sanitizer, 'bypassSecurityTrustResourceUrl').and.callThrough(); + spyOn(matIconRegistry, 'addSvgIconInNamespace').and.callThrough(); + + component.ngOnInit(); + + expect(sanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalledWith('./assets/images/custom_filter.svg'); + expect(sanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalledWith('./assets/images/custom_filter_filled.svg'); + expect(matIconRegistry.addSvgIconInNamespace).toHaveBeenCalledWith('adf', 'custom_filter', jasmine.any(Object)); + expect(matIconRegistry.addSvgIconInNamespace).toHaveBeenCalledWith('adf', 'custom_filter_filled', jasmine.any(Object)); }); describe('Accessibility', () => { diff --git a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts index d9349d98b6..2e2235c9f6 100644 --- a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts +++ b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.ts @@ -25,22 +25,14 @@ import { MatMenuModule, MatMenuTrigger } from '@angular/material/menu'; import { FilterSearch } from '../../models/filter-search.interface'; import { CommonModule } from '@angular/common'; import { MatButtonModule } from '@angular/material/button'; -import { MatBadgeModule } from '@angular/material/badge'; import { TranslatePipe } from '@ngx-translate/core'; import { MatDialogModule } from '@angular/material/dialog'; +import { DomSanitizer } from '@angular/platform-browser'; +import { MatIconRegistry } from '@angular/material/icon'; @Component({ selector: 'adf-search-filter-container', - imports: [ - CommonModule, - MatButtonModule, - MatMenuModule, - IconComponent, - MatBadgeModule, - SearchWidgetContainerComponent, - TranslatePipe, - MatDialogModule - ], + imports: [CommonModule, MatButtonModule, MatMenuModule, IconComponent, SearchWidgetContainerComponent, TranslatePipe, MatDialogModule], templateUrl: './search-filter-container.component.html', styleUrls: ['./search-filter-container.component.scss'], encapsulation: ViewEncapsulation.None @@ -69,12 +61,15 @@ export class SearchFilterContainerComponent implements OnInit { initialValue: any; constructor( - private searchFilterQueryBuilder: SearchHeaderQueryBuilderService, - private translationService: TranslationService, - private focusTrapFactory: ConfigurableFocusTrapFactory + private readonly searchFilterQueryBuilder: SearchHeaderQueryBuilderService, + private readonly translationService: TranslationService, + private readonly focusTrapFactory: ConfigurableFocusTrapFactory, + private readonly matIconRegistry: MatIconRegistry, + private readonly sanitizer: DomSanitizer ) {} ngOnInit() { + this.registerFilterIcon(); this.category = this.searchFilterQueryBuilder.getCategoryForColumn(this.col.key); this.initialValue = this.value?.[this.category?.id]; } @@ -129,4 +124,11 @@ export class SearchFilterContainerComponent implements OnInit { this.focusTrap.destroy(); this.focusTrap = null; } + + private registerFilterIcon(): void { + const filterIcon = this.sanitizer.bypassSecurityTrustResourceUrl('./assets/images/custom_filter.svg'); + const filterIconFilled = this.sanitizer.bypassSecurityTrustResourceUrl('./assets/images/custom_filter_filled.svg'); + this.matIconRegistry.addSvgIconInNamespace('adf', 'custom_filter', filterIcon); + this.matIconRegistry.addSvgIconInNamespace('adf', 'custom_filter_filled', filterIconFilled); + } } diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.scss b/lib/core/src/lib/datatable/components/datatable/datatable.component.scss index 2aa90bbb0d..585a16d565 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.scss +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.scss @@ -243,12 +243,6 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default; &--fileSize { min-width: $data-table-cell-min-width-file-size; } - - button { - #{ms.$mat-icon} { - margin-top: -10px; - } - } } .adf-datatable-cell-header.adf-expand-cell-1,