mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Merge branch 'feature-bulk-edit' into feature-bulk-editor
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| <div class="form-group paperless-input-select"> | ||||
|   <label [for]="inputId">{{title}}</label> | ||||
|   <div [class.input-group]="showPlusButton()"> | ||||
|     <ng-select name="correspondent" [(ngModel)]="value" | ||||
|     <ng-select name="inputId" [(ngModel)]="value" | ||||
|       [disabled]="disabled" | ||||
|       [style.color]="textColor" | ||||
|       [style.background]="backgroundColor" | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <app-page-header title="Dashboard" subTitle="Welcome to paperless-ng!"> | ||||
| <app-page-header title="Dashboard" [subTitle]="subtitle"> | ||||
|   <img src="assets/logo.svg" height="80" class="m-2 d-none d-md-block"> | ||||
| </app-page-header> | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { Meta } from '@angular/platform-browser'; | ||||
| import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'; | ||||
| import { SavedViewService } from 'src/app/services/rest/saved-view.service'; | ||||
|  | ||||
| @@ -11,8 +12,29 @@ import { SavedViewService } from 'src/app/services/rest/saved-view.service'; | ||||
| export class DashboardComponent implements OnInit { | ||||
|  | ||||
|   constructor( | ||||
|     private savedViewService: SavedViewService) { } | ||||
|     private savedViewService: SavedViewService, | ||||
|     private meta: Meta | ||||
|   ) { } | ||||
|  | ||||
|   get displayName() { | ||||
|     let tagFullName = this.meta.getTag('name=full_name') | ||||
|     let tagUsername = this.meta.getTag('name=username') | ||||
|     if (tagFullName && tagFullName.content) { | ||||
|       return tagFullName.content | ||||
|     } else if (tagUsername && tagUsername.content) { | ||||
|       return tagUsername.content | ||||
|     } else { | ||||
|       return null | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   get subtitle() { | ||||
|     if (this.displayName) { | ||||
|       return `Hello ${this.displayName}, welcome to Paperless-ng!` | ||||
|     } else { | ||||
|       return `Welcome to Paperless-ng!` | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   savedViews: PaperlessSavedView[] = [] | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ export class SavedViewWidgetComponent implements OnInit { | ||||
|   documents: PaperlessDocument[] = [] | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.documentService.list(1,10,this.savedView.sort_field, this.savedView.sort_reverse, this.savedView.filter_rules).subscribe(result => { | ||||
|     this.documentService.listFiltered(1,10,this.savedView.sort_field, this.savedView.sort_reverse, this.savedView.filter_rules).subscribe(result => { | ||||
|       this.documents = result.results | ||||
|     }) | ||||
|   } | ||||
|   | ||||
| @@ -1,7 +1,15 @@ | ||||
| <div class="card mb-3 bg-light shadow-sm"> | ||||
| <div class="card mb-3 bg-light shadow-sm" [class.card-selected]="selected" [class.document-card]="selectable"> | ||||
|   <div class="row no-gutters"> | ||||
|     <div class="col-md-2 d-none d-lg-block"> | ||||
|       <img [src]="getThumbUrl()" class="card-img doc-img border-right"> | ||||
|     <div class="col-md-2 d-none d-lg-block doc-img-background" [class.doc-img-background-selected]="selected"> | ||||
|       <img [src]="getThumbUrl()" class="card-img doc-img border-right" (click)="selected = selectable ? !selected : false"> | ||||
|  | ||||
|       <div style="top: 0; left: 0" class="position-absolute border-right border-bottom bg-light p-1" [class.document-card-check]="!selected"> | ||||
|         <div class="custom-control custom-checkbox"> | ||||
|           <input type="checkbox" class="custom-control-input" id="smallCardCheck{{document.id}}" [checked]="selected" (change)="selected = $event.target.checked"> | ||||
|           <label class="custom-control-label" for="smallCardCheck{{document.id}}"></label> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|     </div> | ||||
|     <div class="col"> | ||||
|       <div class="card-body"> | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| @import "/src/theme"; | ||||
|  | ||||
| .result-content { | ||||
|   color: darkgray; | ||||
|   overflow-wrap: anywhere; | ||||
| } | ||||
|  | ||||
| @@ -8,11 +9,31 @@ | ||||
|   object-position: top; | ||||
|   height: 100%; | ||||
|   position: absolute; | ||||
|  | ||||
|   mix-blend-mode: multiply; | ||||
| } | ||||
|  | ||||
| .search-score-bar { | ||||
|   width: 100px; | ||||
|   height: 5px; | ||||
|   margin-top: 2px; | ||||
| } | ||||
|  | ||||
| .document-card-check { | ||||
|   display: none | ||||
| } | ||||
|  | ||||
| .document-card:hover .document-card-check { | ||||
|   display: block; | ||||
| } | ||||
|  | ||||
| .card-selected { | ||||
|   border-color: $primary; | ||||
| } | ||||
|  | ||||
| .doc-img-background { | ||||
|   background-color: white; | ||||
| } | ||||
|  | ||||
| .doc-img-background-selected { | ||||
|   background-color: $primaryFaded; | ||||
| } | ||||
| @@ -12,6 +12,25 @@ export class DocumentCardLargeComponent implements OnInit { | ||||
|  | ||||
|   constructor(private documentService: DocumentService, private sanitizer: DomSanitizer) { } | ||||
|  | ||||
|   _selected = false | ||||
|  | ||||
|   get selected() { | ||||
|     return this._selected | ||||
|   } | ||||
|  | ||||
|   @Input() | ||||
|   set selected(value: boolean) { | ||||
|     this._selected = value | ||||
|     this.selectedChange.emit(value) | ||||
|   } | ||||
|  | ||||
|   @Output() | ||||
|   selectedChange = new EventEmitter<boolean>() | ||||
|  | ||||
|   get selectable() { | ||||
|     return this.selectedChange.observers.length > 0 | ||||
|   } | ||||
|  | ||||
|   @Input() | ||||
|   moreLikeThis: boolean = false | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|  | ||||
|       <div style="top: 0; right: 0; font-size: large" class="text-right position-absolute mr-1"> | ||||
|         <div *ngFor="let t of getTagsLimited$() | async"> | ||||
|           <app-tag [tag]="t" (click)="clickTag.emit(t.id)" [clickable]="true" linkTitle="Filter by tag"></app-tag> | ||||
|   | ||||
| @@ -100,7 +100,7 @@ | ||||
| </div> | ||||
|  | ||||
| <div *ngIf="displayMode == 'largeCards'"> | ||||
|   <app-document-card-large *ngFor="let d of list.documents" [document]="d" [details]="d.content" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"> | ||||
|   <app-document-card-large [selected]="list.isSelected(d)" (selectedChange)="list.setSelected(d, $event)"   *ngFor="let d of list.documents; trackBy: trackByDocumentId" [document]="d" [details]="d.content" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"> | ||||
|   </app-document-card-large> | ||||
| </div> | ||||
|  | ||||
| @@ -115,7 +115,7 @@ | ||||
|     <th class="d-none d-xl-table-cell">Added</th> | ||||
|   </thead> | ||||
|   <tbody> | ||||
|     <tr *ngFor="let d of list.documents" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''"> | ||||
|     <tr *ngFor="let d of list.documents; trackBy: trackByDocumentId" [ngClass]="list.isSelected(d) ? 'table-row-selected' : ''"> | ||||
|       <td> | ||||
|         <div class="custom-control custom-checkbox"> | ||||
|           <input type="checkbox" class="custom-control-input" id="docCheck{{d.id}}" [checked]="list.isSelected(d)" (change)="list.setSelected(d, $event.target.checked)"> | ||||
| @@ -149,7 +149,6 @@ | ||||
|   </tbody> | ||||
| </table> | ||||
|  | ||||
|  | ||||
| <div class="m-n2 row m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'"> | ||||
|   <app-document-card-small [document]="d" [selected]="list.isSelected(d)" (selectedChange)="list.setSelected(d, $event)" *ngFor="let d of list.documents" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"></app-document-card-small> | ||||
| <div class="m-n2 row row-cols-paperless-cards" *ngIf="displayMode == 'smallCards'"> | ||||
|   <app-document-card-small [selected]="list.isSelected(d)" (selectedChange)="list.setSelected(d, $event)"  [document]="d" *ngFor="let d of list.documents; trackBy: trackByDocumentId" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)"></app-document-card-small> | ||||
| </div> | ||||
|   | ||||
| @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router'; | ||||
| import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||||
| import { Observable } from 'rxjs'; | ||||
| import { map } from 'rxjs/operators'; | ||||
| import { PaperlessDocument } from 'src/app/data/paperless-document'; | ||||
| import { PaperlessSavedView } from 'src/app/data/paperless-saved-view'; | ||||
| import { DocumentListViewService } from 'src/app/services/document-list-view.service'; | ||||
| import { CorrespondentService } from 'src/app/services/rest/correspondent.service'; | ||||
| @@ -139,6 +140,10 @@ export class DocumentListComponent implements OnInit { | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   trackByDocumentId(index, item: PaperlessDocument) { | ||||
|     return item.id | ||||
|   } | ||||
|  | ||||
|   private executeBulkOperation(method: string, args): Observable<any> { | ||||
|     return this.documentService.bulkEdit(Array.from(this.list.selected), method, args).pipe( | ||||
|       map(r => { | ||||
|   | ||||
| @@ -8,10 +8,9 @@ | ||||
|   <div class="modal-body"> | ||||
|      | ||||
|     <app-input-text title="Name" formControlName="name"></app-input-text> | ||||
|     <app-input-text title="Match" formControlName="match"></app-input-text> | ||||
|     <app-input-select title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> | ||||
|     <app-input-check title="Case insensitive" formControlName="is_insensitive"></app-input-check> | ||||
|  | ||||
|     <app-input-text title="Match" formControlName="match" hint="Auto matching does not require you to fill in this field."></app-input-text> | ||||
|     <app-input-check title="Case insensitive" formControlName="is_insensitive" hint="Auto matching ignores this option."></app-input-check> | ||||
|   </div> | ||||
|   <div class="modal-footer"> | ||||
|     <button type="button" class="btn btn-outline-dark" (click)="cancel()">Cancel</button> | ||||
|   | ||||
| @@ -8,9 +8,9 @@ | ||||
|     <div class="modal-body"> | ||||
|        | ||||
|       <app-input-text title="Name" formControlName="name"></app-input-text> | ||||
|       <app-input-text title="Match" formControlName="match"></app-input-text> | ||||
|       <app-input-select title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> | ||||
|       <app-input-check title="Case insensitive" formControlName="is_insensitive"></app-input-check> | ||||
|       <app-input-text title="Match" formControlName="match" hint="Auto matching does not require you to fill in this field."></app-input-text> | ||||
|       <app-input-check title="Case insensitive" formControlName="is_insensitive" hint="Auto matching ignores this option."></app-input-check> | ||||
|  | ||||
|     </div> | ||||
|     <div class="modal-footer"> | ||||
|   | ||||
| @@ -7,11 +7,21 @@ | ||||
|     </div> | ||||
|     <div class="modal-body"> | ||||
|       <app-input-text title="Name" formControlName="name"></app-input-text> | ||||
|       <app-input-select title="Colour" [items]="getColours()" formControlName="colour" [textColor]="getColor(objectForm.value.colour).textColor" [backgroundColor]="getColor(objectForm.value.colour).value"></app-input-select> | ||||
|  | ||||
|  | ||||
|       <div class="form-group paperless-input-select"> | ||||
|         <label for="colour">Colour</label> | ||||
|         <ng-select name="colour" formControlName="colour" [items]="getColours()" bindValue="id" bindLabel="name" [clearable]="false"> | ||||
|           <ng-template ng-option-tmp ng-label-tmp let-item="item"> | ||||
|             <span class="badge" [style.background]="item.value" [style.color]="item.textColor">{{item.name}}</span> | ||||
|           </ng-template> | ||||
|         </ng-select> | ||||
|       </div> | ||||
|       | ||||
|       <app-input-check title="Inbox tag" formControlName="is_inbox_tag" hint="Inbox tags are automatically assigned to all consumed documents."></app-input-check> | ||||
|       <app-input-text title="Match" formControlName="match"></app-input-text> | ||||
|       <app-input-select title="Matching algorithm" [items]="getMatchingAlgorithms()" formControlName="matching_algorithm"></app-input-select> | ||||
|       <app-input-check title="Case insensitive" formControlName="is_insensitive"></app-input-check> | ||||
|       <app-input-text title="Match" formControlName="match" hint="Auto matching does not require you to fill in this field."></app-input-text> | ||||
|       <app-input-check title="Case insensitive" formControlName="is_insensitive" hint="Auto matching ignores this option."></app-input-check> | ||||
|     </div> | ||||
|     <div class="modal-footer"> | ||||
|       <button type="button" class="btn btn-outline-dark" (click)="cancel()">Cancel</button> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Shamoon
					Michael Shamoon