mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-08-19 01:03:18 +00:00
Chorehancement: update to Angular v22, 'zoneless' / 'reactive' (#13114)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
|
||||
<li ngbDropdown class="nav-item mx-1" (openChange)="onOpenChange($event)">
|
||||
@if (toasts.length) {
|
||||
<span class="badge rounded-pill z-3 pe-none bg-secondary me-2 position-absolute top-0 left-0">{{ toasts.length }}</span>
|
||||
@if (toasts().length) {
|
||||
<span class="badge rounded-pill z-3 pe-none bg-secondary me-2 position-absolute top-0 left-0">{{ toasts().length }}</span>
|
||||
}
|
||||
<button class="btn border-0" id="notificationsDropdown" ngbDropdownToggle>
|
||||
<i-bs width="1.3em" height="1.3em" name="bell"></i-bs>
|
||||
@@ -12,15 +12,15 @@
|
||||
<div class="btn-group ms-auto">
|
||||
<button class="btn btn-sm btn-outline-secondary mb-2 ms-auto"
|
||||
(click)="toastService.clearToasts()"
|
||||
[disabled]="toasts.length === 0"
|
||||
[disabled]="toasts().length === 0"
|
||||
i18n>Clear All</button>
|
||||
</div>
|
||||
</div>
|
||||
@if (toasts.length === 0) {
|
||||
@if (toasts().length === 0) {
|
||||
<p class="text-center mb-0 small text-muted"><em i18n>No notifications</em></p>
|
||||
}
|
||||
<div class="scroll-list">
|
||||
@for (toast of toasts; track toast.id) {
|
||||
@for (toast of toasts(); track toast.id) {
|
||||
<pngx-toast [autohide]="false" [toast]="toast" (hidden)="onHidden(toast)" (closed)="toastService.closeToast(toast)"></pngx-toast>
|
||||
}
|
||||
</div>
|
||||
|
||||
+16
-35
@@ -1,12 +1,6 @@
|
||||
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing'
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
discardPeriodicTasks,
|
||||
fakeAsync,
|
||||
flush,
|
||||
} from '@angular/core/testing'
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
|
||||
import { Subject } from 'rxjs'
|
||||
import { Toast, ToastService } from 'src/app/services/toast.service'
|
||||
@@ -42,7 +36,8 @@ describe('ToastsDropdownComponent', () => {
|
||||
let component: ToastsDropdownComponent
|
||||
let fixture: ComponentFixture<ToastsDropdownComponent>
|
||||
let toastService: ToastService
|
||||
let toastsSubject: Subject<Toast[]> = new Subject()
|
||||
let toastsSubject: Subject<Toast[]>
|
||||
let getToastsSpy: jest.SpyInstance
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
@@ -56,57 +51,43 @@ describe('ToastsDropdownComponent', () => {
|
||||
],
|
||||
}).compileComponents()
|
||||
|
||||
fixture = TestBed.createComponent(ToastsDropdownComponent)
|
||||
toastService = TestBed.inject(ToastService)
|
||||
jest.spyOn(toastService, 'getToasts').mockReturnValue(toastsSubject)
|
||||
toastsSubject = new Subject()
|
||||
getToastsSpy = jest
|
||||
.spyOn(toastService, 'getToasts')
|
||||
.mockReturnValue(toastsSubject)
|
||||
|
||||
fixture = TestBed.createComponent(ToastsDropdownComponent)
|
||||
component = fixture.componentInstance
|
||||
|
||||
fixture.detectChanges()
|
||||
})
|
||||
|
||||
it('should call getToasts and return toasts', fakeAsync(() => {
|
||||
const spy = jest.spyOn(toastService, 'getToasts')
|
||||
|
||||
component.ngOnInit()
|
||||
it('should call getToasts and return toasts', () => {
|
||||
toastsSubject.next(toasts)
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
expect(component.toasts).toContainEqual({
|
||||
expect(getToastsSpy).toHaveBeenCalled()
|
||||
expect(component.toasts()).toContainEqual({
|
||||
id: 'abc-123',
|
||||
content: 'foo bar',
|
||||
delay: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
component.ngOnDestroy()
|
||||
flush()
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
|
||||
it('should show a toast', fakeAsync(() => {
|
||||
component.ngOnInit()
|
||||
it('should show a toast', () => {
|
||||
toastsSubject.next(toasts)
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(fixture.nativeElement.textContent).toContain('foo bar')
|
||||
})
|
||||
|
||||
component.ngOnDestroy()
|
||||
flush()
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
|
||||
it('should toggle suppressPopupToasts', fakeAsync((finish) => {
|
||||
component.ngOnInit()
|
||||
it('should toggle suppressPopupToasts', () => {
|
||||
fixture.detectChanges()
|
||||
toastsSubject.next(toasts)
|
||||
|
||||
const spy = jest.spyOn(toastService, 'suppressPopupToasts', 'set')
|
||||
component.onOpenChange(true)
|
||||
expect(spy).toHaveBeenCalledWith(true)
|
||||
|
||||
component.ngOnDestroy()
|
||||
flush()
|
||||
discardPeriodicTasks()
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Component, OnDestroy, OnInit, inject } from '@angular/core'
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { toSignal } from '@angular/core/rxjs-interop'
|
||||
import {
|
||||
NgbDropdownModule,
|
||||
NgbProgressbarModule,
|
||||
} from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { Subscription } from 'rxjs'
|
||||
import { map } from 'rxjs'
|
||||
import { Toast, ToastService } from 'src/app/services/toast.service'
|
||||
import { ToastComponent } from '../../common/toast/toast.component'
|
||||
|
||||
@@ -19,22 +20,13 @@ import { ToastComponent } from '../../common/toast/toast.component'
|
||||
NgxBootstrapIconsModule,
|
||||
],
|
||||
})
|
||||
export class ToastsDropdownComponent implements OnInit, OnDestroy {
|
||||
export class ToastsDropdownComponent {
|
||||
toastService = inject(ToastService)
|
||||
|
||||
private subscription: Subscription
|
||||
|
||||
public toasts: Toast[] = []
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.subscription?.unsubscribe()
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.subscription = this.toastService.getToasts().subscribe((toasts) => {
|
||||
this.toasts = [...toasts]
|
||||
})
|
||||
}
|
||||
readonly toasts = toSignal(
|
||||
this.toastService.getToasts().pipe(map((toasts) => [...toasts])),
|
||||
{ initialValue: [] as Toast[] }
|
||||
)
|
||||
|
||||
onOpenChange(open: boolean): void {
|
||||
this.toastService.suppressPopupToasts = open
|
||||
|
||||
Reference in New Issue
Block a user