mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Merge branch 'dev' into feature-websockets-status
This commit is contained in:
@@ -27,6 +27,8 @@ export class DocumentListViewService {
|
||||
currentPage = 1
|
||||
currentPageSize: number = this.settings.get(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
|
||||
collectionSize: number
|
||||
rangeSelectionAnchorIndex: number
|
||||
lastRangeSelectionToIndex: number
|
||||
|
||||
/**
|
||||
* This is the current config for the document list. The service will always remember the last settings used for the document list.
|
||||
@@ -108,6 +110,7 @@ export class DocumentListViewService {
|
||||
if (onFinish) {
|
||||
onFinish()
|
||||
}
|
||||
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
|
||||
this.isReloading = false
|
||||
},
|
||||
error => {
|
||||
@@ -218,6 +221,7 @@ export class DocumentListViewService {
|
||||
|
||||
selectNone() {
|
||||
this.selected.clear()
|
||||
this.rangeSelectionAnchorIndex = this.lastRangeSelectionToIndex = null
|
||||
}
|
||||
|
||||
reduceSelectionToFilter() {
|
||||
@@ -249,14 +253,39 @@ export class DocumentListViewService {
|
||||
return this.selected.has(d.id)
|
||||
}
|
||||
|
||||
setSelected(d: PaperlessDocument, value: boolean) {
|
||||
if (value) {
|
||||
this.selected.add(d.id)
|
||||
} else if (!value) {
|
||||
this.selected.delete(d.id)
|
||||
toggleSelected(d: PaperlessDocument): void {
|
||||
if (this.selected.has(d.id)) this.selected.delete(d.id)
|
||||
else this.selected.add(d.id)
|
||||
this.rangeSelectionAnchorIndex = this.documentIndexInCurrentView(d.id)
|
||||
this.lastRangeSelectionToIndex = null
|
||||
}
|
||||
|
||||
selectRangeTo(d: PaperlessDocument) {
|
||||
if (this.rangeSelectionAnchorIndex !== null) {
|
||||
const documentToIndex = this.documentIndexInCurrentView(d.id)
|
||||
const fromIndex = Math.min(this.rangeSelectionAnchorIndex, documentToIndex)
|
||||
const toIndex = Math.max(this.rangeSelectionAnchorIndex, documentToIndex)
|
||||
|
||||
if (this.lastRangeSelectionToIndex !== null) {
|
||||
// revert the old selection
|
||||
this.documents.slice(Math.min(this.rangeSelectionAnchorIndex, this.lastRangeSelectionToIndex), Math.max(this.rangeSelectionAnchorIndex, this.lastRangeSelectionToIndex) + 1).forEach(d => {
|
||||
this.selected.delete(d.id)
|
||||
})
|
||||
}
|
||||
|
||||
this.documents.slice(fromIndex, toIndex + 1).forEach(d => {
|
||||
this.selected.add(d.id)
|
||||
})
|
||||
this.lastRangeSelectionToIndex = documentToIndex
|
||||
} else { // e.g. shift key but was first click
|
||||
this.toggleSelected(d)
|
||||
}
|
||||
}
|
||||
|
||||
documentIndexInCurrentView(documentID: number): number {
|
||||
return this.documents.map(d => d.id).indexOf(documentID)
|
||||
}
|
||||
|
||||
constructor(private documentService: DocumentService, private settings: SettingsService, private router: Router) {
|
||||
let documentListViewConfigJson = sessionStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG)
|
||||
if (documentListViewConfigJson) {
|
||||
|
14
src-ui/src/app/services/rest/abstract-name-filter-service.ts
Normal file
14
src-ui/src/app/services/rest/abstract-name-filter-service.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { ObjectWithId } from 'src/app/data/object-with-id'
|
||||
import { AbstractPaperlessService } from './abstract-paperless-service'
|
||||
|
||||
export abstract class AbstractNameFilterService<T extends ObjectWithId> extends AbstractPaperlessService<T> {
|
||||
|
||||
listFiltered(page?: number, pageSize?: number, sortField?: string, sortReverse?: boolean, nameFilter?: string) {
|
||||
let params = {}
|
||||
if (nameFilter) {
|
||||
params = {'name__icontains': nameFilter}
|
||||
}
|
||||
return this.list(page, pageSize, sortField, sortReverse, params)
|
||||
}
|
||||
|
||||
}
|
@@ -1,12 +1,12 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent';
|
||||
import { AbstractPaperlessService } from './abstract-paperless-service';
|
||||
import { AbstractNameFilterService } from './abstract-name-filter-service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CorrespondentService extends AbstractPaperlessService<PaperlessCorrespondent> {
|
||||
export class CorrespondentService extends AbstractNameFilterService<PaperlessCorrespondent> {
|
||||
|
||||
constructor(http: HttpClient) {
|
||||
super(http, 'correspondents')
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
|
||||
import { AbstractPaperlessService } from './abstract-paperless-service';
|
||||
import { AbstractNameFilterService } from './abstract-name-filter-service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DocumentTypeService extends AbstractPaperlessService<PaperlessDocumentType> {
|
||||
export class DocumentTypeService extends AbstractNameFilterService<PaperlessDocumentType> {
|
||||
|
||||
constructor(http: HttpClient) {
|
||||
super(http, 'document_types')
|
||||
|
@@ -28,7 +28,11 @@ export class SearchService {
|
||||
}
|
||||
return this.http.get<SearchResult>(`${environment.apiBaseUrl}search/`, {params: httpParams}).pipe(
|
||||
map(result => {
|
||||
result.results.forEach(hit => this.documentService.addObservablesToDocument(hit.document))
|
||||
result.results.forEach(hit => {
|
||||
if (hit.document) {
|
||||
this.documentService.addObservablesToDocument(hit.document)
|
||||
}
|
||||
})
|
||||
return result
|
||||
})
|
||||
)
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PaperlessTag } from 'src/app/data/paperless-tag';
|
||||
import { AbstractPaperlessService } from './abstract-paperless-service';
|
||||
import { AbstractNameFilterService } from './abstract-name-filter-service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TagService extends AbstractPaperlessService<PaperlessTag> {
|
||||
export class TagService extends AbstractNameFilterService<PaperlessTag> {
|
||||
|
||||
constructor(http: HttpClient) {
|
||||
super(http, 'tags')
|
||||
|
@@ -1,5 +1,7 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
|
||||
import { Meta } from '@angular/platform-browser';
|
||||
import { CookieService } from 'ngx-cookie-service';
|
||||
|
||||
export interface PaperlessSettings {
|
||||
key: string
|
||||
@@ -7,12 +9,21 @@ export interface PaperlessSettings {
|
||||
default: any
|
||||
}
|
||||
|
||||
export interface LanguageOption {
|
||||
code: string,
|
||||
name: string,
|
||||
englishName?: string
|
||||
}
|
||||
|
||||
export const SETTINGS_KEYS = {
|
||||
BULK_EDIT_CONFIRMATION_DIALOGS: 'general-settings:bulk-edit:confirmation-dialogs',
|
||||
BULK_EDIT_APPLY_ON_CLOSE: 'general-settings:bulk-edit:apply-on-close',
|
||||
DOCUMENT_LIST_SIZE: 'general-settings:documentListSize',
|
||||
DARK_MODE_USE_SYSTEM: 'general-settings:dark-mode:use-system',
|
||||
DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled'
|
||||
DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled',
|
||||
USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer',
|
||||
DATE_LOCALE: 'general-settings:date-display:date-locale',
|
||||
DATE_FORMAT: 'general-settings:date-display:date-format'
|
||||
}
|
||||
|
||||
const SETTINGS: PaperlessSettings[] = [
|
||||
@@ -20,7 +31,10 @@ const SETTINGS: PaperlessSettings[] = [
|
||||
{key: SETTINGS_KEYS.BULK_EDIT_APPLY_ON_CLOSE, type: "boolean", default: false},
|
||||
{key: SETTINGS_KEYS.DOCUMENT_LIST_SIZE, type: "number", default: 50},
|
||||
{key: SETTINGS_KEYS.DARK_MODE_USE_SYSTEM, type: "boolean", default: true},
|
||||
{key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}
|
||||
{key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false},
|
||||
{key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false},
|
||||
{key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""},
|
||||
{key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}
|
||||
]
|
||||
|
||||
@Injectable({
|
||||
@@ -32,7 +46,9 @@ export class SettingsService {
|
||||
|
||||
constructor(
|
||||
private rendererFactory: RendererFactory2,
|
||||
@Inject(DOCUMENT) private document
|
||||
@Inject(DOCUMENT) private document,
|
||||
private cookieService: CookieService,
|
||||
private meta: Meta
|
||||
) {
|
||||
this.renderer = rendererFactory.createRenderer(null, null);
|
||||
|
||||
@@ -53,6 +69,35 @@ export class SettingsService {
|
||||
|
||||
}
|
||||
|
||||
getLanguageOptions(): LanguageOption[] {
|
||||
return [
|
||||
{code: "en-US", name: $localize`English (US)`, englishName: "English (US)"},
|
||||
{code: "de", name: $localize`German`, englishName: "German"},
|
||||
{code: "nl", name: $localize`Dutch`, englishName: "Dutch"},
|
||||
{code: "fr", name: $localize`French`, englishName: "French"}
|
||||
]
|
||||
}
|
||||
|
||||
private getLanguageCookieName() {
|
||||
let prefix = ""
|
||||
if (this.meta.getTag('name=cookie_prefix')) {
|
||||
prefix = this.meta.getTag('name=cookie_prefix').content
|
||||
}
|
||||
return `${prefix || ''}django_language`
|
||||
}
|
||||
|
||||
getLanguage(): string {
|
||||
return this.cookieService.get(this.getLanguageCookieName())
|
||||
}
|
||||
|
||||
setLanguage(language: string) {
|
||||
if (language) {
|
||||
this.cookieService.set(this.getLanguageCookieName(), language)
|
||||
} else {
|
||||
this.cookieService.delete(this.getLanguageCookieName())
|
||||
}
|
||||
}
|
||||
|
||||
get(key: string): any {
|
||||
let setting = SETTINGS.find(s => s.key == key)
|
||||
|
||||
|
Reference in New Issue
Block a user