Merge branch 'dev' into feature-localization

This commit is contained in:
jonaswinkler 2020-12-31 15:59:47 +01:00
commit 1b8c4bb1a5
24 changed files with 82 additions and 39 deletions

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/jonaswinkler/paperless-ng.svg?branch=master)](https://travis-ci.org/jonaswinkler/paperless-ng) [![Build Status](https://travis-ci.com/jonaswinkler/paperless-ng.svg?branch=master)](https://travis-ci.com/jonaswinkler/paperless-ng)
[![Documentation Status](https://readthedocs.org/projects/paperless-ng/badge/?version=latest)](https://paperless-ng.readthedocs.io/en/latest/?badge=latest) [![Documentation Status](https://readthedocs.org/projects/paperless-ng/badge/?version=latest)](https://paperless-ng.readthedocs.io/en/latest/?badge=latest)
[![Gitter](https://badges.gitter.im/paperless-ng/community.svg)](https://gitter.im/paperless-ng/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Gitter](https://badges.gitter.im/paperless-ng/community.svg)](https://gitter.im/paperless-ng/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Docker Hub Pulls](https://img.shields.io/docker/pulls/jonaswinkler/paperless-ng.svg)](https://hub.docker.com/r/jonaswinkler/paperless-ng) [![Docker Hub Pulls](https://img.shields.io/docker/pulls/jonaswinkler/paperless-ng.svg)](https://hub.docker.com/r/jonaswinkler/paperless-ng)

View File

@ -1,4 +1,4 @@
bind = ['[::]:8000', 'localhost:8000'] bind = '0.0.0.0:8000'
backlog = 2048 backlog = 2048
workers = 3 workers = 3
worker_class = 'sync' worker_class = 'sync'

View File

@ -15,7 +15,7 @@ services:
POSTGRES_PASSWORD: paperless POSTGRES_PASSWORD: paperless
webserver: webserver:
image: jonaswinkler/paperless-ng:0.9.10 image: jonaswinkler/paperless-ng:0.9.11
restart: always restart: always
depends_on: depends_on:
- db - db

View File

@ -5,7 +5,7 @@ services:
restart: always restart: always
webserver: webserver:
image: jonaswinkler/paperless-ng:0.9.10 image: jonaswinkler/paperless-ng:0.9.11
restart: always restart: always
depends_on: depends_on:
- broker - broker

View File

@ -5,6 +5,13 @@
Changelog Changelog
********* *********
paperless-ng 0.9.11
###################
* Fixed an issue with the docker image not starting at all due to a configuration change of the web server.
paperless-ng 0.9.10 paperless-ng 0.9.10
################### ###################
@ -15,6 +22,7 @@ paperless-ng 0.9.10
* Other changes and additions * Other changes and additions
* Thanks to `zjean`_, paperless now publishes a webmanifest, which is useful for adding the application to home screens on mobile devices.
* The Paperless-ng logo now navigates to the dashboard. * The Paperless-ng logo now navigates to the dashboard.
* Filter for documents that don't have any correspondents, types or tags assigned. * Filter for documents that don't have any correspondents, types or tags assigned.
* Tags, types and correspondents are now sorted case insensitive. * Tags, types and correspondents are now sorted case insensitive.
@ -25,6 +33,8 @@ paperless-ng 0.9.10
* Added missing dependencies for Raspberry Pi builds. * Added missing dependencies for Raspberry Pi builds.
* Fixed an issue with plain text file consumption: Thumbnail generation failed due to missing fonts. * Fixed an issue with plain text file consumption: Thumbnail generation failed due to missing fonts.
* An issue with the search index reporting missing documents after bulk deletes was fixed. * An issue with the search index reporting missing documents after bulk deletes was fixed.
* Issue with the tag selector not clearing input correctly.
* The consumer used to stop working when encountering an incomplete classifier model file.
.. note:: .. note::
@ -956,6 +966,7 @@ bulk of the work on this big change.
* Initial release * Initial release
.. _zjean: https://github.com/zjean
.. _rYR79435: https://github.com/rYR79435 .. _rYR79435: https://github.com/rYR79435
.. _Michael Shamoon: https://github.com/shamoon .. _Michael Shamoon: https://github.com/shamoon
.. _jayme-github: http://github.com/jayme-github .. _jayme-github: http://github.com/jayme-github

View File

@ -39,7 +39,7 @@
#PAPERLESS_OCR_OUTPUT_TYPE=pdfa #PAPERLESS_OCR_OUTPUT_TYPE=pdfa
#PAPERLESS_OCR_PAGES=1 #PAPERLESS_OCR_PAGES=1
#PAPERLESS_OCR_IMAGE_DPI=300 #PAPERLESS_OCR_IMAGE_DPI=300
#PAPERLESS_OCR_USER_ARG={} #PAPERLESS_OCR_USER_ARGS={}
#PAPERLESS_CONVERT_MEMORY_LIMIT=0 #PAPERLESS_CONVERT_MEMORY_LIMIT=0
#PAPERLESS_CONVERT_TMPDIR=/var/tmp/paperless #PAPERLESS_CONVERT_TMPDIR=/var/tmp/paperless

View File

@ -33,7 +33,8 @@
"aot": true, "aot": true,
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
"src/assets" "src/assets",
"src/manifest.webmanifest"
], ],
"styles": [ "styles": [
"src/styles.scss" "src/styles.scss"
@ -100,7 +101,8 @@
"karmaConfig": "karma.conf.js", "karmaConfig": "karma.conf.js",
"assets": [ "assets": [
"src/favicon.ico", "src/favicon.ico",
"src/assets" "src/assets",
"src/manifest.webmanifest"
], ],
"styles": [ "styles": [
"src/styles.scss" "src/styles.scss"

View File

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
<div *ngIf="selectionModel.items" class="items"> <div *ngIf="selectionModel.items" class="items">
<ng-container *ngFor="let item of selectionModel.items | filter: filterText"> <ng-container *ngFor="let item of (editing ? selectionModel.itemsSorted : selectionModel.items) | filter: filterText">
<app-toggleable-dropdown-button *ngIf="allowSelectNone || item.id" [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)"></app-toggleable-dropdown-button> <app-toggleable-dropdown-button *ngIf="allowSelectNone || item.id" [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)"></app-toggleable-dropdown-button>
</ng-container> </ng-container>
</div> </div>

View File

@ -18,6 +18,18 @@ export class FilterableDropdownSelectionModel {
items: MatchingModel[] = [] items: MatchingModel[] = []
get itemsSorted(): MatchingModel[] {
return this.items.sort((a,b) => {
if (this.getNonTemporary(a.id) == ToggleableItemState.NotSelected && this.getNonTemporary(b.id) != ToggleableItemState.NotSelected) {
return 1
} else if (this.getNonTemporary(a.id) != ToggleableItemState.NotSelected && this.getNonTemporary(b.id) == ToggleableItemState.NotSelected) {
return -1
} else {
return a.name.localeCompare(b.name)
}
})
}
private selectionStates = new Map<number, ToggleableItemState>() private selectionStates = new Map<number, ToggleableItemState>()
private temporarySelectionStates = new Map<number, ToggleableItemState>() private temporarySelectionStates = new Map<number, ToggleableItemState>()
@ -69,6 +81,10 @@ export class FilterableDropdownSelectionModel {
} }
private getNonTemporary(id: number) {
return this.selectionStates.get(id) || ToggleableItemState.NotSelected
}
get(id: number) { get(id: number) {
return this.temporarySelectionStates.get(id) || ToggleableItemState.NotSelected return this.temporarySelectionStates.get(id) || ToggleableItemState.NotSelected
} }

View File

@ -5,7 +5,9 @@
<ng-select name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="displayValue" <ng-select name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="displayValue"
[multiple]="true" [multiple]="true"
[closeOnSelect]="false" [closeOnSelect]="false"
[clearSearchOnAdd]="true"
[disabled]="disabled" [disabled]="disabled"
[hideSelected]="true"
(change)="ngSelectChange()"> (change)="ngSelectChange()">
<ng-template ng-label-tmp let-item="item"> <ng-template ng-label-tmp let-item="item">

View File

@ -1,5 +1,5 @@
<div class="col p-2 h-100"> <div class="col p-2 h-100">
<div class="card h-100 shadow-sm" [class.card-selected]="selected"> <div class="card h-100 shadow-sm document-card" [class.card-selected]="selected">
<div class="border-bottom" [class.doc-img-background-selected]="selected"> <div class="border-bottom" [class.doc-img-background-selected]="selected">
<img class="card-img doc-img" [src]="getThumbUrl()" (click)="setSelected(!selected)"> <img class="card-img doc-img" [src]="getThumbUrl()" (click)="setSelected(!selected)">

View File

@ -78,8 +78,8 @@
</app-page-header> </app-page-header>
<div class="w-100 mb-2 mb-sm-4"> <div class="w-100 mb-2 mb-sm-4">
<app-filter-editor *ngIf="!isBulkEditing" [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor> <app-filter-editor [hidden]="isBulkEditing" [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor>
<app-bulk-editor *ngIf="isBulkEditing"></app-bulk-editor> <app-bulk-editor [hidden]="!isBulkEditing"></app-bulk-editor>
</div> </div>
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">

View File

@ -1,5 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FILTER_CORRESPONDENT } from 'src/app/data/filter-rule-type'; import { FILTER_CORRESPONDENT } from 'src/app/data/filter-rule-type';
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'; import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent';
@ -16,7 +15,6 @@ import { CorrespondentEditDialogComponent } from './correspondent-edit-dialog/co
export class CorrespondentListComponent extends GenericListComponent<PaperlessCorrespondent> { export class CorrespondentListComponent extends GenericListComponent<PaperlessCorrespondent> {
constructor(correspondentsService: CorrespondentService, modalService: NgbModal, constructor(correspondentsService: CorrespondentService, modalService: NgbModal,
private router: Router,
private list: DocumentListViewService private list: DocumentListViewService
) { ) {
super(correspondentsService,modalService,CorrespondentEditDialogComponent) super(correspondentsService,modalService,CorrespondentEditDialogComponent)
@ -27,9 +25,6 @@ export class CorrespondentListComponent extends GenericListComponent<PaperlessCo
} }
filterDocuments(object: PaperlessCorrespondent) { filterDocuments(object: PaperlessCorrespondent) {
this.list.documentListView.filter_rules = [ this.list.quickFilter([{rule_type: FILTER_CORRESPONDENT, value: object.id.toString()}])
{rule_type: FILTER_CORRESPONDENT, value: object.id.toString()}
]
this.router.navigate(["documents"])
} }
} }

View File

@ -1,5 +1,4 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FILTER_DOCUMENT_TYPE } from 'src/app/data/filter-rule-type'; import { FILTER_DOCUMENT_TYPE } from 'src/app/data/filter-rule-type';
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type'; import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
@ -16,7 +15,6 @@ import { DocumentTypeEditDialogComponent } from './document-type-edit-dialog/doc
export class DocumentTypeListComponent extends GenericListComponent<PaperlessDocumentType> { export class DocumentTypeListComponent extends GenericListComponent<PaperlessDocumentType> {
constructor(service: DocumentTypeService, modalService: NgbModal, constructor(service: DocumentTypeService, modalService: NgbModal,
private router: Router,
private list: DocumentListViewService private list: DocumentListViewService
) { ) {
super(service, modalService, DocumentTypeEditDialogComponent) super(service, modalService, DocumentTypeEditDialogComponent)
@ -28,9 +26,6 @@ export class DocumentTypeListComponent extends GenericListComponent<PaperlessDoc
filterDocuments(object: PaperlessDocumentType) { filterDocuments(object: PaperlessDocumentType) {
this.list.documentListView.filter_rules = [ this.list.quickFilter([{rule_type: FILTER_DOCUMENT_TYPE, value: object.id.toString()}])
{rule_type: FILTER_DOCUMENT_TYPE, value: object.id.toString()}
]
this.router.navigate(["documents"])
} }
} }

View File

@ -1,5 +1,4 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FILTER_HAS_TAG } from 'src/app/data/filter-rule-type'; import { FILTER_HAS_TAG } from 'src/app/data/filter-rule-type';
import { TAG_COLOURS, PaperlessTag } from 'src/app/data/paperless-tag'; import { TAG_COLOURS, PaperlessTag } from 'src/app/data/paperless-tag';
@ -16,7 +15,6 @@ import { TagEditDialogComponent } from './tag-edit-dialog/tag-edit-dialog.compon
export class TagListComponent extends GenericListComponent<PaperlessTag> { export class TagListComponent extends GenericListComponent<PaperlessTag> {
constructor(tagService: TagService, modalService: NgbModal, constructor(tagService: TagService, modalService: NgbModal,
private router: Router,
private list: DocumentListViewService private list: DocumentListViewService
) { ) {
super(tagService, modalService, TagEditDialogComponent) super(tagService, modalService, TagEditDialogComponent)
@ -27,14 +25,11 @@ export class TagListComponent extends GenericListComponent<PaperlessTag> {
} }
getDeleteMessage(object: PaperlessTag) { getDeleteMessage(object: PaperlessTag) {
return $localize`Do you really want to delete the tag "${object.name}"?` return $localize`Do you really want to delete the tag "${object.name}"?`
} }
filterDocuments(object: PaperlessTag) { filterDocuments(object: PaperlessTag) {
this.list.documentListView.filter_rules = [ this.list.quickFilter([{rule_type: FILTER_HAS_TAG, value: object.id.toString()}])
{rule_type: FILTER_HAS_TAG, value: object.id.toString()}
]
this.router.navigate(["documents"])
} }
} }

View File

@ -1,4 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { cloneFilterRules, FilterRule } from '../data/filter-rule'; import { cloneFilterRules, FilterRule } from '../data/filter-rule';
import { PaperlessDocument } from '../data/paperless-document'; import { PaperlessDocument } from '../data/paperless-document';
@ -155,6 +156,14 @@ export class DocumentListViewService {
sessionStorage.setItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG, JSON.stringify(this.documentListView)) sessionStorage.setItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG, JSON.stringify(this.documentListView))
} }
quickFilter(filterRules: FilterRule[]) {
this.savedView = null
this.view.filter_rules = filterRules
this.reduceSelectionToFilter()
this.saveDocumentListView()
this.router.navigate(["documents"])
}
getLastPage(): number { getLastPage(): number {
return Math.ceil(this.collectionSize / this.currentPageSize) return Math.ceil(this.collectionSize / this.currentPageSize)
} }
@ -240,7 +249,7 @@ export class DocumentListViewService {
} }
} }
constructor(private documentService: DocumentService, private settings: SettingsService) { constructor(private documentService: DocumentService, private settings: SettingsService, private router: Router) {
let documentListViewConfigJson = sessionStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG) let documentListViewConfigJson = sessionStorage.getItem(DOCUMENT_LIST_SERVICE.CURRENT_VIEW_CONFIG)
if (documentListViewConfigJson) { if (documentListViewConfigJson) {
try { try {

View File

@ -2,5 +2,5 @@ export const environment = {
production: true, production: true,
apiBaseUrl: "/api/", apiBaseUrl: "/api/",
appTitle: "Paperless-ng", appTitle: "Paperless-ng",
version: "0.9.10" version: "0.9.11"
}; };

View File

@ -5,6 +5,8 @@
<title>Paperless-ng</title> <title>Paperless-ng</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#17541f" />
<link rel="manifest" href="manifest.webmanifest">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
</head> </head>
<body> <body>

View File

@ -0,0 +1,14 @@
{
"background_color": "white",
"description": "A supercharged version of paperless: scan, index and archive all your physical documents",
"display": "fullscreen",
"icons": [
{
"src": "favicon.ico",
"sizes": "128x128"
}
],
"name": "Paperless NG",
"short_name": "Paperless NG",
"start_url": "/"
}

View File

@ -158,7 +158,7 @@ class Consumer(LoggingMixin):
try: try:
classifier = DocumentClassifier() classifier = DocumentClassifier()
classifier.reload() classifier.reload()
except (FileNotFoundError, IncompatibleClassifierVersionError) as e: except (OSError, EOFError, IncompatibleClassifierVersionError) as e:
self.log( self.log(
"warning", "warning",
f"Cannot classify documents: {e}.") f"Cannot classify documents: {e}.")

View File

@ -73,7 +73,7 @@ class Command(Renderable, BaseCommand):
classifier = DocumentClassifier() classifier = DocumentClassifier()
try: try:
classifier.reload() classifier.reload()
except (FileNotFoundError, IncompatibleClassifierVersionError) as e: except (OSError, EOFError, IncompatibleClassifierVersionError) as e:
logging.getLogger(__name__).warning( logging.getLogger(__name__).warning(
f"Cannot classify documents: {e}.") f"Cannot classify documents: {e}.")
classifier = None classifier = None

View File

@ -35,9 +35,9 @@ def train_classifier():
try: try:
# load the classifier, since we might not have to train it again. # load the classifier, since we might not have to train it again.
classifier.reload() classifier.reload()
except (FileNotFoundError, IncompatibleClassifierVersionError): except (OSError, EOFError, IncompatibleClassifierVersionError):
# This is what we're going to fix here. # This is what we're going to fix here.
pass classifier = DocumentClassifier()
try: try:
if classifier.train(): if classifier.train():

View File

@ -12,7 +12,9 @@
<meta name="full_name" content="{{full_name}}"> <meta name="full_name" content="{{full_name}}">
<meta name="cookie_prefix" content="{{cookie_prefix}}"> <meta name="cookie_prefix" content="{{cookie_prefix}}">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="{% static styles_css %}"></head> <link rel="manifest" href="{% static 'frontend/manifest.webmanifest' %}">
<link rel="stylesheet" href="{% static styles_css %}">
</head>
<body> <body>
<app-root>Loading...</app-root> <app-root>Loading...</app-root>
<script src="{% static runtime_js %}" defer></script> <script src="{% static runtime_js %}" defer></script>

View File

@ -1 +1 @@
__version__ = (0, 9, 10) __version__ = (0, 9, 11)