Merge branch 'dev' into feature/dark-mode

This commit is contained in:
Michael Shamoon 2020-12-28 14:28:53 -08:00 committed by GitHub
commit e6164eb1ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 138 additions and 74 deletions

View File

@ -9,6 +9,7 @@ RUN apt-get update \
&& apt-get -y --no-install-recommends install \
build-essential \
curl \
file \
fonts-liberation \
ghostscript \
gnupg \

View File

@ -5,7 +5,7 @@ import { Observable } from 'rxjs';
import { MATCHING_ALGORITHMS } from 'src/app/data/matching-model';
import { ObjectWithId } from 'src/app/data/object-with-id';
import { AbstractPaperlessService } from 'src/app/services/rest/abstract-paperless-service';
import { Toast, ToastService } from 'src/app/services/toast.service';
import { ToastService } from 'src/app/services/toast.service';
@Directive()
export abstract class EditDialogComponent<T extends ObjectWithId> implements OnInit {
@ -13,8 +13,7 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
constructor(
private service: AbstractPaperlessService<T>,
private activeModal: NgbActiveModal,
private toastService: ToastService,
private entityName: string) { }
private toastService: ToastService) { }
@Input()
dialogMode: string = 'create'
@ -35,12 +34,24 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
}
}
getCreateTitle() {
return $localize`Create new item`
}
getEditTitle() {
return $localize`Edit item`
}
getSaveErrorMessage(error: string) {
return $localize`Could not save element: ${error}`
}
getTitle() {
switch (this.dialogMode) {
case 'create':
return "Create new " + this.entityName
return this.getCreateTitle()
case 'edit':
return "Edit " + this.entityName
return this.getEditTitle()
default:
break;
}
@ -66,7 +77,7 @@ export abstract class EditDialogComponent<T extends ObjectWithId> implements OnI
this.activeModal.close()
this.success.emit(result)
}, error => {
this.toastService.showToast(Toast.makeError(`Could not save ${this.entityName}: ${error.error.name}`))
this.toastService.showError(this.getSaveErrorMessage(error.error.name))
})
}

View File

