mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Bulk editor component skeleton
This commit is contained in:
parent
55a6dca373
commit
01d448ecde
@ -27,6 +27,9 @@ export class FilterableDropdownComponent {
|
||||
@Output()
|
||||
toggle = new EventEmitter()
|
||||
|
||||
@Output()
|
||||
close = new EventEmitter()
|
||||
|
||||
@ViewChild('listFilterTextInput') listFilterTextInput: ElementRef
|
||||
@ViewChild('dropdown') dropdown: NgbDropdown
|
||||
|
||||
@ -47,6 +50,7 @@ export class FilterableDropdownComponent {
|
||||
}, 0);
|
||||
} else {
|
||||
this.filterText = ''
|
||||
this.close.emit(this.itemsSelected)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,89 +1,34 @@
|
||||
<div class="card bg-light">
|
||||
<div class="card-body small px-2 py-2 d-flex flex-column flex-xl-row justify-content-between justify-content-xl-start">
|
||||
<div class="d-flex flex-grow-1 flex-xl-grow-0 mb-2 mb-xl-0 mr-xl-5" role="group" aria-label="Select">
|
||||
<label class="d-flex align-self-center my-0 mr-auto mr-lg-2">Select:</label>
|
||||
<div class="btn-group d-flex">
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="selectPage.next()">
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<div class="row">
|
||||
<div class="col mb-2 mb-xl-0" role="group" aria-label="Select">
|
||||
<label class="mr-lg-2">Select:</label>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-outline-primary" (click)="selectPage.next()">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#file-earmark-check" />
|
||||
</svg>
|
||||
<small>Page</small>
|
||||
Page
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="selectAll.next()">
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<button class="btn btn-sm btn-outline-primary" (click)="selectAll.next()">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#check-all" />
|
||||
</svg>
|
||||
<small>All</small>
|
||||
All
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="selectNone.next()">
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<button class="btn btn-sm btn-outline-primary" (click)="selectNone.next()">
|
||||
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#slash-circle" />
|
||||
</svg>
|
||||
<small>None</small>
|
||||
None
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-grow-1 flex-xl-grow-0 mb-2 mb-xl-0 mr-xl-5" role="group" aria-label="Tags">
|
||||
<label class="d-flex align-self-center my-0 mr-auto mr-lg-2">Tags:</label>
|
||||
<div class="btn-group d-flex">
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="addTag.next()">
|
||||
<ng-container *ngTemplateOutlet="add"></ng-container>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="removeTag.next()">
|
||||
<ng-container *ngTemplateOutlet="remove"></ng-container>
|
||||
</button>
|
||||
<div class="w-100 d-xl-none"></div>
|
||||
<div class="col mb-2 mb-xl-0">
|
||||
<div class="d-flex">
|
||||
<label class="ml-auto mt-1 mr-2">Apply:</label>
|
||||
<app-filterable-dropdown class="mr-2 mr-md-3" title="Apply Tags" icon="tag-fill" [items]="tags" [itemsSelected]="selectedTags" (close)="applyTags($event)"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="mr-2 mr-md-3" title="Set Correspondent" icon="person-fill" [items]="correspondents" [itemsSelected]="selectedCorrespondents" (close)="applyCorrespondent($event)"></app-filterable-dropdown>
|
||||
<app-filterable-dropdown class="mr-2 mr-md-3" title="Set Document Type" icon="file-earmark-fill" [items]="documentTypes" [itemsSelected]="selectedDocumentTypes" (close)="applyDocumentType($event)"></app-filterable-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-grow-1 flex-xl-grow-0 mb-2 mb-xl-0 mr-xl-5" role="group" aria-label="Correspondent">
|
||||
<label class="d-flex align-self-center my-0 mr-auto mr-lg-2">Correspondent:</label>
|
||||
<div class="btn-group d-flex">
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="setCorrespondent.next()">
|
||||
<ng-container *ngTemplateOutlet="edit"></ng-container>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="removeCorrespondent.next()">
|
||||
<ng-container *ngTemplateOutlet="remove"></ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-grow-1 flex-xl-grow-0 mb-2 mb-xl-0 mr-xl-5" role="group" aria-label="Document Type">
|
||||
<label class="d-flex align-self-center my-0 mr-auto mr-lg-2">Document Type:</label>
|
||||
<div class="btn-group d-flex">
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="setDocumentType.next()">
|
||||
<ng-container *ngTemplateOutlet="edit"></ng-container>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-primary py-1 px-2" (click)="removeDocumentType.next()">
|
||||
<ng-container *ngTemplateOutlet="remove"></ng-container>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-grow-1 flex-xl-grow-0 mb-2 mb-lg-0 ml-auto ml-lg-0 ml-xl-auto" role="group" aria-label="Delete">
|
||||
<button class="btn btn-sm btn-outline-danger" (click)="delete.next()">
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
||||
</svg>
|
||||
<small>Delete</small>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #add>
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#plus-circle" />
|
||||
</svg>
|
||||
<small>Add</small>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #edit>
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#pencil" />
|
||||
</svg>
|
||||
<small>Edit</small>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #remove>
|
||||
<svg viewBox="0 0 16 16" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#x-circle" />
|
||||
</svg>
|
||||
<small>Remove</small>
|
||||
</ng-template>
|
||||
|
@ -1,10 +0,0 @@
|
||||
.btn svg {
|
||||
width: 0.9em;
|
||||
height: 0.9em;
|
||||
margin-right: 3px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
line-height: 1;
|
||||
}
|
@ -1,5 +1,12 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
|
||||
import { PaperlessTag } from 'src/app/data/paperless-tag';
|
||||
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent';
|
||||
import { PaperlessDocumentType } from 'src/app/data/paperless-document-type';
|
||||
import { PaperlessDocument } from 'src/app/data/paperless-document';
|
||||
import { TagService } from 'src/app/services/rest/tag.service';
|
||||
import { CorrespondentService } from 'src/app/services/rest/correspondent.service';
|
||||
import { DocumentTypeService } from 'src/app/services/rest/document-type.service';
|
||||
import { DocumentService } from 'src/app/services/rest/document.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-bulk-editor',
|
||||
@ -9,7 +16,10 @@ import { DocumentListViewService } from 'src/app/services/document-list-view.ser
|
||||
export class BulkEditorComponent {
|
||||
|
||||
@Input()
|
||||
list: DocumentListViewService
|
||||
documentsSelected: Set<number>
|
||||
|
||||
@Input()
|
||||
allDocuments: PaperlessDocument[]
|
||||
|
||||
@Output()
|
||||
selectPage = new EventEmitter()
|
||||
@ -41,6 +51,65 @@ export class BulkEditorComponent {
|
||||
@Output()
|
||||
delete = new EventEmitter()
|
||||
|
||||
constructor( ) { }
|
||||
tags: PaperlessTag[]
|
||||
correspondents: PaperlessCorrespondent[]
|
||||
documentTypes: PaperlessDocumentType[]
|
||||
|
||||
get selectedTags(): PaperlessTag[] {
|
||||
let selectedTags = []
|
||||
this.allDocuments.forEach(d => {
|
||||
if (this.documentsSelected.has(d.id)) {
|
||||
if (d.tags && !d.tags.every(t => selectedTags.find(st => st.id == t) !== undefined)) d.tags$.subscribe(t => selectedTags = selectedTags.concat(t))
|
||||
}
|
||||
})
|
||||
return selectedTags
|
||||
}
|
||||
|
||||
get selectedCorrespondents(): PaperlessCorrespondent[] {
|
||||
let selectedCorrespondents = []
|
||||
this.allDocuments.forEach(d => {
|
||||
if (this.documentsSelected.has(d.id)) {
|
||||
if (d.correspondent && selectedCorrespondents.find(sc => sc.id == d.correspondent) == undefined) d.correspondent$.subscribe(c => selectedCorrespondents.push(c))
|
||||
}
|
||||
})
|
||||
return selectedCorrespondents
|
||||
}
|
||||
|
||||
get selectedDocumentTypes(): PaperlessDocumentType[] {
|
||||
let selectedDocumentTypes = []
|
||||
this.allDocuments.forEach(d => {
|
||||
if (this.documentsSelected.has(d.id)) {
|
||||
if (d.document_type && selectedDocumentTypes.find(sdt => sdt.id == d.document_type) == undefined) d.document_type$.subscribe(dt => selectedDocumentTypes.push(dt))
|
||||
}
|
||||
})
|
||||
return selectedDocumentTypes
|
||||
}
|
||||
|
||||
constructor(
|
||||
private documentTypeService: DocumentTypeService,
|
||||
private tagService: TagService,
|
||||
private correspondentService: CorrespondentService,
|
||||
private documentService: DocumentService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.tagService.listAll().subscribe(result => this.tags = result.results)
|
||||
this.correspondentService.listAll().subscribe(result => this.correspondents = result.results)
|
||||
this.documentTypeService.listAll().subscribe(result => this.documentTypes = result.results)
|
||||
}
|
||||
|
||||
applyTags(tags) {
|
||||
console.log(tags);
|
||||
|
||||
}
|
||||
|
||||
applyCorrespondent(correspondent) {
|
||||
console.log(correspondent);
|
||||
|
||||
}
|
||||
|
||||
applyDocumentType(documentType) {
|
||||
console.log(documentType);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -78,17 +78,11 @@
|
||||
</app-page-header>
|
||||
|
||||
<div class="w-100 mb-2 mb-sm-4">
|
||||
<app-filter-editor [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor>
|
||||
</div>
|
||||
<app-filter-editor *ngIf="!isBulkEditing" [(filterRules)]="list.filterRules" #filterEditor></app-filter-editor>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<p><span *ngIf="list.selected.size > 0">Selected {{list.selected.size}} of </span>{{list.collectionSize || 0}} document(s) <span *ngIf="isFiltered">(filtered)</span></p>
|
||||
<ngb-pagination [pageSize]="list.currentPageSize" [collectionSize]="list.collectionSize" [(page)]="list.currentPage" [maxSize]="5"
|
||||
[rotate]="true" (pageChange)="list.reload()" aria-label="Default pagination"></ngb-pagination>
|
||||
</div>
|
||||
|
||||
<div class="w-100 mb-3" [ngbCollapse]="!isBulkEditing">
|
||||
<app-bulk-editor
|
||||
<app-bulk-editor *ngIf="isBulkEditing"
|
||||
[allDocuments]="list.documents"
|
||||
[(documentsSelected)]="list.selected"
|
||||
(selectPage)="list.selectPage()"
|
||||
(selectAll)="list.selectAll()"
|
||||
(selectNone)="list.selectNone()"
|
||||
@ -99,7 +93,13 @@
|
||||
(addTag)="bulkAddTag()"
|
||||
(removeTag)="bulkRemoveTag()"
|
||||
(delete)="bulkDelete()">
|
||||
</app-bulk-editor>
|
||||
</app-bulk-editor>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<p><span *ngIf="list.selected.size > 0">Selected {{list.selected.size}} of </span>{{list.collectionSize || 0}} document(s) <span *ngIf="isFiltered">(filtered)</span></p>
|
||||
<ngb-pagination [pageSize]="list.currentPageSize" [collectionSize]="list.collectionSize" [(page)]="list.currentPage" [maxSize]="5"
|
||||
[rotate]="true" (pageChange)="list.reload()" aria-label="Default pagination"></ngb-pagination>
|
||||
</div>
|
||||
|
||||
<div *ngIf="displayMode == 'largeCards'">
|
||||
|
Loading…
x
Reference in New Issue
Block a user