mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-11-05 14:29:22 +00:00
Chorehancement: update to Angular v22, 'zoneless' / 'reactive' (#13114)
This commit is contained in:
1 parent
f244442c65
commit
106b41a15c
213 files changed
+5363
-5842
No files matched your search
+10
-10
@@ -1,15 +1,15 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title}}</h4>
|
||||
<h4 class="modal-title" id="modal-basic-title">{{title()}}</h4>
|
||||
<button type="button" class="btn-close" aria-label="Close" (click)="close()"></button>
|
||||
</div>
|
||||
<div class="modal-body p-0">
|
||||
<ul class="list-group list-group-flush">
|
||||
@if (!shareLinks || shareLinks.length === 0) {
|
||||
@if (!shareLinks() || shareLinks().length === 0) {
|
||||
<li class="list-group-item fst-italic small text-center text-secondary" i18n>
|
||||
No existing links
|
||||
</li>
|
||||
}
|
||||
@for (link of shareLinks; track link) {
|
||||
@for (link of shareLinks(); track link) {
|
||||
<li class="list-group-item">
|
||||
<div class="input-group w-100">
|
||||
<input type="text" class="form-control" aria-label="Share link" [value]="getShareUrl(link)" readonly>
|
||||
@@ -19,10 +19,10 @@
|
||||
</span>
|
||||
}
|
||||
<button type="button" class="btn btn-outline-primary" (click)="copy(link)">
|
||||
@if (copied !== link.id) {
|
||||
@if (copied() !== link.id) {
|
||||
<i-bs width="1.2em" height="1.2em" name="clipboard-fill"></i-bs>
|
||||
}
|
||||
@if (copied === link.id) {
|
||||
@if (copied() === link.id) {
|
||||
<i-bs width="1.2em" height="1.2em" name="clipboard-check-fill"></i-bs>
|
||||
}
|
||||
<span class="visually-hidden" i18n>Copy</span>
|
||||
@@ -36,7 +36,7 @@
|
||||
<i-bs width="1.2em" height="1.2em" name="trash"></i-bs><span class="visually-hidden" i18n>Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
<span class="badge copied-badge bg-primary small fade ms-4 position-absolute top-50 translate-middle-y pe-none z-3" [class.show]="copied === link.id" i18n>Copied!</span>
|
||||
<span class="badge copied-badge bg-primary small fade ms-4 position-absolute top-50 translate-middle-y pe-none z-3" [class.show]="copied() === link.id" i18n>Copied!</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
@@ -44,7 +44,7 @@
|
||||
<div class="modal-footer">
|
||||
<div class="input-group w-100">
|
||||
<div class="form-check form-switch ms-auto">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="versionSwitch" [disabled]="!hasArchiveVersion" [(ngModel)]="useArchiveVersion">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="versionSwitch" [disabled]="!hasArchiveVersion()" [(ngModel)]="useArchiveVersion">
|
||||
<label class="form-check-label" for="versionSwitch" i18n>Share archive version</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,11 +55,11 @@
|
||||
<option [ngValue]="option.value">{{ option.label }}</option>
|
||||
}
|
||||
</select>
|
||||
<button class="btn btn-outline-primary ms-auto" type="button" (click)="createLink()" [disabled]="loading">
|
||||
@if (loading) {
|
||||
<button class="btn btn-outline-primary ms-auto" type="button" (click)="createLink()" [disabled]="loading()">
|
||||
@if (loading()) {
|
||||
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
|
||||
}
|
||||
@if (!loading) {
|
||||
@if (!loading()) {
|
||||
<i-bs name="plus"></i-bs>
|
||||
}
|
||||
<ng-container i18n>Create</ng-container>
|
||||
|
||||
+14
-17
@@ -4,12 +4,7 @@ import {
|
||||
HttpTestingController,
|
||||
provideHttpClientTesting,
|
||||
} from '@angular/common/http/testing'
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
fakeAsync,
|
||||
tick,
|
||||
} from '@angular/core/testing'
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { By } from '@angular/platform-browser'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
@@ -56,7 +51,7 @@ describe('ShareLinksDialogComponent', () => {
|
||||
|
||||
it('should support refresh to retrieve links', () => {
|
||||
const getSpy = jest.spyOn(shareLinkService, 'getLinksForDocument')
|
||||
component.documentId = 99
|
||||
component.documentId.set(99)
|
||||
|
||||
const now = new Date()
|
||||
const expiration7days = new Date()
|
||||
@@ -88,7 +83,7 @@ describe('ShareLinksDialogComponent', () => {
|
||||
|
||||
fixture.detectChanges()
|
||||
|
||||
expect(component.shareLinks).toHaveLength(2)
|
||||
expect(component.shareLinks()).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('should show error on refresh if needed', () => {
|
||||
@@ -96,16 +91,17 @@ describe('ShareLinksDialogComponent', () => {
|
||||
jest
|
||||
.spyOn(shareLinkService, 'getLinksForDocument')
|
||||
.mockReturnValueOnce(throwError(() => new Error('Unable to get links')))
|
||||
component.documentId = 99
|
||||
component.documentId.set(99)
|
||||
|
||||
component.ngOnInit()
|
||||
fixture.detectChanges()
|
||||
expect(toastSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should support link creation then refresh & copy url', fakeAsync(() => {
|
||||
it('should support link creation then refresh & copy url', () => {
|
||||
jest.useFakeTimers()
|
||||
const createSpy = jest.spyOn(shareLinkService, 'createLinkForDocument')
|
||||
component.documentId = 99
|
||||
component.documentId.set(99)
|
||||
component.expirationDays = 7
|
||||
component.useArchiveVersion = false
|
||||
|
||||
@@ -126,16 +122,17 @@ describe('ShareLinksDialogComponent', () => {
|
||||
expiration: expiration.toISOString(),
|
||||
})
|
||||
fixture.detectChanges()
|
||||
tick(3000)
|
||||
jest.advanceTimersByTime(3000)
|
||||
|
||||
expect(refreshSpy).toHaveBeenCalled()
|
||||
expect(copySpy).toHaveBeenCalled()
|
||||
expect(component.copied).toEqual(1)
|
||||
tick(100) // copy timeout
|
||||
}))
|
||||
expect(component.copied()).toEqual(1)
|
||||
jest.advanceTimersByTime(100) // copy timeout
|
||||
jest.useRealTimers()
|
||||
})
|
||||
|
||||
it('should show error on link creation if needed', () => {
|
||||
component.documentId = 99
|
||||
component.documentId.set(99)
|
||||
component.expirationDays = 7
|
||||
|
||||
const expiration = new Date()
|
||||
@@ -227,7 +224,7 @@ describe('ShareLinksDialogComponent', () => {
|
||||
})
|
||||
|
||||
it('should disable archive switch & option if no archive available', (done) => {
|
||||
component.hasArchiveVersion = false
|
||||
component.hasArchiveVersion.set(false)
|
||||
component.ngOnInit()
|
||||
fixture.detectChanges()
|
||||
expect(component.useArchiveVersion).toBeFalsy()
|
||||
|
||||
+29
-44
@@ -1,5 +1,5 @@
|
||||
import { Clipboard } from '@angular/cdk/clipboard'
|
||||
import { Component, Input, OnInit, inject } from '@angular/core'
|
||||
import { Component, OnInit, effect, inject, input, signal } from '@angular/core'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
@@ -27,55 +27,40 @@ export class ShareLinksDialogComponent implements OnInit {
|
||||
|
||||
readonly expirationOptions = SHARE_LINK_EXPIRATION_OPTIONS
|
||||
|
||||
@Input()
|
||||
title = $localize`Share Links`
|
||||
|
||||
_documentId: number
|
||||
|
||||
@Input()
|
||||
set documentId(id: number) {
|
||||
if (id !== undefined) {
|
||||
this._documentId = id
|
||||
this.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
private _hasArchiveVersion: boolean = true
|
||||
|
||||
@Input()
|
||||
set hasArchiveVersion(value: boolean) {
|
||||
this._hasArchiveVersion = value
|
||||
this.useArchiveVersion = value
|
||||
}
|
||||
|
||||
get hasArchiveVersion(): boolean {
|
||||
return this._hasArchiveVersion
|
||||
}
|
||||
|
||||
shareLinks: ShareLink[]
|
||||
|
||||
loading: boolean = false
|
||||
|
||||
copied: number
|
||||
readonly title = input($localize`Share Links`)
|
||||
readonly documentId = signal<number>(undefined)
|
||||
readonly hasArchiveVersion = signal(true)
|
||||
readonly shareLinks = signal<ShareLink[]>(undefined)
|
||||
readonly loading = signal(false)
|
||||
readonly copied = signal<number>(undefined)
|
||||
|
||||
expirationDays: number = 7
|
||||
|
||||
useArchiveVersion: boolean = true
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const id = this.documentId()
|
||||
if (id !== undefined) this.refresh()
|
||||
})
|
||||
effect(() => {
|
||||
this.useArchiveVersion = this.hasArchiveVersion()
|
||||
})
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this._documentId !== undefined) this.refresh()
|
||||
if (this.documentId() !== undefined) this.refresh()
|
||||
}
|
||||
|
||||
refresh() {
|
||||
if (this._documentId === undefined) return
|
||||
this.loading = true
|
||||
if (this.documentId() === undefined) return
|
||||
this.loading.set(true)
|
||||
this.shareLinkService
|
||||
.getLinksForDocument(this._documentId)
|
||||
.getLinksForDocument(this.documentId())
|
||||
.pipe(first())
|
||||
.subscribe({
|
||||
next: (results) => {
|
||||
this.loading = false
|
||||
this.shareLinks = results
|
||||
this.loading.set(false)
|
||||
this.shareLinks.set(results)
|
||||
},
|
||||
error: (e) => {
|
||||
this.toastService.showError(
|
||||
@@ -104,9 +89,9 @@ export class ShareLinksDialogComponent implements OnInit {
|
||||
copy(link: ShareLink) {
|
||||
const success = this.clipboard.copy(this.getShareUrl(link))
|
||||
if (success) {
|
||||
this.copied = link.id
|
||||
this.copied.set(link.id)
|
||||
setTimeout(() => {
|
||||
this.copied = null
|
||||
this.copied.set(null)
|
||||
}, 3000)
|
||||
}
|
||||
}
|
||||
@@ -138,23 +123,23 @@ export class ShareLinksDialogComponent implements OnInit {
|
||||
expiration = new Date()
|
||||
expiration.setDate(expiration.getDate() + this.expirationDays)
|
||||
}
|
||||
this.loading = true
|
||||
this.loading.set(true)
|
||||
this.shareLinkService
|
||||
.createLinkForDocument(
|
||||
this._documentId,
|
||||
this.documentId(),
|
||||
this.useArchiveVersion ? FileVersion.Archive : FileVersion.Original,
|
||||
expiration
|
||||
)
|
||||
.subscribe({
|
||||
next: (result) => {
|
||||
this.loading = false
|
||||
this.loading.set(false)
|
||||
setTimeout(() => {
|
||||
this.copy(result)
|
||||
}, 10)
|
||||
this.refresh()
|
||||
},
|
||||
error: (e) => {
|
||||
this.loading = false
|
||||
this.loading.set(false)
|
||||
this.toastService.showError($localize`Error creating link`, 10000, e)
|
||||
},
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user