From 2a4e8f9acd98bfb1c1cc9f0d3f6d78320e6aad6e Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 3 Nov 2025 09:46:35 -0800 Subject: [PATCH] Performance: re-enable virtual scroll, bump ng-select (#11279) --- src-ui/package.json | 2 +- src-ui/pnpm-lock.yaml | 12 ++++++------ .../custom-fields-query-dropdown.component.html | 1 + .../common/input/select/select.component.html | 1 + .../common/input/tags/tags.component.spec.ts | 2 +- .../components/common/input/tags/tags.component.ts | 2 +- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src-ui/package.json b/src-ui/package.json index e75aa3a24..2589a048c 100644 --- a/src-ui/package.json +++ b/src-ui/package.json @@ -21,7 +21,7 @@ "@angular/platform-browser-dynamic": "~20.3.2", "@angular/router": "~20.3.2", "@ng-bootstrap/ng-bootstrap": "^19.0.1", - "@ng-select/ng-select": "^20.2.2", + "@ng-select/ng-select": "^20.6.3", "@ngneat/dirty-check-forms": "^3.0.3", "@popperjs/core": "^2.11.8", "bootstrap": "^5.3.8", diff --git a/src-ui/pnpm-lock.yaml b/src-ui/pnpm-lock.yaml index 5c75a1419..13a84f1c2 100644 --- a/src-ui/pnpm-lock.yaml +++ b/src-ui/pnpm-lock.yaml @@ -39,8 +39,8 @@ importers: specifier: ^19.0.1 version: 19.0.1(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/localize@20.3.2(@angular/compiler-cli@20.3.2(@angular/compiler@20.3.2)(typescript@5.8.3))(@angular/compiler@20.3.2))(@popperjs/core@2.11.8)(rxjs@7.8.2) '@ng-select/ng-select': - specifier: ^20.2.2 - version: 20.2.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)) + specifier: ^20.6.3 + version: 20.6.3(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)) '@ngneat/dirty-check-forms': specifier: ^3.0.3 version: 3.0.3(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(@angular/router@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))(lodash-es@4.17.21)(rxjs@7.8.2) @@ -2356,9 +2356,9 @@ packages: '@popperjs/core': ^2.11.8 rxjs: ^6.5.3 || ^7.4.0 - '@ng-select/ng-select@20.2.2': - resolution: {integrity: sha512-7mctt04/q9yquE4Ec1dQG+SkY6fZ2BQnJLsWmb05TCxYKAYAzDrDTgJJruPDuWrpYx+f3SwejpaI+z/GDrwYdw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + '@ng-select/ng-select@20.6.3': + resolution: {integrity: sha512-+aX2l3OshyPsyMCAuiA3ND5c6X1DG5jQjdlP8PBIyYEoQWlxEcgJWrMsPa7mHVFRpp+5KZZhnXhyosUE4CEc3w==} + engines: {node: ^22.12.0 || >=24.0.0} peerDependencies: '@angular/common': ^20.0.0 '@angular/core': ^20.0.0 @@ -9413,7 +9413,7 @@ snapshots: rxjs: 7.8.2 tslib: 2.8.1 - '@ng-select/ng-select@20.2.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))': + '@ng-select/ng-select@20.6.3(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/forms@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@20.3.2(@angular/common@20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2))': dependencies: '@angular/common': 20.3.2(@angular/core@20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/core': 20.3.2(@angular/compiler@20.3.2)(rxjs@7.8.2)(zone.js@0.15.1) diff --git a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html index a8973e702..7761ecb89 100644 --- a/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html +++ b/src-ui/src/app/components/common/custom-fields-query-dropdown/custom-fields-query-dropdown.component.html @@ -63,6 +63,7 @@ bindValue="id" [(ngModel)]="atom.value" [disabled]="disabled" + [virtualScroll]="getSelectOptionsForField(atom.field)?.length > 100" (mousedown)="$event.stopImmediatePropagation()" > } @else if (getCustomFieldByID(atom.field)?.data_type === CustomFieldDataType.DocumentLink) { diff --git a/src-ui/src/app/components/common/input/select/select.component.html b/src-ui/src/app/components/common/input/select/select.component.html index eb351cbe6..3cfbfe330 100644 --- a/src-ui/src/app/components/common/input/select/select.component.html +++ b/src-ui/src/app/components/common/input/select/select.component.html @@ -29,6 +29,7 @@ [multiple]="multiple" [bindLabel]="bindLabel" bindValue="id" + [virtualScroll]="items?.length > 100" (change)="onChange(value)" (search)="onSearch($event)" (focus)="clearLastSearchTerm()" diff --git a/src-ui/src/app/components/common/input/tags/tags.component.spec.ts b/src-ui/src/app/components/common/input/tags/tags.component.spec.ts index 3c69fbade..84f1c4817 100644 --- a/src-ui/src/app/components/common/input/tags/tags.component.spec.ts +++ b/src-ui/src/app/components/common/input/tags/tags.component.spec.ts @@ -138,7 +138,7 @@ describe('TagsComponent', () => { settingsService.currentUser = { id: 1 } let activeInstances: NgbModalRef[] modalService.activeInstances.subscribe((v) => (activeInstances = v)) - component.select.searchTerm = 'foobar' + component.select.filter('foobar') component.createTag() expect(modalService.hasOpenModals()).toBeTruthy() expect(activeInstances[0].componentInstance.object.name).toEqual('foobar') diff --git a/src-ui/src/app/components/common/input/tags/tags.component.ts b/src-ui/src/app/components/common/input/tags/tags.component.ts index 323d3ddf1..4546dabcb 100644 --- a/src-ui/src/app/components/common/input/tags/tags.component.ts +++ b/src-ui/src/app/components/common/input/tags/tags.component.ts @@ -169,7 +169,7 @@ export class TagsComponent implements OnInit, ControlValueAccessor { if (name) modal.componentInstance.object = { name: name } else if (this.select.searchTerm) modal.componentInstance.object = { name: this.select.searchTerm } - this.select.searchTerm = null + this.select.filter(null) this.select.detectChanges() return firstValueFrom( (modal.componentInstance as TagEditDialogComponent).succeeded.pipe(