@ -2,7 +2,7 @@ import { HttpEventType } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
import { DocumentService } from 'src/app/services/rest/document.service';
import { Toast, ToastService } from 'src/app/services/toast.service';
import { ToastService } from 'src/app/services/toast.service';
interface UploadStatus {
@ -60,7 +60,7 @@ export class UploadFileWidgetComponent implements OnInit {
} else if (event.type == HttpEventType.Response) {
this.uploadStatus.splice(this.uploadStatus.indexOf(uploadStatusObject), 1)
this.completedFiles += 1
this.toastService.showToast(Toast.make("Information", $localize`The document has been uploaded and will be processed by the consumer shortly.`))
this.toastService.showInfo($localize`The document has been uploaded and will be processed by the consumer shortly.`)
}
}, error => {
@ -68,11 +68,11 @@ export class UploadFileWidgetComponent implements OnInit {
this.completedFiles += 1
switch (error.status) {
case 400: {
this.toastService.showToast(Toast.makeError($localize`There was an error while uploading the document: ${error.error.document}`))
this.toastService.showInfo($localize`There was an error while uploading the document: ${error.error.document}`)
break;
}
default: {
this.toastService.showToast(Toast.makeError($localize`An error has occurred while uploading the document. Sorry!`))
this.toastService.showInfo($localize`An error has occurred while uploading the document. Sorry!`)
break;
}
}

View File

@ -14,6 +14,7 @@ import { OpenDocumentsService } from 'src/app/services/open-documents.service';
import { ConfirmDialogComponent } from 'src/app/components/common/confirm-dialog/confirm-dialog.component';
import { ChangedItems, FilterableDropdownSelectionModel } from '../../common/filterable-dropdown/filterable-dropdown.component';
import { ToggleableItemState } from '../../common/filterable-dropdown/toggleable-dropdown-button/toggleable-dropdown-button.component';
import { MatchingModel } from 'src/app/data/matching-model';
@Component({
selector: 'app-bulk-editor',
@ -88,15 +89,40 @@ export class BulkEditorComponent {
})
}
private _localizeList(items: MatchingModel[]) {
if (items.length == 0) {
return ""
} else if (items.length == 1) {
return items[0].name
} else if (items.length == 2) {
return $localize`${items[0].name} and ${items[1].name}`
} else {
let list = items.slice(0, items.length - 1).map(i => i.name).join($localize`, `)
return $localize`${list} and ${items[items.length - 1].name}`
}
}
setTags(changedTags: ChangedItems) {
if (changedTags.itemsToAdd.length == 0 && changedTags.itemsToRemove.length == 0) return
let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
modal.componentInstance.title = "Confirm Tags Assignment"
modal.componentInstance.message = `This operation will modify some tags on all ${this.list.selected.size} selected document(s).`
modal.componentInstance.title = $localize`Confirm tags assignment`
if (changedTags.itemsToAdd.length == 1 && changedTags.itemsToRemove.length == 0) {
let tag = changedTags.itemsToAdd[0]
modal.componentInstance.message = $localize`This operation will add the tag ${tag.name} to all ${this.list.selected.size} selected document(s).`
} else if (changedTags.itemsToAdd.length > 1 && changedTags.itemsToRemove.length == 0) {
modal.componentInstance.message = $localize`This operation will add the tags ${this._localizeList(changedTags.itemsToAdd)} to all ${this.list.selected.size} selected document(s).`
} else if (changedTags.itemsToAdd.length == 0 && changedTags.itemsToRemove.length == 1) {
let tag = changedTags.itemsToAdd[0]
modal.componentInstance.message = $localize`This operation will remove the tag ${tag.name} from all ${this.list.selected.size} selected document(s).`
} else if (changedTags.itemsToAdd.length == 0 && changedTags.itemsToRemove.length > 1) {
modal.componentInstance.message = $localize`This operation will remove the tags ${this._localizeList(changedTags.itemsToRemove)} from all ${this.list.selected.size} selected document(s).`
} else {
modal.componentInstance.message = $localize`This operation will add the tags ${this._localizeList(changedTags.itemsToAdd)} and remove the tags ${this._localizeList(changedTags.itemsToRemove)} on all ${this.list.selected.size} selected document(s).`
}
modal.componentInstance.btnClass = "btn-warning"
modal.componentInstance.btnCaption = "Confirm"
modal.componentInstance.btnCaption = $localize`Confirm`
modal.componentInstance.confirmClicked.subscribe(() => {
this.executeBulkOperation('modify_tags', {"add_tags": changedTags.itemsToAdd.map(t => t.id), "remove_tags": changedTags.itemsToRemove.map(t => t.id)}).subscribe(
response => {
@ -111,18 +137,17 @@ export class BulkEditorComponent {
if (changedCorrespondents.itemsToAdd.length == 0 && changedCorrespondents.itemsToRemove.length == 0) return
let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
modal.componentInstance.title = "Confirm Correspondent Assignment"
let correspondent
let messageFragment = 'remove all correspondents from'
if (changedCorrespondents && changedCorrespondents.itemsToAdd.length > 0) {
correspondent = changedCorrespondents.itemsToAdd[0]
messageFragment = `assign the correspondent ${correspondent.name} to`
modal.componentInstance.title = $localize`Confirm correspondent assignment`
let correspondent = changedCorrespondents.itemsToAdd.length > 0 ? changedCorrespondents.itemsToAdd[0] : null
if (correspondent) {
modal.componentInstance.message = $localize`This operation will assign the correspondent ${correspondent.name} to all ${this.list.selected.size} selected document(s).`
} else {
modal.componentInstance.message = $localize`This operation will remove the correspondent from all ${this.list.selected.size} selected document(s).`
}
modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).`
modal.componentInstance.btnClass = "btn-warning"
modal.componentInstance.btnCaption = "Confirm"
modal.componentInstance.btnCaption = $localize`Confirm`
modal.componentInstance.confirmClicked.subscribe(() => {
this.executeBulkOperation('set_correspondent', {"correspondent": correspondent ? correspondent.id : null}).subscribe(
this.executeBulkOperation('set_correspondent', {"correspondent": correspondent?.id}).subscribe(
response => {
this.correspondentService.clearCache()
modal.close()
@ -135,18 +160,17 @@ export class BulkEditorComponent {
if (changedDocumentTypes.itemsToAdd.length == 0 && changedDocumentTypes.itemsToRemove.length == 0) return
let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
modal.componentInstance.title = "Confirm Document Type Assignment"
let documentType
let messageFragment = 'remove all document types from'
if (changedDocumentTypes && changedDocumentTypes.itemsToAdd.length > 0) {
documentType = changedDocumentTypes.itemsToAdd[0]
messageFragment = `assign the document type ${documentType.name} to`
modal.componentInstance.title = $localize`Confirm document type assignment`
let documentType = changedDocumentTypes.itemsToAdd.length > 0 ? changedDocumentTypes.itemsToAdd[0] : null
if (documentType) {
modal.componentInstance.message = $localize`This operation will assign the document type ${documentType.name} to all ${this.list.selected.size} selected document(s).`
} else {
modal.componentInstance.message = $localize`This operation will remove the document type from all ${this.list.selected.size} selected document(s).`
}
modal.componentInstance.message = `This operation will ${messageFragment} all ${this.list.selected.size} selected document(s).`
modal.componentInstance.btnClass = "btn-warning"
modal.componentInstance.btnCaption = "Confirm"
modal.componentInstance.btnCaption = $localize`Confirm`
modal.componentInstance.confirmClicked.subscribe(() => {
this.executeBulkOperation('set_document_type', {"document_type": documentType ? documentType.id : null}).subscribe(
this.executeBulkOperation('set_document_type', {"document_type": documentType?.id}).subscribe(
response => {
this.documentService.clearCache()
modal.close()
@ -158,11 +182,11 @@ export class BulkEditorComponent {
applyDelete() {
let modal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
modal.componentInstance.delayConfirm(5)
modal.componentInstance.title = "Delete confirm"
modal.componentInstance.messageBold = `This operation will permanently delete all ${this.list.selected.size} selected document(s).`
modal.componentInstance.message = `This operation cannot be undone.`
modal.componentInstance.title = $localize`Delete confirm`
modal.componentInstance.messageBold = $localize`This operation will permanently delete all ${this.list.selected.size} selected document(s).`
modal.componentInstance.message = $localize`This operation cannot be undone.`
modal.componentInstance.btnClass = "btn-danger"
modal.componentInstance.btnCaption = "Delete document(s)"
modal.componentInstance.btnCaption = $localize`Delete document(s)`
modal.componentInstance.confirmClicked.subscribe(() => {
this.executeBulkOperation("delete", {}).subscribe(
response => {

View File

@ -81,7 +81,7 @@ export class DocumentListComponent implements OnInit {
saveViewConfig() {
this.savedViewService.update(this.list.savedView).subscribe(result => {
this.toastService.showToast(Toast.make("Information", $localize`View "${this.list.savedView.name}" saved successfully.`))
this.toastService.showInfo($localize`View "${this.list.savedView.name}" saved successfully.`)
})
}
@ -100,7 +100,7 @@ export class DocumentListComponent implements OnInit {
}
this.savedViewService.create(savedView).subscribe(() => {
modal.close()
this.toastService.showToast(Toast.make("Information", $localize`View "${savedView.name}" created successfully.`))
this.toastService.showInfo($localize`View "${savedView.name}" created successfully.`)
})
})
}

View File

@ -14,7 +14,19 @@ import { ToastService } from 'src/app/services/toast.service';
export class CorrespondentEditDialogComponent extends EditDialogComponent<PaperlessCorrespondent> {
constructor(service: CorrespondentService, activeModal: NgbActiveModal, toastService: ToastService) {
super(service, activeModal, toastService, 'correspondent')
super(service, activeModal, toastService)
}
getCreateTitle() {
return $localize`Create new correspondent`
}
getEditTitle() {
return $localize`Edit correspondent`
}
getSaveErrorMessage(error: string) {
return $localize`Could not save correspondent: ${error}`
}
getForm(): FormGroup {

View File

@ -22,8 +22,8 @@ export class CorrespondentListComponent extends GenericListComponent<PaperlessCo
super(correspondentsService,modalService,CorrespondentEditDialogComponent)
}
getObjectName(object: PaperlessCorrespondent) {
return `correspondent '${object.name}'`
getDeleteMessage(object: PaperlessCorrespondent) {
return $localize`Do you really want to delete the correspondent ${object.name}?`
}
filterDocuments(object: PaperlessCorrespondent) {

View File

@ -14,7 +14,19 @@ import { ToastService } from 'src/app/services/toast.service';
export class DocumentTypeEditDialogComponent extends EditDialogComponent<PaperlessDocumentType> {
constructor(service: DocumentTypeService, activeModal: NgbActiveModal, toastService: ToastService) {
super(service, activeModal, toastService, 'document type')
super(service, activeModal, toastService)
}
getCreateTitle() {
return $localize`Create new document type`
}
getEditTitle() {
return $localize`Edit document type`
}
getSaveErrorMessage(error: string) {
return $localize`Could not save document type: ${error}`
}
getForm(): FormGroup {

View File

@ -22,10 +22,11 @@ export class DocumentTypeListComponent extends GenericListComponent<PaperlessDoc
super(service, modalService, DocumentTypeEditDialogComponent)
}
getObjectName(object: PaperlessDocumentType) {
return `document type '${object.name}'`
getDeleteMessage(object: PaperlessDocumentType) {
return $localize`Do you really want to delete the document type ${object.name}?`
}
filterDocuments(object: PaperlessDocumentType) {
this.list.documentListView.filter_rules = [
{rule_type: FILTER_DOCUMENT_TYPE, value: object.id.toString()}

View File

@ -84,14 +84,14 @@ export abstract class GenericListComponent<T extends ObjectWithId> implements On
})
}
getObjectName(object: T) {
return object.toString()
getDeleteMessage(object: T) {
return $localize`Do you really want to delete this element?`
}
openDeleteDialog(object: T) {
var activeModal = this.modalService.open(ConfirmDialogComponent, {backdrop: 'static'})
activeModal.componentInstance.title = $localize`Confirm delete`
activeModal.componentInstance.messageBold = $localize`Do you really want to delete ${this.getObjectName(object)}?`
activeModal.componentInstance.messageBold = this.getDeleteMessage(object)
activeModal.componentInstance.message = $localize`Associated documents will not be deleted.`
activeModal.componentInstance.btnClass = "btn-danger"
activeModal.componentInstance.btnCaption = $localize`Delete`

View File

@ -4,7 +4,7 @@ import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
import { GENERAL_SETTINGS } from 'src/app/data/storage-keys';
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
import { SavedViewService } from 'src/app/services/rest/saved-view.service';
import { Toast, ToastService } from 'src/app/services/toast.service';
import { ToastService } from 'src/app/services/toast.service';
import { AppViewService } from 'src/app/services/app-view.service';
@Component({
@ -54,7 +54,7 @@ export class SettingsComponent implements OnInit {
this.savedViewService.delete(savedView).subscribe(() => {
this.savedViewGroup.removeControl(savedView.id.toString())
this.savedViews.splice(this.savedViews.indexOf(savedView), 1)
this.toastService.showToast(Toast.make("Information", $localize`Saved view "${savedView.name} deleted.`))
this.toastService.showInfo($localize`Saved view "${savedView.name} deleted.`)
})
}
@ -72,7 +72,7 @@ export class SettingsComponent implements OnInit {
localStorage.setItem(GENERAL_SETTINGS.DARK_MODE_ENABLED, (this.settingsForm.value.darkModeEnabled == true).toString())
this.documentListViewService.updatePageSize()
this.appViewService.updateDarkModeSettings()
this.toastService.showToast(Toast.make("Information", $localize`Settings saved successfully.`))
this.toastService.showInfo($localize`Settings saved successfully.`)
}
saveSettings() {
@ -84,7 +84,7 @@ export class SettingsComponent implements OnInit {
this.savedViewService.patchMany(x).subscribe(s => {
this.saveLocalSettings()
}, error => {
this.toastService.showToast(Toast.makeError($localize`Error while storing settings on server: ${JSON.stringify(error.error)}`))
this.toastService.showError($localize`Error while storing settings on server: ${JSON.stringify(error.error)}`)
})
} else {
this.saveLocalSettings()

View File

@ -14,7 +14,19 @@ import { ToastService } from 'src/app/services/toast.service';
export class TagEditDialogComponent extends EditDialogComponent<PaperlessTag> {
constructor(service: TagService, activeModal: NgbActiveModal, toastService: ToastService) {
super(service, activeModal, toastService, 'tag')
super(service, activeModal, toastService)
}
getCreateTitle() {
return $localize`Create new tag`
}
getEditTitle() {
return $localize`Edit tag`
}
getSaveErrorMessage(error: string) {
return $localize`Could not save tag: ${error}`
}
getForm(): FormGroup {

View File

@ -26,8 +26,8 @@ export class TagListComponent extends GenericListComponent<PaperlessTag> {
return TAG_COLOURS.find(c => c.id == id)
}
getObjectName(object: PaperlessTag) {
return `tag '${object.name}'`
getDeleteMessage(object: PaperlessTag) {
return $localize`Do you really want to delete the tag ${object.name}?`
}
filterDocuments(object: PaperlessTag) {

View File

@ -1,30 +1,13 @@
import { Injectable } from '@angular/core';
import { Subject, zip } from 'rxjs';
export class Toast {
static make(title: string, content: string, classname?: string, delay?: number): Toast {
let t = new Toast()
t.title = title
t.content = content
t.classname = classname
if (delay) {
t.delay = delay
}
return t
}
static makeError(content: string) {
return Toast.make("Error", content, null, 10000)
}
export interface Toast {
title: string
classname: string
content: string
delay: number = 5000
delay: number
}
@ -39,11 +22,19 @@ export class ToastService {
private toastsSubject: Subject<Toast[]> = new Subject()
showToast(toast: Toast) {
show(toast: Toast) {
this.toasts.push(toast)
this.toastsSubject.next(this.toasts)
}
showError(content: string, delay: number = 10000) {
this.show({title: $localize`Error`, content: content, delay: delay})
}
showInfo(content: string, delay: number = 5000) {
this.show({title: $localize`Information`, content: content, delay: delay})
}
closeToast(toast: Toast) {
let index = this.toasts.findIndex(t => t == toast)
if (index > -1) {