mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-07-08 13:05:10 +00:00
Ok first real chunk of zoneless pngx
document list dashboard / widget frame stats
This commit is contained in:
+1
-1
@@ -67,11 +67,11 @@ export class StoragePathEditDialogComponent
|
||||
private testDocument: Document
|
||||
public testResult: string
|
||||
public testFailed: boolean = false
|
||||
public loading = false
|
||||
public testLoading = false
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.loading = false
|
||||
this.service = inject(StoragePathService)
|
||||
this.userService = inject(UserService)
|
||||
this.settingsService = inject(SettingsService)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, inject, Input } from '@angular/core'
|
||||
import { Component, inject, Input, signal } from '@angular/core'
|
||||
import { Tag } from 'src/app/data/tag'
|
||||
import {
|
||||
PermissionAction,
|
||||
@@ -16,16 +16,16 @@ export class TagComponent {
|
||||
private permissionsService = inject(PermissionsService)
|
||||
private tagService = inject(TagService)
|
||||
|
||||
private _tag: Tag
|
||||
private tagSignal = signal<Tag>(null)
|
||||
private _tagID: number
|
||||
|
||||
@Input()
|
||||
public set tag(tag: Tag) {
|
||||
this._tag = tag
|
||||
this.tagSignal.set(tag)
|
||||
}
|
||||
|
||||
public get tag(): Tag {
|
||||
return this._tag
|
||||
return this.tagSignal()
|
||||
}
|
||||
|
||||
@Input()
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DragDropModule,
|
||||
moveItemInArray,
|
||||
} from '@angular/cdk/drag-drop'
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { Component, inject, signal } from '@angular/core'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { TourNgBootstrap, TourService } from 'ngx-ui-tour-ng-bootstrap'
|
||||
@@ -47,7 +47,15 @@ export class DashboardComponent extends ComponentWithPermissions {
|
||||
private tourService = inject(TourService)
|
||||
private toastService = inject(ToastService)
|
||||
|
||||
public dashboardViews: SavedView[] = []
|
||||
private dashboardViewsSignal = signal<SavedView[]>([])
|
||||
|
||||
get dashboardViews(): SavedView[] {
|
||||
return this.dashboardViewsSignal()
|
||||
}
|
||||
|
||||
set dashboardViews(value: SavedView[]) {
|
||||
this.dashboardViewsSignal.set(value)
|
||||
}
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
|
||||
+18
-3
@@ -1,6 +1,6 @@
|
||||
import { DecimalPipe } from '@angular/common'
|
||||
import { HttpClient } from '@angular/common/http'
|
||||
import { Component, inject, OnDestroy, OnInit } from '@angular/core'
|
||||
import { Component, inject, OnDestroy, OnInit, signal } from '@angular/core'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import * as mimeTypeNames from 'mime-names'
|
||||
@@ -55,9 +55,24 @@ export class StatisticsWidgetComponent
|
||||
private websocketConnectionService = inject(WebsocketStatusService)
|
||||
private documentListViewService = inject(DocumentListViewService)
|
||||
|
||||
loading: boolean = false
|
||||
private loadingSignal = signal(false)
|
||||
private statisticsSignal = signal<Statistics>({})
|
||||
|
||||
statistics: Statistics = {}
|
||||
get loading(): boolean {
|
||||
return this.loadingSignal()
|
||||
}
|
||||
|
||||
set loading(value: boolean) {
|
||||
this.loadingSignal.set(value)
|
||||
}
|
||||
|
||||
get statistics(): Statistics {
|
||||
return this.statisticsSignal()
|
||||
}
|
||||
|
||||
set statistics(value: Statistics) {
|
||||
this.statisticsSignal.set(value)
|
||||
}
|
||||
|
||||
subscription: Subscription
|
||||
private unsubscribeNotifer: Subject<any> = new Subject()
|
||||
|
||||
@@ -16,13 +16,20 @@ export class WidgetFrameComponent
|
||||
{
|
||||
constructor() {
|
||||
super()
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
@Input()
|
||||
title: string
|
||||
|
||||
@Input()
|
||||
loading: boolean = false
|
||||
override set loading(value: boolean) {
|
||||
super.loading = value
|
||||
}
|
||||
|
||||
override get loading(): boolean {
|
||||
return super.loading
|
||||
}
|
||||
|
||||
@Input()
|
||||
draggable: any
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, OnDestroy } from '@angular/core'
|
||||
import { Directive, OnDestroy, signal } from '@angular/core'
|
||||
import { Subject } from 'rxjs'
|
||||
import { ComponentWithPermissions } from '../with-permissions/with-permissions.component'
|
||||
|
||||
@@ -7,8 +7,24 @@ export abstract class LoadingComponentWithPermissions
|
||||
extends ComponentWithPermissions
|
||||
implements OnDestroy
|
||||
{
|
||||
public loading: boolean = true
|
||||
public show: boolean = false
|
||||
private loadingSignal = signal(true)
|
||||
private showSignal = signal(false)
|
||||
|
||||
public get loading(): boolean {
|
||||
return this.loadingSignal()
|
||||
}
|
||||
|
||||
public set loading(value: boolean) {
|
||||
this.loadingSignal.set(value)
|
||||
}
|
||||
|
||||
public get show(): boolean {
|
||||
return this.showSignal()
|
||||
}
|
||||
|
||||
public set show(value: boolean) {
|
||||
this.showSignal.set(value)
|
||||
}
|
||||
|
||||
protected unsubscribeNotifier: Subject<any> = new Subject()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from '@angular/core'
|
||||
import { Injectable, inject, signal } from '@angular/core'
|
||||
import { ParamMap, Router, UrlTree } from '@angular/router'
|
||||
import { Observable, Subject, takeUntil } from 'rxjs'
|
||||
import {
|
||||
@@ -118,6 +118,7 @@ export class DocumentListViewService {
|
||||
isReloading: boolean = false
|
||||
initialized: boolean = false
|
||||
error: string = null
|
||||
private stateVersion = signal(0)
|
||||
|
||||
rangeSelectionAnchorIndex: number
|
||||
lastRangeSelectionToIndex: number
|
||||
@@ -132,6 +133,14 @@ export class DocumentListViewService {
|
||||
|
||||
private displayFieldsInitialized: boolean = false
|
||||
|
||||
private markChanged(): void {
|
||||
this.stateVersion.update((version) => version + 1)
|
||||
}
|
||||
|
||||
private trackState(): void {
|
||||
this.stateVersion()
|
||||
}
|
||||
|
||||
private restoreListViewState(savedState: unknown): ListViewState {
|
||||
const newState = this.defaultListViewState()
|
||||
|
||||
@@ -159,10 +168,12 @@ export class DocumentListViewService {
|
||||
}
|
||||
|
||||
get activeSavedViewId() {
|
||||
this.trackState()
|
||||
return this._activeSavedViewId
|
||||
}
|
||||
|
||||
get activeSavedViewTitle() {
|
||||
this.trackState()
|
||||
return this.activeListViewState.title
|
||||
}
|
||||
|
||||
@@ -191,6 +202,7 @@ export class DocumentListViewService {
|
||||
)
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
this.markChanged()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -243,6 +255,7 @@ export class DocumentListViewService {
|
||||
} else {
|
||||
this._activeSavedViewId = null
|
||||
}
|
||||
this.markChanged()
|
||||
}
|
||||
|
||||
activateSavedViewWithQueryParams(view: SavedView, queryParams: ParamMap) {
|
||||
@@ -267,6 +280,7 @@ export class DocumentListViewService {
|
||||
this.activeListViewState.displayFields = view.display_fields
|
||||
|
||||
this.reduceSelectionToFilter()
|
||||
this.markChanged()
|
||||
|
||||
if (!this.router.routerState.snapshot.url.includes('/view/')) {
|
||||
this.router.navigate(['view', view.id])
|
||||
@@ -297,6 +311,7 @@ export class DocumentListViewService {
|
||||
this.activeListViewState.sortField = newState.sortField
|
||||
this.activeListViewState.sortReverse = newState.sortReverse
|
||||
this.activeListViewState.currentPage = newState.currentPage
|
||||
this.markChanged()
|
||||
this.reload(null, paramsEmpty) // update the params if there aren't any
|
||||
}
|
||||
}
|
||||
@@ -305,6 +320,7 @@ export class DocumentListViewService {
|
||||
this.cancelPending()
|
||||
this.isReloading = true
|
||||
this.error = null
|
||||
this.markChanged()
|
||||
let activeListViewState = this.activeListViewState
|
||||
this.documentService
|
||||
.listFiltered(
|
||||
@@ -325,6 +341,7 @@ export class DocumentListViewService {
|
||||
activeListViewState.documents = result.results
|
||||
this.selectionData = resultWithSelectionData.selection_data ?? null
|
||||
this.syncSelectedToCurrentPage()
|
||||
this.markChanged()
|
||||
|
||||
if (updateQueryParams && !this._activeSavedViewId) {
|
||||
let base = ['/documents']
|
||||
@@ -343,12 +360,14 @@ export class DocumentListViewService {
|
||||
onFinish()
|
||||
}
|
||||
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
|
||||
this.markChanged()
|
||||
},
|
||||
error: (error) => {
|
||||
this.isReloading = false
|
||||
if (activeListViewState.currentPage != 1 && error.status == 404) {
|
||||
// this happens when applying a filter: the current page might not be available anymore due to the reduced result set.
|
||||
activeListViewState.currentPage = 1
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
} else if (
|
||||
activeListViewState.sortField.indexOf('custom_field') === 0 &&
|
||||
@@ -381,6 +400,7 @@ export class DocumentListViewService {
|
||||
errorMessage = error.error
|
||||
}
|
||||
this.error = errorMessage
|
||||
this.markChanged()
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -397,12 +417,14 @@ export class DocumentListViewService {
|
||||
if (resetPage) {
|
||||
this.activeListViewState.currentPage = 1
|
||||
}
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
this.reduceSelectionToFilter()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
get filterRules(): FilterRule[] {
|
||||
this.trackState()
|
||||
return this.activeListViewState.filterRules
|
||||
}
|
||||
|
||||
@@ -416,48 +438,58 @@ export class DocumentListViewService {
|
||||
|
||||
set sortField(field: string) {
|
||||
this.activeListViewState.sortField = field
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
get sortField(): string {
|
||||
this.trackState()
|
||||
return this.activeListViewState.sortField
|
||||
}
|
||||
|
||||
set sortReverse(reverse: boolean) {
|
||||
this.activeListViewState.sortReverse = reverse
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
get sortReverse(): boolean {
|
||||
this.trackState()
|
||||
return this.activeListViewState.sortReverse
|
||||
}
|
||||
|
||||
get collectionSize(): number {
|
||||
this.trackState()
|
||||
return this.activeListViewState.collectionSize
|
||||
}
|
||||
|
||||
get currentPage(): number {
|
||||
this.trackState()
|
||||
return this.activeListViewState.currentPage
|
||||
}
|
||||
|
||||
set currentPage(page: number) {
|
||||
if (this.activeListViewState.currentPage == page) return
|
||||
this.activeListViewState.currentPage = page
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
get documents(): Document[] {
|
||||
this.trackState()
|
||||
return this.activeListViewState.documents
|
||||
}
|
||||
|
||||
get selected(): Set<number> {
|
||||
this.trackState()
|
||||
return this.activeListViewState.selected
|
||||
}
|
||||
|
||||
get allSelected(): boolean {
|
||||
this.trackState()
|
||||
return this.activeListViewState.allSelected ?? false
|
||||
}
|
||||
|
||||
@@ -474,16 +506,19 @@ export class DocumentListViewService {
|
||||
setSort(field: string, reverse: boolean) {
|
||||
this.activeListViewState.sortField = field
|
||||
this.activeListViewState.sortReverse = reverse
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
set displayMode(mode: DisplayMode) {
|
||||
this.activeListViewState.displayMode = mode
|
||||
this.markChanged()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
get displayMode(): DisplayMode {
|
||||
this.trackState()
|
||||
const mode = this.activeListViewState.displayMode ?? DisplayMode.SMALL_CARDS
|
||||
if (mode === ('details' as any)) {
|
||||
// legacy
|
||||
@@ -494,11 +529,13 @@ export class DocumentListViewService {
|
||||
|
||||
set pageSize(size: number) {
|
||||
this.activeListViewState.pageSize = size
|
||||
this.markChanged()
|
||||
this.reload()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
get pageSize(): number {
|
||||
this.trackState()
|
||||
return (
|
||||
this.activeListViewState.pageSize ??
|
||||
this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
|
||||
@@ -506,6 +543,7 @@ export class DocumentListViewService {
|
||||
}
|
||||
|
||||
get displayFields(): DisplayField[] {
|
||||
this.trackState()
|
||||
return this.activeListViewState.displayFields ?? LIST_DEFAULT_DISPLAY_FIELDS
|
||||
}
|
||||
|
||||
@@ -517,6 +555,7 @@ export class DocumentListViewService {
|
||||
undefined
|
||||
)
|
||||
: fields
|
||||
this.markChanged()
|
||||
this.saveDocumentListView()
|
||||
}
|
||||
|
||||
@@ -540,6 +579,7 @@ export class DocumentListViewService {
|
||||
|
||||
quickFilter(filterRules: FilterRule[]) {
|
||||
this._activeSavedViewId = null
|
||||
this.markChanged()
|
||||
this.setFilterRules(filterRules)
|
||||
this.router.navigate(['documents'])
|
||||
}
|
||||
@@ -628,6 +668,7 @@ export class DocumentListViewService {
|
||||
this.activeListViewState.allSelected = false
|
||||
this.selected.clear()
|
||||
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
|
||||
this.markChanged()
|
||||
}
|
||||
|
||||
reduceSelectionToFilter() {
|
||||
@@ -644,6 +685,7 @@ export class DocumentListViewService {
|
||||
this.selected.delete(id)
|
||||
}
|
||||
}
|
||||
this.markChanged()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -651,6 +693,7 @@ export class DocumentListViewService {
|
||||
selectAll() {
|
||||
this.activeListViewState.allSelected = true
|
||||
this.syncSelectedToCurrentPage()
|
||||
this.markChanged()
|
||||
}
|
||||
|
||||
selectPage() {
|
||||
@@ -659,6 +702,7 @@ export class DocumentListViewService {
|
||||
this.documents.forEach((doc) => {
|
||||
this.selected.add(doc.id)
|
||||
})
|
||||
this.markChanged()
|
||||
}
|
||||
|
||||
isSelected(d: Document) {
|
||||
@@ -673,6 +717,7 @@ export class DocumentListViewService {
|
||||
else this.selected.add(d.id)
|
||||
this.rangeSelectionAnchorIndex = this.documentIndexInCurrentView(d.id)
|
||||
this.lastRangeSelectionToIndex = null
|
||||
this.markChanged()
|
||||
}
|
||||
|
||||
selectRangeTo(d: Document) {
|
||||
@@ -710,6 +755,7 @@ export class DocumentListViewService {
|
||||
this.selected.add(d.id)
|
||||
})
|
||||
this.lastRangeSelectionToIndex = documentToIndex
|
||||
this.markChanged()
|
||||
} else {
|
||||
// e.g. shift key but was first click
|
||||
this.toggleSelected(d)
|
||||
|
||||
Reference in New Issue
Block a user