remove filter string pipe, performance improvements (#10231)

This commit is contained in:
Denys Vuika 2024-09-30 10:44:15 -04:00 committed by GitHub
parent dd2bbd0a4b
commit 0139273914
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 64 additions and 111 deletions

View File

@ -37,21 +37,17 @@
</div>
<div class="adf-columns-selector-list-container">
<ng-container *ngFor="let column of columnItems">
<div
*ngIf="(column.title | translate | filterString:searchQuery) as translatedTitle"
class="adf-columns-selector-list-item">
<mat-checkbox
color="primary"
class="adf-columns-selector-column-checkbox"
[attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title"
[checked]="!column.isHidden"
[disabled]="isCheckboxDisabled(column)"
(change)="changeColumnVisibility(column)">
<div class="adf-columns-selector-list-content">{{translatedTitle}}</div>
</mat-checkbox>
</div>
</ng-container>
<div *ngFor="let column of columnItems" class="adf-columns-selector-list-item">
<mat-checkbox
color="primary"
class="adf-columns-selector-column-checkbox"
[attr.data-automation-id]="'adf-columns-selector-column-checkbox-' + column.title"
[checked]="!column.isHidden"
[disabled]="isCheckboxDisabled(column)"
(change)="changeColumnVisibility(column)">
<div class="adf-columns-selector-list-content">{{column.title | translate}}</div>
</mat-checkbox>
</div>
</div>
<mat-divider class="adf-columns-selector-divider"></mat-divider>

View File

@ -24,7 +24,7 @@ import { By } from '@angular/platform-browser';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { HarnessLoader } from '@angular/cdk/testing';
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
import { NoopTranslateModule } from '@alfresco/adf-core';
import { NoopTranslateModule } from '../../../testing/noop-translate.module';
describe('ColumnsSelectorComponent', () => {
let fixture: ComponentFixture<ColumnsSelectorComponent>;
@ -91,6 +91,8 @@ describe('ColumnsSelectorComponent', () => {
fixture.detectChanges();
});
afterEach(() => fixture.destroy());
it('should clear search after closing menu', fakeAsync(() => {
menuOpenedTrigger.next();
fixture.detectChanges();

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { Component, EventEmitter, inject, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core';
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
import { MatMenuTrigger } from '@angular/material/menu';
import { Subject } from 'rxjs';
@ -27,25 +27,19 @@ import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatDividerModule } from '@angular/material/divider';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { FilterStringPipe } from '../../../pipes';
import { TranslationService } from '../../../translation';
@Component({
selector: 'adf-datatable-column-selector',
standalone: true,
imports: [
CommonModule,
TranslateModule,
MatButtonModule,
MatIconModule,
MatDividerModule,
ReactiveFormsModule,
MatCheckboxModule,
FilterStringPipe
],
imports: [CommonModule, TranslateModule, MatButtonModule, MatIconModule, MatDividerModule, ReactiveFormsModule, MatCheckboxModule],
templateUrl: './columns-selector.component.html',
styleUrls: ['./columns-selector.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class ColumnsSelectorComponent implements OnInit, OnDestroy {
private translationService = inject(TranslationService);
@Input()
columns: DataColumn[] = [];
@ -68,8 +62,7 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.mainMenuTrigger.menuOpened.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
const columns = this.columns.map((column) => ({ ...column }));
this.columnItems = this.columnsSorting ? this.sortColumns(columns) : columns;
this.updateColumnItems();
});
this.mainMenuTrigger.menuClosed.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
@ -78,9 +71,17 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
this.searchInputControl.valueChanges.pipe(debounceTime(300), takeUntil(this.onDestroy$)).subscribe((searchQuery) => {
this.searchQuery = searchQuery;
this.updateColumnItems();
});
}
private updateColumnItems(): void {
let columns = this.columns.map((column) => ({ ...column }));
columns = this.filterColumnItems(columns, this.searchQuery);
columns = this.sortColumns(columns);
this.columnItems = columns;
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
@ -90,6 +91,34 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
this.mainMenuTrigger.closeMenu();
}
private filterString(value: string = '', filterBy: string = ''): string {
const testResult = filterBy ? value.toLowerCase().indexOf(filterBy.toLowerCase()) > -1 : true;
return testResult ? value : '';
}
private filterColumnItems(columns: DataColumn[], query: string): DataColumn[] {
const result = [];
for (const column of columns) {
if (!column.title) {
continue;
}
if (!query) {
result.push(column);
continue;
}
const title = this.translationService.instant(column.title);
if (this.filterString(title, query)) {
result.push(column);
}
}
return result;
}
changeColumnVisibility(column: DataColumn): void {
column.isHidden = !column.isHidden;
}
@ -103,14 +132,17 @@ export class ColumnsSelectorComponent implements OnInit, OnDestroy {
return (
this.maxColumnsVisible &&
column.isHidden &&
this.maxColumnsVisible === this.columnItems.filter((dataColumn) => !dataColumn.isHidden).length
this.maxColumnsVisible >= this.columnItems.filter((dataColumn) => !dataColumn.isHidden).length
);
}
private sortColumns(columns: DataColumn[]): DataColumn[] {
const shownColumns = columns.filter((column) => !column.isHidden);
const hiddenColumns = columns.filter((column) => column.isHidden);
if (this.columnsSorting) {
const shownColumns = columns.filter((column) => !column.isHidden);
const hiddenColumns = columns.filter((column) => column.isHidden);
return [...shownColumns, ...hiddenColumns];
return [...shownColumns, ...hiddenColumns];
}
return columns;
}
}

View File

@ -1,44 +0,0 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FilterStringPipe } from './filter-string.pipe';
describe('FilterStringPipe', () => {
let pipe: FilterStringPipe;
beforeEach(() => {
pipe = new FilterStringPipe();
});
it('should left string', () => {
const result = pipe.transform('ABC', 'B');
expect(result).toBe('ABC');
});
it('should filter out string', () => {
const result = pipe.transform('ABC', 'D');
expect(result).toBe('');
});
it('should left string when no query string is passed', () => {
const result = pipe.transform('ABC');
expect(result).toBe('ABC');
});
});

View File

@ -1,30 +0,0 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filterString',
standalone: true
})
export class FilterStringPipe implements PipeTransform {
transform(value: string = '', filterBy: string = ''): string {
const testResult = filterBy ? value.toLowerCase().indexOf(filterBy.toLowerCase()) > -1 : true;
return testResult ? value : '';
}
}

View File

@ -29,7 +29,6 @@ import { LocalizedDatePipe } from './localized-date.pipe';
import { DecimalNumberPipe } from './decimal-number.pipe';
import { MomentDatePipe } from './moment-date.pipe';
import { MomentDateTimePipe } from './moment-datetime.pipe';
import { FilterStringPipe } from './filter-string.pipe';
import { DateTimePipe } from './date-time.pipe';
export const CORE_PIPES = [
@ -45,7 +44,6 @@ export const CORE_PIPES = [
MomentDatePipe,
MomentDateTimePipe,
DateTimePipe,
FilterStringPipe,
InitialUsernamePipe
] as const;

View File

@ -29,4 +29,3 @@ export * from './pipe.module';
export * from './moment-date.pipe';
export * from './moment-datetime.pipe';
export * from './date-time.pipe';
export * from './filter-string.pipe';