From 6dc933dabf596f8defd572fa59d8abdc7e2c9ade Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sat, 14 Mar 2026 22:14:46 -0700 Subject: [PATCH] Wire up selection with hasSelection, allSelected since we dont get list of IDs anymore --- .../document-list.component.html | 14 ++--- .../document-list/document-list.component.ts | 6 +-- .../document-list-view.service.spec.ts | 28 +++++----- .../services/document-list-view.service.ts | 54 +++++++++++++++++-- 4 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src-ui/src/app/components/document-list/document-list.component.html b/src-ui/src/app/components/document-list/document-list.component.html index 176513663..aadec7d77 100644 --- a/src-ui/src/app/components/document-list/document-list.component.html +++ b/src-ui/src/app/components/document-list/document-list.component.html @@ -2,8 +2,8 @@
@@ -17,7 +17,7 @@ Select:
- @if (list.selected.size > 0) { + @if (list.hasSelection) { @@ -127,11 +127,11 @@
Loading... } - @if (list.selected.size > 0) { - {list.collectionSize, plural, =1 {Selected {{list.selected.size}} of one document} other {Selected {{list.selected.size}} of {{list.collectionSize || 0}} documents}} + @if (list.hasSelection) { + {list.collectionSize, plural, =1 {Selected {{list.selectedCount}} of one document} other {Selected {{list.selectedCount}} of {{list.collectionSize || 0}} documents}} } @if (!list.isReloading) { - @if (list.selected.size === 0) { + @if (!list.hasSelection) { {list.collectionSize, plural, =1 {One document} other {{{list.collectionSize || 0}} documents}} } @if (isFiltered) {  (filtered) @@ -142,7 +142,7 @@ Reset filters } - @if (!list.isReloading && list.selected.size > 0) { + @if (!list.isReloading && list.hasSelection) { diff --git a/src-ui/src/app/components/document-list/document-list.component.ts b/src-ui/src/app/components/document-list/document-list.component.ts index 2cd2ccaf3..eb453d4dc 100644 --- a/src-ui/src/app/components/document-list/document-list.component.ts +++ b/src-ui/src/app/components/document-list/document-list.component.ts @@ -240,7 +240,7 @@ export class DocumentListComponent } get isBulkEditing(): boolean { - return this.list.selected.size > 0 + return this.list.hasSelection } toggleDisplayField(field: DisplayField) { @@ -327,7 +327,7 @@ export class DocumentListComponent }) .pipe(takeUntil(this.unsubscribeNotifier)) .subscribe(() => { - if (this.list.selected.size > 0) { + if (this.list.hasSelection) { this.list.selectNone() } else if (this.isFiltered) { this.resetFilters() @@ -356,7 +356,7 @@ export class DocumentListComponent .pipe(takeUntil(this.unsubscribeNotifier)) .subscribe(() => { if (this.list.documents.length > 0) { - if (this.list.selected.size > 0) { + if (this.list.hasSelection) { this.openDocumentDetail(Array.from(this.list.selected)[0]) } else { this.openDocumentDetail(this.list.documents[0]) diff --git a/src-ui/src/app/services/document-list-view.service.spec.ts b/src-ui/src/app/services/document-list-view.service.spec.ts index de574d6d3..bfbd26ff0 100644 --- a/src-ui/src/app/services/document-list-view.service.spec.ts +++ b/src-ui/src/app/services/document-list-view.service.spec.ts @@ -510,12 +510,16 @@ describe('DocumentListViewService', () => { }) it('should support select all', () => { - documentListViewService.selectAll() - const req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id` + documentListViewService.reload() + const reloadReq = httpTestingController.expectOne( + `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&include_selection_data=true` ) - expect(req.request.method).toEqual('GET') - req.flush(full_results) + expect(reloadReq.request.method).toEqual('GET') + reloadReq.flush(full_results) + + documentListViewService.selectAll() + expect(documentListViewService.allSelected).toBeTruthy() + expect(documentListViewService.selectedCount).toEqual(documents.length) expect(documentListViewService.selected.size).toEqual(documents.length) expect(documentListViewService.isSelected(documents[0])).toBeTruthy() documentListViewService.selectNone() @@ -552,25 +556,25 @@ describe('DocumentListViewService', () => { }) it('should support selection range reduction', () => { - documentListViewService.selectAll() + documentListViewService.reload() let req = httpTestingController.expectOne( - `${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id` + `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&include_selection_data=true` ) expect(req.request.method).toEqual('GET') req.flush(full_results) + + documentListViewService.selectAll() expect(documentListViewService.selected.size).toEqual(6) documentListViewService.setFilterRules(filterRules) - httpTestingController.expectOne( + req = httpTestingController.expectOne( `${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&include_selection_data=true&tags__id__all=9` ) - const reqs = httpTestingController.match( - `${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id&tags__id__all=9` - ) - reqs[0].flush({ + req.flush({ count: 3, results: documents.slice(0, 3), }) + expect(documentListViewService.allSelected).toBeTruthy() expect(documentListViewService.selected.size).toEqual(3) }) diff --git a/src-ui/src/app/services/document-list-view.service.ts b/src-ui/src/app/services/document-list-view.service.ts index 9413d3562..9983bc62d 100644 --- a/src-ui/src/app/services/document-list-view.service.ts +++ b/src-ui/src/app/services/document-list-view.service.ts @@ -66,6 +66,11 @@ export interface ListViewState { */ selected?: Set + /** + * True if the full filtered result set is selected. + */ + allSelected?: boolean + /** * The page size of the list view. */ @@ -166,6 +171,20 @@ export class DocumentListViewService { sortReverse: true, filterRules: [], selected: new Set(), + allSelected: false, + } + } + + private syncSelectedToCurrentPage() { + if (!this.allSelected) { + return + } + + this.selected.clear() + this.documents?.forEach((doc) => this.selected.add(doc.id)) + + if (!this.collectionSize) { + this.selectNone() } } @@ -272,6 +291,7 @@ export class DocumentListViewService { activeListViewState.collectionSize = result.count activeListViewState.documents = result.results this.selectionData = resultWithSelectionData.selection_data ?? null + this.syncSelectedToCurrentPage() if (updateQueryParams && !this._activeSavedViewId) { let base = ['/documents'] @@ -404,6 +424,20 @@ export class DocumentListViewService { return this.activeListViewState.selected } + get allSelected(): boolean { + return this.activeListViewState.allSelected ?? false + } + + get selectedCount(): number { + return this.allSelected + ? (this.collectionSize ?? this.selected.size) + : this.selected.size + } + + get hasSelection(): boolean { + return this.allSelected || this.selected.size > 0 + } + setSort(field: string, reverse: boolean) { this.activeListViewState.sortField = field this.activeListViewState.sortReverse = reverse @@ -558,11 +592,16 @@ export class DocumentListViewService { } selectNone() { + this.activeListViewState.allSelected = false this.selected.clear() this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null } reduceSelectionToFilter() { + if (this.allSelected) { + return + } + if (this.selected.size > 0) { this.documentService .listAllFilteredIds(this.filterRules) @@ -577,12 +616,12 @@ export class DocumentListViewService { } selectAll() { - this.documentService - .listAllFilteredIds(this.filterRules) - .subscribe((ids) => ids.forEach((id) => this.selected.add(id))) + this.activeListViewState.allSelected = true + this.syncSelectedToCurrentPage() } selectPage() { + this.activeListViewState.allSelected = false this.selected.clear() this.documents.forEach((doc) => { this.selected.add(doc.id) @@ -590,10 +629,13 @@ export class DocumentListViewService { } isSelected(d: Document) { - return this.selected.has(d.id) + return this.allSelected || this.selected.has(d.id) } toggleSelected(d: Document): void { + if (this.allSelected) { + this.activeListViewState.allSelected = false + } if (this.selected.has(d.id)) this.selected.delete(d.id) else this.selected.add(d.id) this.rangeSelectionAnchorIndex = this.documentIndexInCurrentView(d.id) @@ -601,6 +643,10 @@ export class DocumentListViewService { } selectRangeTo(d: Document) { + if (this.allSelected) { + this.activeListViewState.allSelected = false + } + if (this.rangeSelectionAnchorIndex !== null) { const documentToIndex = this.documentIndexInCurrentView(d.id) const fromIndex = Math.min(