mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Merge branch 'dev' into feature-localization
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| [](https://travis-ci.org/jonaswinkler/paperless-ng) | ||||
| [](https://travis-ci.com/jonaswinkler/paperless-ng) | ||||
| [](https://paperless-ng.readthedocs.io/en/latest/?badge=latest) | ||||
| [](https://gitter.im/paperless-ng/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||||
| [](https://hub.docker.com/r/jonaswinkler/paperless-ng) | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| bind = ['[::]:8000', 'localhost:8000'] | ||||
| bind = '0.0.0.0:8000' | ||||
| backlog = 2048 | ||||
| workers = 3 | ||||
| worker_class = 'sync' | ||||
|   | ||||
| @@ -15,7 +15,7 @@ services: | ||||
|       POSTGRES_PASSWORD: paperless | ||||
|  | ||||
|   webserver: | ||||
|     image: jonaswinkler/paperless-ng:0.9.10 | ||||
|     image: jonaswinkler/paperless-ng:0.9.11 | ||||
|     restart: always | ||||
|     depends_on: | ||||
|       - db | ||||
|   | ||||
| @@ -5,7 +5,7 @@ services: | ||||
|     restart: always | ||||
|  | ||||
|   webserver: | ||||
|     image: jonaswinkler/paperless-ng:0.9.10 | ||||
|     image: jonaswinkler/paperless-ng:0.9.11 | ||||
|     restart: always | ||||
|     depends_on: | ||||
|       - broker | ||||
|   | ||||
| @@ -5,6 +5,13 @@ | ||||
| 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 | ||||
| ################### | ||||
|  | ||||
| @@ -15,6 +22,7 @@ paperless-ng 0.9.10 | ||||
|  | ||||
| * 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. | ||||
|   * Filter for documents that don't have any correspondents, types or tags assigned. | ||||
|   * 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. | ||||
|   * 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. | ||||
|   * Issue with the tag selector not clearing input correctly. | ||||
|   * The consumer used to stop working when encountering an incomplete classifier model file. | ||||
|  | ||||
| .. note:: | ||||
|  | ||||
| @@ -956,6 +966,7 @@ bulk of the work on this big change. | ||||
|  | ||||
| * Initial release | ||||
|  | ||||
| .. _zjean: https://github.com/zjean | ||||
| .. _rYR79435: https://github.com/rYR79435 | ||||
| .. _Michael Shamoon: https://github.com/shamoon | ||||
| .. _jayme-github: http://github.com/jayme-github | ||||
|   | ||||
| @@ -39,7 +39,7 @@ | ||||
| #PAPERLESS_OCR_OUTPUT_TYPE=pdfa | ||||
| #PAPERLESS_OCR_PAGES=1 | ||||
| #PAPERLESS_OCR_IMAGE_DPI=300 | ||||
| #PAPERLESS_OCR_USER_ARG={} | ||||
| #PAPERLESS_OCR_USER_ARGS={} | ||||
| #PAPERLESS_CONVERT_MEMORY_LIMIT=0 | ||||
| #PAPERLESS_CONVERT_TMPDIR=/var/tmp/paperless | ||||
|  | ||||
|   | ||||
| @@ -33,7 +33,8 @@ | ||||
| 						"aot": true, | ||||
| 						"assets": [ | ||||
| 							"src/favicon.ico", | ||||
| 							"src/assets" | ||||
| 							"src/assets", | ||||
| 							"src/manifest.webmanifest" | ||||
| 						], | ||||
| 						"styles": [ | ||||
| 							"src/styles.scss" | ||||
| @@ -100,7 +101,8 @@ | ||||
| 						"karmaConfig": "karma.conf.js", | ||||
| 						"assets": [ | ||||
| 							"src/favicon.ico", | ||||
| 							"src/assets" | ||||
| 							"src/assets", | ||||
| 							"src/manifest.webmanifest" | ||||
| 						], | ||||
| 						"styles": [ | ||||
| 							"src/styles.scss" | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|         </div> | ||||
|       </div> | ||||
|       <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> | ||||
|         </ng-container> | ||||
|       </div> | ||||
|   | ||||
| @@ -18,6 +18,18 @@ export class FilterableDropdownSelectionModel { | ||||
|  | ||||
|   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 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) { | ||||
|     return this.temporarySelectionStates.get(id) || ToggleableItemState.NotSelected | ||||
|   } | ||||
|   | ||||
| @@ -5,7 +5,9 @@ | ||||
|     <ng-select name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="displayValue" | ||||
|       [multiple]="true" | ||||
|       [closeOnSelect]="false" | ||||
|       [clearSearchOnAdd]="true" | ||||
|       [disabled]="disabled" | ||||
|       [hideSelected]="true" | ||||
|       (change)="ngSelectChange()"> | ||||
|  | ||||
|       <ng-template ng-label-tmp let-item="item"> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <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"> | ||||
|       <img class="card-img doc-img" [src]="getThumbUrl()" (click)="setSelected(!selected)"> | ||||
|  | ||||
|   | ||||
| @@ -78,8 +78,8 @@ | ||||
| </app-page-header> | ||||
|  | ||||
| <div class="w-100 mb-2 mb-sm-4"> | ||||
|   <app-filter-editor *ngIf="!isBulkEditing" [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor> | ||||
|   <app-bulk-editor *ngIf="isBulkEditing"></app-bulk-editor> | ||||
|   <app-filter-editor [hidden]="isBulkEditing" [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor> | ||||
|   <app-bulk-editor [hidden]="!isBulkEditing"></app-bulk-editor> | ||||
| </div> | ||||
|  | ||||
| <div class="d-flex justify-content-between align-items-center"> | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { Component } from '@angular/core'; | ||||
| import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||||
| import { FILTER_CORRESPONDENT } from 'src/app/data/filter-rule-type'; | ||||
| 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> { | ||||
|  | ||||
|   constructor(correspondentsService: CorrespondentService, modalService: NgbModal, | ||||
|     private router: Router, | ||||
|     private list: DocumentListViewService | ||||
|   ) {  | ||||
|     super(correspondentsService,modalService,CorrespondentEditDialogComponent) | ||||
| @@ -27,9 +25,6 @@ export class CorrespondentListComponent extends GenericListComponent<PaperlessCo | ||||
|   } | ||||
|  | ||||
|   filterDocuments(object: PaperlessCorrespondent) { | ||||
|     this.list.documentListView.filter_rules = [ | ||||
|       {rule_type: FILTER_CORRESPONDENT, value: object.id.toString()} | ||||
|     ] | ||||
|     this.router.navigate(["documents"]) | ||||
|     this.list.quickFilter([{rule_type: FILTER_CORRESPONDENT, value: object.id.toString()}]) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import { Component } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||||
| import { FILTER_DOCUMENT_TYPE } from 'src/app/data/filter-rule-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> { | ||||
|  | ||||
|   constructor(service: DocumentTypeService, modalService: NgbModal, | ||||
|     private router: Router, | ||||
|     private list: DocumentListViewService | ||||
|   ) { | ||||
|     super(service, modalService, DocumentTypeEditDialogComponent) | ||||
| @@ -28,9 +26,6 @@ export class DocumentTypeListComponent extends GenericListComponent<PaperlessDoc | ||||
|  | ||||
|  | ||||
|   filterDocuments(object: PaperlessDocumentType) { | ||||
|     this.list.documentListView.filter_rules = [ | ||||
|       {rule_type: FILTER_DOCUMENT_TYPE, value: object.id.toString()} | ||||
|     ] | ||||
|     this.router.navigate(["documents"]) | ||||
|     this.list.quickFilter([{rule_type: FILTER_DOCUMENT_TYPE, value: object.id.toString()}]) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import { Component } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||||
| import { FILTER_HAS_TAG } from 'src/app/data/filter-rule-type'; | ||||
| 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> { | ||||
|  | ||||
|   constructor(tagService: TagService, modalService: NgbModal, | ||||
|     private router: Router, | ||||
|     private list: DocumentListViewService | ||||
|   ) { | ||||
|     super(tagService, modalService, TagEditDialogComponent) | ||||
| @@ -27,14 +25,11 @@ export class TagListComponent extends GenericListComponent<PaperlessTag> { | ||||
|   } | ||||
|  | ||||
|   getDeleteMessage(object: PaperlessTag) { | ||||
|      | ||||
|     return $localize`Do you really want to delete the tag "${object.name}"?` | ||||
|   } | ||||
|  | ||||
|   filterDocuments(object: PaperlessTag) { | ||||
|     this.list.documentListView.filter_rules = [ | ||||
|       {rule_type: FILTER_HAS_TAG, value: object.id.toString()} | ||||
|     ] | ||||
|     this.router.navigate(["documents"]) | ||||
|     this.list.quickFilter([{rule_type: FILTER_HAS_TAG, value: object.id.toString()}]) | ||||
|  | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { cloneFilterRules, FilterRule } from '../data/filter-rule'; | ||||
| 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)) | ||||
|   } | ||||
|  | ||||
|   quickFilter(filterRules: FilterRule[]) { | ||||
|     this.savedView = null | ||||
|     this.view.filter_rules = filterRules | ||||
|     this.reduceSelectionToFilter() | ||||
|     this.saveDocumentListView() | ||||
|     this.router.navigate(["documents"]) | ||||
|   } | ||||
|  | ||||
|   getLastPage(): number { | ||||
|     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) | ||||
|     if (documentListViewConfigJson) { | ||||
|       try { | ||||
|   | ||||
| @@ -2,5 +2,5 @@ export const environment = { | ||||
|   production: true, | ||||
|   apiBaseUrl: "/api/", | ||||
|   appTitle: "Paperless-ng", | ||||
|   version: "0.9.10" | ||||
|   version: "0.9.11" | ||||
| }; | ||||
|   | ||||
| @@ -5,6 +5,8 @@ | ||||
|   <title>Paperless-ng</title> | ||||
|   <base href="/"> | ||||
|   <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"> | ||||
| </head> | ||||
| <body> | ||||
|   | ||||
							
								
								
									
										14
									
								
								src-ui/src/manifest.webmanifest
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src-ui/src/manifest.webmanifest
									
									
									
									
									
										Normal 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": "/" | ||||
| } | ||||
| @@ -158,7 +158,7 @@ class Consumer(LoggingMixin): | ||||
|         try: | ||||
|             classifier = DocumentClassifier() | ||||
|             classifier.reload() | ||||
|         except (FileNotFoundError, IncompatibleClassifierVersionError) as e: | ||||
|         except (OSError, EOFError, IncompatibleClassifierVersionError) as e: | ||||
|             self.log( | ||||
|                 "warning", | ||||
|                 f"Cannot classify documents: {e}.") | ||||
|   | ||||
| @@ -73,7 +73,7 @@ class Command(Renderable, BaseCommand): | ||||
|         classifier = DocumentClassifier() | ||||
|         try: | ||||
|             classifier.reload() | ||||
|         except (FileNotFoundError, IncompatibleClassifierVersionError) as e: | ||||
|         except (OSError, EOFError, IncompatibleClassifierVersionError) as e: | ||||
|             logging.getLogger(__name__).warning( | ||||
|                 f"Cannot classify documents: {e}.") | ||||
|             classifier = None | ||||
|   | ||||
| @@ -35,9 +35,9 @@ def train_classifier(): | ||||
|     try: | ||||
|         # load the classifier, since we might not have to train it again. | ||||
|         classifier.reload() | ||||
|     except (FileNotFoundError, IncompatibleClassifierVersionError): | ||||
|     except (OSError, EOFError, IncompatibleClassifierVersionError): | ||||
|         # This is what we're going to fix here. | ||||
|         pass | ||||
|         classifier = DocumentClassifier() | ||||
|  | ||||
|     try: | ||||
|         if classifier.train(): | ||||
|   | ||||
| @@ -12,7 +12,9 @@ | ||||
| 	<meta name="full_name" content="{{full_name}}"> | ||||
| 	<meta name="cookie_prefix" content="{{cookie_prefix}}"> | ||||
|   <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> | ||||
|   <app-root>Loading...</app-root> | ||||
| 	<script src="{% static runtime_js %}" defer></script> | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| __version__ = (0, 9, 10) | ||||
| __version__ = (0, 9, 11) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 jonaswinkler
					jonaswinkler