Enhancement: notifications improvements (#14500)

This commit is contained in:
shamoon authored and GitHub committed 2026-10-19 19:18:39 -07:00
1 parent c657fceea5
commit 98fb7c3b63
77 files changed
+1535 -627

No files matched your search

@@ -39,6 +39,7 @@ import { TagService } from 'src/app/services/rest/tag.service'
import { UserService } from 'src/app/services/rest/user.service'
import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service'
import { TrashService } from 'src/app/services/trash.service'
import { environment } from 'src/environments/environment'
import { CorrespondentEditDialogComponent } from '../../common/edit-dialog/correspondent-edit-dialog/correspondent-edit-dialog.component'
import { CustomFieldEditDialogComponent } from '../../common/edit-dialog/custom-field-edit-dialog/custom-field-edit-dialog.component'
@@ -74,6 +75,7 @@ describe('BulkEditorComponent', () => {
let documentListViewService: DocumentListViewService
let documentService: DocumentService
let toastService: ToastService
let trashService: TrashService
let modalService: NgbModal
let tagService: TagService
let correspondentsService: CorrespondentService
@@ -185,6 +187,7 @@ describe('BulkEditorComponent', () => {
documentListViewService = TestBed.inject(DocumentListViewService)
documentService = TestBed.inject(DocumentService)
toastService = TestBed.inject(ToastService)
trashService = TestBed.inject(TrashService)
modalService = TestBed.inject(NgbModal)
tagService = TestBed.inject(TagService)
correspondentsService = TestBed.inject(CorrespondentService)
@@ -1164,10 +1167,14 @@ describe('BulkEditorComponent', () => {
let req = httpTestingController.expectOne(
`${environment.apiBaseUrl}documents/delete/`
)
const notifySpy = jest
.spyOn(trashService, 'notifyMovedToTrash')
.mockImplementation(() => {})
req.flush(true)
expect(req.request.body).toEqual({
documents: [3, 4],
})
expect(notifySpy).toHaveBeenCalledWith(expect.any(String), [3, 4])
httpTestingController.match(
`${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&include_selection_data=true`
) // list reload
@@ -1177,10 +1184,19 @@ describe('BulkEditorComponent', () => {
component.showConfirmationDialogs = false
fixture.detectChanges()
jest
.spyOn(documentListViewService, 'allSelected', 'get')
.mockReturnValue(true)
component.applyDelete()
req = httpTestingController.expectOne(
`${environment.apiBaseUrl}documents/delete/`
)
req.flush(true)
// ids aren't known when all matching documents are selected, so no undo
expect(notifySpy).toHaveBeenLastCalledWith(expect.any(String), null)
httpTestingController.match(
`${environment.apiBaseUrl}documents/?page=1&page_size=50&ordering=-created&truncate_content=true&include_selection_data=true`
) // list reload
})
it('should not be accessible with insufficient global permissions', () => {
@@ -1416,7 +1432,7 @@ describe('BulkEditorComponent', () => {
const mergeAsVersionsSpy = jest
.spyOn(documentService, 'mergeDocumentsAsVersions')
.mockReturnValue(of(true))
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const toastSuccessSpy = jest.spyOn(toastService, 'showSuccess')
fixture.detectChanges()
component.mergeSelectedAsVersions()
@@ -1432,7 +1448,9 @@ describe('BulkEditorComponent', () => {
`${environment.apiBaseUrl}documents/?page=1&page_size=100000&fields=id`
)
expect(documentListViewService.selected.size).toEqual(0)
expect(toastInfoSpy).toHaveBeenCalledWith('Documents merged as versions.')
expect(toastSuccessSpy).toHaveBeenCalledWith(
'Documents merged as versions.'
)
})
it('should not report success when merging documents as versions fails', () => {
@@ -1458,7 +1476,7 @@ describe('BulkEditorComponent', () => {
jest
.spyOn(documentService, 'mergeDocumentsAsVersions')
.mockReturnValue(throwError(() => new Error('failed')))
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const toastSuccessSpy = jest.spyOn(toastService, 'showSuccess')
const toastErrorSpy = jest.spyOn(toastService, 'showError')
fixture.detectChanges()
@@ -1467,7 +1485,7 @@ describe('BulkEditorComponent', () => {
modal.componentInstance.confirm()
expect(toastErrorSpy).toHaveBeenCalled()
expect(toastInfoSpy).not.toHaveBeenCalled()
expect(toastSuccessSpy).not.toHaveBeenCalled()
})
it('should support bulk download with archive, originals or both and file formatting', () => {
@@ -1846,7 +1864,7 @@ describe('BulkEditorComponent', () => {
.spyOn(documentListViewService, 'selected', 'get')
.mockReturnValue(new Set([3, 4]))
fixture.detectChanges()
const toastServiceShowInfoSpy = jest.spyOn(toastService, 'showInfo')
const toastServiceShowInfoSpy = jest.spyOn(toastService, 'showSuccess')
const toastServiceShowErrorSpy = jest.spyOn(toastService, 'showError')
const listReloadSpy = jest.spyOn(documentListViewService, 'reload')
@@ -20,7 +20,15 @@ import {
} from '@ng-bootstrap/ng-bootstrap'
import { saveAs } from 'file-saver'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { first, map, Observable, Subject, switchMap, takeUntil } from 'rxjs'
import {
first,
map,
Observable,
Subject,
switchMap,
takeUntil,
tap,
} from 'rxjs'
import { ConfirmDialogComponent } from 'src/app/components/common/confirm-dialog/confirm-dialog.component'
import { CustomField } from 'src/app/data/custom-field'
import { MatchingModel } from 'src/app/data/matching-model'
@@ -49,6 +57,7 @@ import { StoragePathService } from 'src/app/services/rest/storage-path.service'
import { TagService } from 'src/app/services/rest/tag.service'
import { SettingsService } from 'src/app/services/settings.service'
import { ToastService } from 'src/app/services/toast.service'
import { TrashService } from 'src/app/services/trash.service'
import { flattenTags } from 'src/app/utils/flatten-tags'
import { queryParamsFromFilterRules } from 'src/app/utils/query-params'
import { MergeAsVersionsConfirmDialogComponent } from '../../common/confirm-dialog/merge-as-versions-confirm-dialog/merge-as-versions-confirm-dialog.component'
@@ -99,6 +108,7 @@ export class BulkEditorComponent
private openDocumentService = inject(OpenDocumentsService)
private settings = inject(SettingsService)
private toastService = inject(ToastService)
private trashService = inject(TrashService)
private storagePathService = inject(StoragePathService)
private customFieldService = inject(CustomFieldsService)
public readonly permissionService = inject(PermissionsService)
@@ -306,7 +316,7 @@ export class BulkEditorComponent
next: () => {
this.handleOperationSuccess(modal, options.clearSelection ?? false)
if (options.successMessage) {
this.toastService.showInfo(options.successMessage)
this.toastService.showSuccess(options.successMessage)
}
},
error: (error) => this.handleOperationError(modal, error),
@@ -884,19 +894,33 @@ export class BulkEditorComponent
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe(() => {
modal.componentInstance.buttonsEnabled.set(false)
this.executeDocumentAction(
modal,
this.documentService.deleteDocuments(this.getSelectionQuery())
)
this.deleteSelected(modal)
})
} else {
this.executeDocumentAction(
null,
this.documentService.deleteDocuments(this.getSelectionQuery())
)
this.deleteSelected(null)
}
}
private deleteSelected(modal: NgbModalRef) {
const documents = this.list.allSelected
? null
: Array.from(this.list.selected)
const count = this.getSelectionSize()
this.executeDocumentAction(
modal,
this.documentService
.deleteDocuments(this.getSelectionQuery())
.pipe(
tap(() =>
this.trashService.notifyMovedToTrash(
$localize`Moved ${count} document(s) to the trash`,
documents
)
)
)
)
}
downloadSelected() {
this.awaitingDownload.set(true)
let downloadFileType: string =
@@ -1065,7 +1089,7 @@ export class BulkEditorComponent
dialog.selection = this.getSelectionQuery()
dialog.selectionCount = this.getSelectionSize()
dialog.succeeded.subscribe((result) => {
this.toastService.showInfo($localize`Custom fields updated.`)
this.toastService.showSuccess($localize`Custom fields updated.`)
this.list.reload()
this.list.reduceSelectionToFilter()
this.list.selected.forEach((id) => {
@@ -487,7 +487,7 @@ describe('DocumentListComponent', () => {
delete modifiedView.name
const savedViewServicePatch = jest.spyOn(savedViewService, 'patch')
savedViewServicePatch.mockReturnValue(of(modifiedView))
const toastSpy = jest.spyOn(toastService, 'showInfo')
const toastSpy = jest.spyOn(toastService, 'showSuccess')
component.saveViewConfig()
expect(savedViewServicePatch).toHaveBeenCalledWith(modifiedView)
@@ -592,7 +592,7 @@ describe('DocumentListComponent', () => {
let openModal: NgbModalRef
modalService.activeInstances.subscribe((modal) => (openModal = modal[0]))
const modalSpy = jest.spyOn(modalService, 'open')
const toastSpy = jest.spyOn(toastService, 'showInfo')
const toastSpy = jest.spyOn(toastService, 'showSuccess')
const savedViewServiceCreate = jest.spyOn(savedViewService, 'create')
jest
.spyOn(savedViewService, 'dashboardViews', 'get')
@@ -418,7 +418,7 @@ export class DocumentListComponent
next: (view) => {
this.activeSavedView = view
this.unmodifiedSavedView = view
this.toastService.showInfo(
this.toastService.showSuccess(
$localize`View "${this.list.activeSavedViewTitle}" saved successfully.`
)
this.unmodifiedFilterRules.set(this.list.filterRules)
@@ -493,7 +493,7 @@ export class DocumentListComponent
.subscribe({
next: () => {
modal.close()
this.toastService.showInfo(
this.toastService.showSuccess(
$localize`View "${savedView.name}" created successfully.`
)
},