Chore: update to Angular 20 (#10273)

This commit is contained in:
shamoon
2025-06-27 14:06:40 -07:00
committed by GitHub
parent dfad3c4d8e
commit 958f98d7e5
146 changed files with 2662 additions and 2687 deletions

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { ActivationStart, Event, Router } from '@angular/router'
import { filter } from 'rxjs'
@@ -8,10 +8,12 @@ const EXCLUDE_COMPONENTS = ['AppFrameComponent']
providedIn: 'root',
})
export class ComponentRouterService {
private router = inject(Router)
private history: string[] = []
private componentHistory: any[] = []
constructor(private router: Router) {
constructor() {
this.router.events
.pipe(filter((event: Event) => event instanceof ActivationStart))
.subscribe((event: ActivationStart) => {

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable, first, map } from 'rxjs'
import { environment } from 'src/environments/environment'
import { PaperlessConfig } from '../data/paperless-config'
@@ -8,9 +8,9 @@ import { PaperlessConfig } from '../data/paperless-config'
providedIn: 'root',
})
export class ConfigService {
protected baseUrl: string = environment.apiBaseUrl + 'config/'
protected http = inject(HttpClient)
constructor(protected http: HttpClient) {}
protected baseUrl: string = environment.apiBaseUrl + 'config/'
getConfig(): Observable<PaperlessConfig> {
return this.http.get<[PaperlessConfig]>(this.baseUrl).pipe(

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { ParamMap, Router } from '@angular/router'
import { Observable, Subject, first, takeUntil } from 'rxjs'
import {
@@ -91,6 +91,10 @@ export interface ListViewState {
providedIn: 'root',
})
export class DocumentListViewService {
private documentService = inject(DocumentService)
private settings = inject(SettingsService)
private router = inject(Router)
isReloading: boolean = false
initialized: boolean = false
error: string = null
@@ -116,11 +120,7 @@ export class DocumentListViewService {
return this.activeListViewState.title
}
constructor(
private documentService: DocumentService,
private settings: SettingsService,
private router: Router
) {
constructor() {
let documentListViewConfigJson = localStorage.getItem(
DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG
)

View File

@@ -1,7 +1,7 @@
import { DOCUMENT } from '@angular/common'
import { TestBed } from '@angular/core/testing'
import { EventManager } from '@angular/platform-browser'
import { DOCUMENT } from '@angular/core'
import { NgbModal, NgbModalModule } from '@ng-bootstrap/ng-bootstrap'
import { HotKeyService } from './hot-key.service'

View File

@@ -1,5 +1,4 @@
import { DOCUMENT } from '@angular/common'
import { Inject, Injectable } from '@angular/core'
import { DOCUMENT, Injectable, inject } from '@angular/core'
import { EventManager } from '@angular/platform-browser'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Observable } from 'rxjs'
@@ -15,17 +14,17 @@ export interface ShortcutOptions {
providedIn: 'root',
})
export class HotKeyService {
private eventManager = inject(EventManager)
private document = inject<Document>(DOCUMENT)
private modalService = inject(NgbModal)
private defaults: Partial<ShortcutOptions> = {
element: this.document,
}
private hotkeys: Map<string, string> = new Map()
constructor(
private eventManager: EventManager,
@Inject(DOCUMENT) private document: Document,
private modalService: NgbModal
) {
constructor() {
this.addShortcut({ keys: 'shift.?' }).subscribe(() => {
this.openHelpModal()
})

View File

@@ -176,22 +176,16 @@ describe('OpenDocumentsService', () => {
OPEN_DOCUMENT_SERVICE.DOCUMENTS,
JSON.stringify(documents)
)
const testOpenDocumentsService = new OpenDocumentsService(
null,
modalService
)
expect(testOpenDocumentsService.getOpenDocuments()).toHaveLength(
openDocumentsService.load()
expect(openDocumentsService.getOpenDocuments()).toHaveLength(
documents.length
)
})
it('should remove open documents from localStorage on error', () => {
sessionStorage.setItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS, 'hello world')
const testOpenDocumentsService = new OpenDocumentsService(
null,
modalService
)
expect(testOpenDocumentsService.getOpenDocuments()).toHaveLength(0)
openDocumentsService.load()
expect(openDocumentsService.getOpenDocuments()).toHaveLength(0)
expect(sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)).toBeNull()
})

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Observable, Subject, of } from 'rxjs'
import { first } from 'rxjs/operators'
@@ -11,12 +11,16 @@ import { DocumentService } from './rest/document.service'
providedIn: 'root',
})
export class OpenDocumentsService {
private documentService = inject(DocumentService)
private modalService = inject(NgbModal)
private MAX_OPEN_DOCUMENTS = 5
constructor(
private documentService: DocumentService,
private modalService: NgbModal
) {
constructor() {
this.load()
}
public load() {
if (sessionStorage.getItem(OPEN_DOCUMENT_SERVICE.DOCUMENTS)) {
try {
this.openDocuments = JSON.parse(

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
import {
@@ -12,9 +12,9 @@ import {
providedIn: 'root',
})
export class ProfileService {
private endpoint = 'profile'
private http = inject(HttpClient)
constructor(private http: HttpClient) {}
private endpoint = 'profile'
get(): Observable<PaperlessUserProfile> {
return this.http.get<PaperlessUserProfile>(

View File

@@ -1,3 +1,4 @@
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { ObjectWithId } from 'src/app/data/object-with-id'
import { PermissionsObject } from 'src/app/data/object-with-permissions'
@@ -7,7 +8,9 @@ export enum BulkEditObjectOperation {
SetPermissions = 'set_permissions',
Delete = 'delete',
}
@Injectable({
providedIn: 'root',
})
export abstract class AbstractNameFilterService<
T extends ObjectWithId,
> extends AbstractPaperlessService<T> {

View File

@@ -1,17 +1,21 @@
import { HttpClient, HttpParams } from '@angular/common/http'
import { inject, Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { map, publishReplay, refCount } from 'rxjs/operators'
import { ObjectWithId } from 'src/app/data/object-with-id'
import { Results } from 'src/app/data/results'
import { environment } from 'src/environments/environment'
@Injectable({
providedIn: 'root',
})
export abstract class AbstractPaperlessService<T extends ObjectWithId> {
protected baseUrl: string = environment.apiBaseUrl
protected http: HttpClient
protected resourceName: string
constructor(
protected http: HttpClient,
protected resourceName: string
) {}
constructor() {
this.http = inject(HttpClient)
}
protected getResourceUrl(id: number = null, action: string = null): string {
let url = `${this.baseUrl}${this.resourceName}/`

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Correspondent } from 'src/app/data/correspondent'
import { AbstractNameFilterService } from './abstract-name-filter-service'
@@ -7,7 +6,8 @@ import { AbstractNameFilterService } from './abstract-name-filter-service'
providedIn: 'root',
})
export class CorrespondentService extends AbstractNameFilterService<Correspondent> {
constructor(http: HttpClient) {
super(http, 'correspondents')
constructor() {
super()
this.resourceName = 'correspondents'
}
}

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { CustomField } from 'src/app/data/custom-field'
import { AbstractPaperlessService } from './abstract-paperless-service'
@@ -7,7 +6,8 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
providedIn: 'root',
})
export class CustomFieldsService extends AbstractPaperlessService<CustomField> {
constructor(http: HttpClient) {
super(http, 'custom_fields')
constructor() {
super()
this.resourceName = 'custom_fields'
}
}

View File

@@ -1,4 +1,4 @@
import { HttpClient, HttpParams } from '@angular/common/http'
import { HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { DocumentNote } from 'src/app/data/document-note'
@@ -8,8 +8,9 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
providedIn: 'root',
})
export class DocumentNotesService extends AbstractPaperlessService<DocumentNote> {
constructor(http: HttpClient) {
super(http, 'documents')
constructor() {
super()
this.resourceName = 'documents'
}
getNotes(documentId: number): Observable<DocumentNote[]> {

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { DocumentType } from 'src/app/data/document-type'
import { AbstractNameFilterService } from './abstract-name-filter-service'
@@ -7,7 +6,8 @@ import { AbstractNameFilterService } from './abstract-name-filter-service'
providedIn: 'root',
})
export class DocumentTypeService extends AbstractNameFilterService<DocumentType> {
constructor(http: HttpClient) {
super(http, 'document_types')
constructor() {
super()
this.resourceName = 'document_types'
}
}

View File

@@ -1,5 +1,4 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'
import { AuditLogEntry } from 'src/app/data/auditlog-entry'
@@ -41,6 +40,10 @@ export interface SelectionData {
providedIn: 'root',
})
export class DocumentService extends AbstractPaperlessService<Document> {
private permissionsService = inject(PermissionsService)
private settingsService = inject(SettingsService)
private customFieldService = inject(CustomFieldsService)
private _searchQuery: string
private _sortFields
@@ -55,13 +58,9 @@ export class DocumentService extends AbstractPaperlessService<Document> {
private customFields: CustomField[] = []
constructor(
http: HttpClient,
private permissionsService: PermissionsService,
private settingsService: SettingsService,
private customFieldService: CustomFieldsService
) {
super(http, 'documents')
constructor() {
super()
this.resourceName = 'documents'
this.reload()
}

View File

@@ -1,5 +1,4 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable, switchMap } from 'rxjs'
import { Group } from 'src/app/data/group'
import { PermissionsService } from '../permissions.service'
@@ -9,11 +8,11 @@ import { AbstractNameFilterService } from './abstract-name-filter-service'
providedIn: 'root',
})
export class GroupService extends AbstractNameFilterService<Group> {
constructor(
http: HttpClient,
private permissionService: PermissionsService
) {
super(http, 'groups')
private permissionService = inject(PermissionsService)
constructor() {
super()
this.resourceName = 'groups'
}
update(o: Group): Observable<Group> {

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
@@ -7,7 +7,7 @@ import { environment } from 'src/environments/environment'
providedIn: 'root',
})
export class LogService {
constructor(private http: HttpClient) {}
private http = inject(HttpClient)
list(): Observable<string[]> {
return this.http.get<string[]>(`${environment.apiBaseUrl}logs/`)

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { tap } from 'rxjs/operators'
import { MailAccount } from 'src/app/data/mail-account'
@@ -10,8 +9,9 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
export class MailAccountService extends AbstractPaperlessService<MailAccount> {
loading: boolean
constructor(http: HttpClient) {
super(http, 'mail_accounts')
constructor() {
super()
this.resourceName = 'mail_accounts'
}
private reload() {

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { tap } from 'rxjs/operators'
import { MailRule } from 'src/app/data/mail-rule'
@@ -10,8 +9,9 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
export class MailRuleService extends AbstractPaperlessService<MailRule> {
loading: boolean
constructor(http: HttpClient) {
super(http, 'mail_rules')
constructor() {
super()
this.resourceName = 'mail_rules'
}
private reload() {

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
@@ -12,7 +12,7 @@ export interface AppRemoteVersion {
providedIn: 'root',
})
export class RemoteVersionService {
constructor(private http: HttpClient) {}
private http = inject(HttpClient)
public checkForUpdates(): Observable<AppRemoteVersion> {
return this.http.get<AppRemoteVersion>(

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { inject, Injectable } from '@angular/core'
import { combineLatest, Observable } from 'rxjs'
import { tap } from 'rxjs/operators'
import { Results } from 'src/app/data/results'
@@ -12,14 +12,15 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
providedIn: 'root',
})
export class SavedViewService extends AbstractPaperlessService<SavedView> {
protected http: HttpClient
private settingsService = inject(SettingsService)
public loading: boolean = true
private savedViews: SavedView[] = []
constructor(
protected http: HttpClient,
private settingsService: SettingsService
) {
super(http, 'saved_views')
constructor() {
super()
this.resourceName = 'saved_views'
}
public list(

View File

@@ -1,5 +1,5 @@
import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { Correspondent } from 'src/app/data/correspondent'
import { CustomField } from 'src/app/data/custom-field'
@@ -37,12 +37,10 @@ export interface GlobalSearchResult {
providedIn: 'root',
})
export class SearchService {
public readonly searchResultObjectLimit: number = 3 // documents/views.py GlobalSearchView > OBJECT_LIMIT
private http = inject(HttpClient)
private settingsService = inject(SettingsService)
constructor(
private http: HttpClient,
private settingsService: SettingsService
) {}
public readonly searchResultObjectLimit: number = 3
autocomplete(term: string): Observable<string[]> {
return this.http.get<string[]>(

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { FileVersion, ShareLink } from 'src/app/data/share-link'
@@ -8,8 +7,9 @@ import { AbstractNameFilterService } from './abstract-name-filter-service'
providedIn: 'root',
})
export class ShareLinkService extends AbstractNameFilterService<ShareLink> {
constructor(http: HttpClient) {
super(http, 'share_links')
constructor() {
super()
this.resourceName = 'share_links'
}
getLinksForDocument(documentId: number): Observable<ShareLink[]> {

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
import { StoragePath } from 'src/app/data/storage-path'
@@ -8,8 +7,9 @@ import { AbstractNameFilterService } from './abstract-name-filter-service'
providedIn: 'root',
})
export class StoragePathService extends AbstractNameFilterService<StoragePath> {
constructor(http: HttpClient) {
super(http, 'storage_paths')
constructor() {
super()
this.resourceName = 'storage_paths'
}
public testPath(path: string, documentID: number): Observable<any> {

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Tag } from 'src/app/data/tag'
import { AbstractNameFilterService } from './abstract-name-filter-service'
@@ -7,7 +6,8 @@ import { AbstractNameFilterService } from './abstract-name-filter-service'
providedIn: 'root',
})
export class TagService extends AbstractNameFilterService<Tag> {
constructor(http: HttpClient) {
super(http, 'tags')
constructor() {
super()
this.resourceName = 'tags'
}
}

View File

@@ -1,5 +1,4 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable, switchMap } from 'rxjs'
import { User } from 'src/app/data/user'
import { PermissionsService } from '../permissions.service'
@@ -10,11 +9,11 @@ const endpoint = 'users'
providedIn: 'root',
})
export class UserService extends AbstractNameFilterService<User> {
constructor(
http: HttpClient,
private permissionService: PermissionsService
) {
super(http, endpoint)
private permissionService = inject(PermissionsService)
constructor() {
super()
this.resourceName = endpoint
}
update(o: User): Observable<User> {

View File

@@ -1,4 +1,3 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { tap } from 'rxjs'
import { Workflow } from 'src/app/data/workflow'
@@ -10,8 +9,9 @@ import { AbstractPaperlessService } from './abstract-paperless-service'
export class WorkflowService extends AbstractPaperlessService<Workflow> {
loading: boolean
constructor(http: HttpClient) {
super(http, 'workflows')
constructor() {
super()
this.resourceName = 'workflows'
}
public reload() {

View File

@@ -1,8 +1,8 @@
import { DOCUMENT } from '@angular/common'
import { HttpClient } from '@angular/common/http'
import {
DOCUMENT,
EventEmitter,
Inject,
inject,
Injectable,
LOCALE_ID,
Renderer2,
@@ -268,6 +268,15 @@ const ISO_LANGUAGE_OPTION: LanguageOption = {
providedIn: 'root',
})
export class SettingsService {
private document = inject(DOCUMENT)
private cookieService = inject(CookieService)
private meta = inject(Meta)
private localeId = inject(LOCALE_ID)
protected http = inject(HttpClient)
private toastService = inject(ToastService)
private permissionsService = inject(PermissionsService)
private customFieldsService = inject(CustomFieldsService)
protected baseUrl: string = environment.apiBaseUrl + 'ui_settings/'
private settings: Object = {}
@@ -293,17 +302,9 @@ export class SettingsService {
}
public displayFieldsInit: EventEmitter<boolean> = new EventEmitter()
constructor(
rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document,
private cookieService: CookieService,
private meta: Meta,
@Inject(LOCALE_ID) private localeId: string,
protected http: HttpClient,
private toastService: ToastService,
private permissionsService: PermissionsService,
private customFieldsService: CustomFieldsService
) {
constructor() {
const rendererFactory = inject(RendererFactory2)
this._renderer = rendererFactory.createRenderer(null, null)
}

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
import { SystemStatus } from '../data/system-status'
@@ -8,9 +8,9 @@ import { SystemStatus } from '../data/system-status'
providedIn: 'root',
})
export class SystemStatusService {
private endpoint = 'status'
private http = inject(HttpClient)
constructor(private http: HttpClient) {}
private endpoint = 'status'
get(): Observable<SystemStatus> {
return this.http.get<SystemStatus>(

View File

@@ -1,5 +1,5 @@
import { HttpClient } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable, Subject } from 'rxjs'
import { first, takeUntil } from 'rxjs/operators'
import {
@@ -13,6 +13,8 @@ import { environment } from 'src/environments/environment'
providedIn: 'root',
})
export class TasksService {
private http = inject(HttpClient)
private baseUrl: string = environment.apiBaseUrl
private endpoint: string = 'tasks'
@@ -48,8 +50,6 @@ export class TasksService {
return this.fileTasks.filter((t) => t.status == PaperlessTaskStatus.Failed)
}
constructor(private http: HttpClient) {}
public reload() {
if (this.loading) return
this.loading = true

View File

@@ -1,5 +1,5 @@
import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Observable } from 'rxjs'
import { environment } from 'src/environments/environment'
import { Document } from '../data/document'
@@ -9,7 +9,7 @@ import { Results } from '../data/results'
providedIn: 'root',
})
export class TrashService {
constructor(private http: HttpClient) {}
private http = inject(HttpClient)
public getTrash(page: number = 1): Observable<Results<Document>> {
const httpParams = new HttpParams().set('page', page.toString())

View File

@@ -1,5 +1,5 @@
import { HttpEventType } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Subscription } from 'rxjs'
import { DocumentService } from './rest/document.service'
import {
@@ -11,12 +11,10 @@ import {
providedIn: 'root',
})
export class UploadDocumentsService {
private uploadSubscriptions: Array<Subscription> = []
private documentService = inject(DocumentService)
private websocketStatusService = inject(WebsocketStatusService)
constructor(
private documentService: DocumentService,
private websocketStatusService: WebsocketStatusService
) {}
private uploadSubscriptions: Array<Subscription> = []
public uploadFile(file: File) {
let formData = new FormData()

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@angular/core'
import { Injectable, inject } from '@angular/core'
import { Subject } from 'rxjs'
import { environment } from 'src/environments/environment'
import { User } from '../data/user'
@@ -93,7 +93,7 @@ export class FileStatus {
providedIn: 'root',
})
export class WebsocketStatusService {
constructor(private settingsService: SettingsService) {}
private settingsService = inject(SettingsService)
private statusWebSocket: WebSocket