From 1b0232a4d7cd95eac02abd4cc69480c3d71ccadc Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 8 Jul 2026 13:02:10 -0700 Subject: [PATCH] Tasks and trash to direct signals --- .../admin/tasks/tasks.component.html | 4 +- .../admin/tasks/tasks.component.spec.ts | 6 +- .../components/admin/tasks/tasks.component.ts | 52 ++++--------- .../admin/trash/trash.component.html | 26 +++---- .../admin/trash/trash.component.spec.ts | 18 ++--- .../components/admin/trash/trash.component.ts | 74 +++++-------------- 6 files changed, 59 insertions(+), 121 deletions(-) diff --git a/src-ui/src/app/components/admin/tasks/tasks.component.html b/src-ui/src/app/components/admin/tasks/tasks.component.html index e1d6bc900..05a224a0a 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.html +++ b/src-ui/src/app/components/admin/tasks/tasks.component.html @@ -11,7 +11,7 @@ -
@@ -107,7 +107,7 @@ { ) req.flush({ count: 2, results: [tasks[0], tasks[1]] }) - expect(component.totalTasks).toBe(2) + expect(component.totalTasks()).toBe(2) }) it('should apply task type and trigger source filters to the server-side task query', () => { @@ -435,8 +435,8 @@ describe('TasksComponent', () => { .flush(pageTwoTasks) expect(component.page).toBe(2) - expect(component.totalTasks).toBe(30) - expect(component.pagedTasks).toEqual([tasks[0]]) + expect(component.totalTasks()).toBe(30) + expect(component.pagedTasks()).toEqual([tasks[0]]) }) it('should not replace section counts with current-page counts', () => { diff --git a/src-ui/src/app/components/admin/tasks/tasks.component.ts b/src-ui/src/app/components/admin/tasks/tasks.component.ts index a5bca0864..a8fd69911 100644 --- a/src-ui/src/app/components/admin/tasks/tasks.component.ts +++ b/src-ui/src/app/components/admin/tasks/tasks.component.ts @@ -166,42 +166,18 @@ export class TasksComponent public autoRefreshEnabled: boolean = true public readonly pageSize = 25 public page: number = 1 - private totalTasksSignal = signal(0) - private sectionCountsSignal = signal>({ + readonly totalTasks = signal(0) + readonly sectionCounts = signal>({ [TaskSection.All]: 0, [TaskSection.NeedsAttention]: 0, [TaskSection.InProgress]: 0, [TaskSection.Completed]: 0, }) - private pagedTasksSignal = signal([]) + readonly pagedTasks = signal([]) public selectedSection: TaskSection = TaskSection.All public selectedTaskType: PaperlessTaskType | null = null public selectedTriggerSource: PaperlessTaskTriggerSource | null = null - public get totalTasks(): number { - return this.totalTasksSignal() - } - - public set totalTasks(value: number) { - this.totalTasksSignal.set(value) - } - - public get sectionCounts(): Record { - return this.sectionCountsSignal() - } - - public set sectionCounts(value: Record) { - this.sectionCountsSignal.set(value) - } - - public get pagedTasks(): PaperlessTask[] { - return this.pagedTasksSignal() - } - - public set pagedTasks(value: PaperlessTask[]) { - this.pagedTasksSignal.set(value) - } - private _filterText: string = '' get filterText() { return this._filterText @@ -370,7 +346,7 @@ export class TasksComponent backdrop: 'static', }) modal.componentInstance.title = $localize`Confirm Dismiss All` - modal.componentInstance.messageBold = $localize`Dismiss all ${this.totalTasks} tasks?` + modal.componentInstance.messageBold = $localize`Dismiss all ${this.totalTasks()} tasks?` modal.componentInstance.btnClass = 'btn-warning' modal.componentInstance.btnCaption = $localize`Dismiss` modal.componentInstance.confirmClicked.pipe(first()).subscribe(() => { @@ -489,7 +465,7 @@ export class TasksComponent } tasksForSection(section: TaskSection): PaperlessTask[] { - let tasks = this.pagedTasks.filter((task) => + let tasks = this.pagedTasks().filter((task) => this.taskBelongsToSection(task, section) ) @@ -501,11 +477,11 @@ export class TasksComponent } sectionCount(section: TaskSection): number { - return this.sectionCounts[section] + return this.sectionCounts()[section] } private setSectionCount(section: TaskSection, count: number) { - this.sectionCountsSignal.update((counts) => ({ + this.sectionCounts.update((counts) => ({ ...counts, [section]: count, })) @@ -683,7 +659,7 @@ export class TasksComponent ? this.sections : [this.selectedSection] - return this.pagedTasks.filter( + return this.pagedTasks().filter( (task) => sections.some((section) => this.taskBelongsToSection(task, section)) && this.taskMatchesFilters(task, { taskType, triggerSource }) @@ -695,12 +671,12 @@ export class TasksComponent .statusCounts(this.getParamsForSection(TaskSection.All)) .pipe(first(), takeUntil(this.unsubscribeNotifier)) .subscribe((counts) => { - this.sectionCounts = { + this.sectionCounts.set({ [TaskSection.All]: counts.all, [TaskSection.NeedsAttention]: counts.needs_attention, [TaskSection.InProgress]: counts.in_progress, [TaskSection.Completed]: counts.completed, - } + }) }) } @@ -766,8 +742,8 @@ export class TasksComponent .pipe(first(), takeUntil(this.unsubscribeNotifier)) .subscribe({ next: (result) => { - this.pagedTasks = result.results - this.totalTasks = result.count + this.pagedTasks.set(result.results) + this.totalTasks.set(result.count) this.setSectionCount(TaskSection.All, result.count) if (this.selectedSection !== TaskSection.All) { this.setSectionCount(this.selectedSection, result.count) @@ -775,8 +751,8 @@ export class TasksComponent this.loading = false if ( this.page > 1 && - this.pagedTasks.length === 0 && - this.totalTasks > 0 + this.pagedTasks().length === 0 && + this.totalTasks() > 0 ) { this.page -= 1 this.reloadPage() diff --git a/src-ui/src/app/components/admin/trash/trash.component.html b/src-ui/src/app/components/admin/trash/trash.component.html index c729d26f2..d680a0575 100644 --- a/src-ui/src/app/components/admin/trash/trash.component.html +++ b/src-ui/src/app/components/admin/trash/trash.component.html @@ -4,22 +4,22 @@ info="Manage trashed documents that are pending deletion." i18n-info infoLink="usage/#document-trash"> - - - -
- +
@@ -28,7 +28,7 @@
- +
@@ -46,11 +46,11 @@ } - @for (document of documentsInTrash; track document.id) { + @for (document of documentsInTrash(); track document.id) {
- +
@@ -91,13 +91,13 @@ @if (!loading) {
- {totalDocuments, plural, =1 {One document in trash} other {{{totalDocuments || 0}} total documents in trash}} - @if (selectedDocuments.size > 0) { -  ({{selectedDocuments.size}} selected) + {totalDocuments(), plural, =1 {One document in trash} other {{{totalDocuments() || 0}} total documents in trash}} + @if (selectedDocuments().size > 0) { +  ({{selectedDocuments().size}} selected) }
- @if (documentsInTrash.length > 20) { - + @if (documentsInTrash().length > 20) { + }
} diff --git a/src-ui/src/app/components/admin/trash/trash.component.spec.ts b/src-ui/src/app/components/admin/trash/trash.component.spec.ts index 215b0b253..65f9fd4af 100644 --- a/src-ui/src/app/components/admin/trash/trash.component.spec.ts +++ b/src-ui/src/app/components/admin/trash/trash.component.spec.ts @@ -77,7 +77,7 @@ describe('TrashComponent', () => { component.reload() jest.advanceTimersByTime(100) expect(trashSpy).toHaveBeenCalled() - expect(component.documentsInTrash).toEqual(documentsInTrash) + expect(component.documentsInTrash()).toEqual(documentsInTrash) }) it('should support delete document, show error if needed', () => { @@ -179,8 +179,8 @@ describe('TrashComponent', () => { }) it('should support toggle all items in view', () => { - component.documentsInTrash = documentsInTrash - expect(component.selectedDocuments.size).toEqual(0) + component.documentsInTrash.set(documentsInTrash) + expect(component.selectedDocuments().size).toEqual(0) const toggleAllSpy = jest.spyOn(component, 'toggleAll') const checkButton = fixture.debugElement.queryAll( By.css('input.form-check-input') @@ -189,21 +189,21 @@ describe('TrashComponent', () => { checkButton.nativeElement.checked = true checkButton.nativeElement.dispatchEvent(new Event('click')) expect(toggleAllSpy).toHaveBeenCalled() - expect(component.selectedDocuments.size).toEqual(documentsInTrash.length) + expect(component.selectedDocuments().size).toEqual(documentsInTrash.length) }) it('should support toggle item', () => { - component.selectedDocuments = new Set([1]) + component.selectedDocuments.set(new Set([1])) component.toggleSelected(documentsInTrash[0]) - expect(component.selectedDocuments.size).toEqual(0) + expect(component.selectedDocuments().size).toEqual(0) component.toggleSelected(documentsInTrash[0]) - expect(component.selectedDocuments.size).toEqual(1) + expect(component.selectedDocuments().size).toEqual(1) }) it('should support clear selection', () => { - component.selectedDocuments = new Set([1]) + component.selectedDocuments.set(new Set([1])) component.clearSelection() - expect(component.selectedDocuments.size).toEqual(0) + expect(component.selectedDocuments().size).toEqual(0) }) it('should correctly display days remaining', () => { diff --git a/src-ui/src/app/components/admin/trash/trash.component.ts b/src-ui/src/app/components/admin/trash/trash.component.ts index 0e9299596..474a0e91c 100644 --- a/src-ui/src/app/components/admin/trash/trash.component.ts +++ b/src-ui/src/app/components/admin/trash/trash.component.ts @@ -42,51 +42,11 @@ export class TrashComponent private settingsService = inject(SettingsService) private router = inject(Router) - private documentsInTrashSignal = signal([]) - private selectedDocumentsSignal = signal>(new Set()) - private allToggledSignal = signal(false) - private pageSignal = signal(1) - private totalDocumentsSignal = signal(undefined) - - public get documentsInTrash(): Document[] { - return this.documentsInTrashSignal() - } - - public set documentsInTrash(documentsInTrash: Document[]) { - this.documentsInTrashSignal.set(documentsInTrash) - } - - public get selectedDocuments(): Set { - return this.selectedDocumentsSignal() - } - - public set selectedDocuments(selectedDocuments: Set) { - this.selectedDocumentsSignal.set(selectedDocuments) - } - - public get allToggled(): boolean { - return this.allToggledSignal() - } - - public set allToggled(allToggled: boolean) { - this.allToggledSignal.set(allToggled) - } - - public get page(): number { - return this.pageSignal() - } - - public set page(page: number) { - this.pageSignal.set(page) - } - - public get totalDocuments(): number { - return this.totalDocumentsSignal() - } - - public set totalDocuments(totalDocuments: number) { - this.totalDocumentsSignal.set(totalDocuments) - } + readonly documentsInTrash = signal([]) + readonly selectedDocuments = signal>(new Set()) + readonly allToggled = signal(false) + readonly page = signal(1) + readonly totalDocuments = signal(undefined) constructor() { super() @@ -96,12 +56,12 @@ export class TrashComponent reload() { this.loading = true this.trashService - .getTrash(this.page) + .getTrash(this.page()) .pipe( tap((r) => { - this.documentsInTrash = r.results - this.totalDocuments = r.count - this.selectedDocuments = new Set() + this.documentsInTrash.set(r.results) + this.totalDocuments.set(r.count) + this.selectedDocuments.set(new Set()) this.loading = false }) ) @@ -161,7 +121,7 @@ export class TrashComponent .subscribe({ next: () => { this.toastService.showInfo($localize`Document(s) deleted`) - this.allToggled = false + this.allToggled.set(false) modal.close() this.reload() }, @@ -204,7 +164,7 @@ export class TrashComponent .subscribe({ next: () => { this.toastService.showInfo($localize`Document(s) restored`) - this.allToggled = false + this.allToggled.set(false) this.reload() }, error: (err) => { @@ -218,23 +178,25 @@ export class TrashComponent toggleAll(event: PointerEvent) { if ((event.target as HTMLInputElement).checked) { - this.selectedDocuments = new Set(this.documentsInTrash.map((t) => t.id)) + this.selectedDocuments.set( + new Set(this.documentsInTrash().map((t) => t.id)) + ) } else { this.clearSelection() } } toggleSelected(object: Document) { - const selectedDocuments = new Set(this.selectedDocuments) + const selectedDocuments = new Set(this.selectedDocuments()) selectedDocuments.has(object.id) ? selectedDocuments.delete(object.id) : selectedDocuments.add(object.id) - this.selectedDocuments = selectedDocuments + this.selectedDocuments.set(selectedDocuments) } clearSelection() { - this.allToggled = false - this.selectedDocuments = new Set() + this.allToggled.set(false) + this.selectedDocuments.set(new Set()) } getDaysRemaining(document: Document): number {