2020-12-11 15:20:47 -08:00
import { Component , OnInit , ViewChild } from '@angular/core' ;
2020-12-14 19:26:36 +01:00
import { ActivatedRoute , Router } from '@angular/router' ;
2020-10-30 22:46:43 +01:00
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' ;
2020-12-11 14:49:22 +01:00
import { Observable } from 'rxjs' ;
import { map } from 'rxjs/operators' ;
2020-12-22 02:59:09 +01:00
import { PaperlessDocument } from 'src/app/data/paperless-document' ;
2020-12-14 19:26:36 +01:00
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view' ;
2020-10-30 23:43:19 +01:00
import { DocumentListViewService } from 'src/app/services/document-list-view.service' ;
2020-12-11 14:49:22 +01:00
import { CorrespondentService } from 'src/app/services/rest/correspondent.service' ;
import { DocumentTypeService } from 'src/app/services/rest/document-type.service' ;
import { DocumentService , DOCUMENT_SORT_FIELDS } from 'src/app/services/rest/document.service' ;
import { TagService } from 'src/app/services/rest/tag.service' ;
2020-12-14 19:26:36 +01:00
import { SavedViewService } from 'src/app/services/rest/saved-view.service' ;
2020-11-28 21:27:04 +01:00
import { Toast , ToastService } from 'src/app/services/toast.service' ;
2020-12-18 16:03:52 -08:00
import { FilterEditorComponent } from './filter-editor/filter-editor.component' ;
2020-12-13 15:13:43 +01:00
import { ConfirmDialogComponent } from '../common/confirm-dialog/confirm-dialog.component' ;
2020-12-11 14:49:22 +01:00
import { SelectDialogComponent } from '../common/select-dialog/select-dialog.component' ;
2020-10-30 22:46:43 +01:00
import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-view-config-dialog.component' ;
2020-12-19 02:26:41 -08:00
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' ;
2020-10-27 01:10:18 +01:00
@Component ( {
selector : 'app-document-list' ,
templateUrl : './document-list.component.html' ,
2020-11-22 14:43:59 +01:00
styleUrls : [ './document-list.component.scss' ]
2020-10-27 01:10:18 +01:00
} )
export class DocumentListComponent implements OnInit {
constructor (
2020-11-28 21:27:04 +01:00
public list : DocumentListViewService ,
2020-12-14 19:26:36 +01:00
public savedViewService : SavedViewService ,
2020-10-30 22:46:43 +01:00
public route : ActivatedRoute ,
2020-12-14 19:26:36 +01:00
private router : Router ,
2020-11-28 21:27:04 +01:00
private toastService : ToastService ,
2020-12-07 22:15:56 +01:00
public modalService : NgbModal ,
2020-12-11 14:49:22 +01:00
private correspondentService : CorrespondentService ,
private documentTypeService : DocumentTypeService ,
private tagService : TagService ,
private documentService : DocumentService ) { }
2020-10-27 01:10:18 +01:00
2020-12-14 16:51:01 +01:00
@ViewChild ( "filterEditor" )
private filterEditor : FilterEditorComponent
2020-10-27 01:10:18 +01:00
displayMode = 'smallCards' // largeCards, smallCards, details
2020-12-08 00:09:36 +01:00
get isFiltered() {
return this . list . filterRules ? . length > 0
}
2020-11-08 00:07:31 +01:00
getTitle() {
2020-11-28 21:27:04 +01:00
return this . list . savedViewTitle || "Documents"
2020-11-08 00:07:31 +01:00
}
2020-10-27 01:10:18 +01:00
getSortFields() {
2020-10-30 23:43:19 +01:00
return DOCUMENT_SORT_FIELDS
2020-10-27 01:10:18 +01:00
}
2020-12-14 23:14:19 -08:00
get isBulkEditing ( ) : boolean {
return this . list . selected . size > 0
}
2020-10-27 01:10:18 +01:00
saveDisplayMode() {
localStorage . setItem ( 'document-list:displayMode' , this . displayMode )
}
ngOnInit ( ) : void {
if ( localStorage . getItem ( 'document-list:displayMode' ) != null ) {
this . displayMode = localStorage . getItem ( 'document-list:displayMode' )
}
2020-10-30 22:46:43 +01:00
this . route . paramMap . subscribe ( params = > {
2020-12-14 19:26:36 +01:00
this . list . clear ( )
2020-10-30 22:46:43 +01:00
if ( params . has ( 'id' ) ) {
2020-12-14 19:26:36 +01:00
this . savedViewService . getCached ( + params . get ( 'id' ) ) . subscribe ( view = > {
if ( ! view ) {
this . router . navigate ( [ "404" ] )
return
}
this . list . savedView = view
this . list . reload ( )
} )
2020-10-30 22:46:43 +01:00
} else {
2020-11-28 21:27:04 +01:00
this . list . savedView = null
2020-12-14 19:26:36 +01:00
this . list . reload ( )
2020-10-30 22:46:43 +01:00
}
} )
2020-10-27 01:10:18 +01:00
}
2020-12-03 15:02:27 +01:00
2020-12-14 19:26:36 +01:00
loadViewConfig ( view : PaperlessSavedView ) {
this . list . load ( view )
2020-12-14 19:39:16 +01:00
this . list . reload ( )
2020-10-30 22:46:43 +01:00
}
saveViewConfig() {
2020-12-14 19:26:36 +01:00
this . savedViewService . update ( this . list . savedView ) . subscribe ( result = > {
this . toastService . showToast ( Toast . make ( "Information" , ` View " ${ this . list . savedView . name } " saved successfully. ` ) )
} )
2020-11-28 21:27:04 +01:00
}
saveViewConfigAs() {
2020-10-30 22:46:43 +01:00
let modal = this . modalService . open ( SaveViewConfigDialogComponent , { backdrop : 'static' } )
2020-12-18 14:55:21 -08:00
modal . componentInstance . defaultName = this . filterEditor . generateFilterName ( )
2020-10-30 22:46:43 +01:00
modal . componentInstance . saveClicked . subscribe ( formValue = > {
2020-12-14 21:14:33 +01:00
let savedView = {
2020-12-14 19:26:36 +01:00
name : formValue.name ,
show_on_dashboard : formValue.showOnDashboard ,
show_in_sidebar : formValue.showInSideBar ,
filter_rules : this.list.filterRules ,
sort_reverse : this.list.sortReverse ,
sort_field : this.list.sortField
2020-12-14 21:14:33 +01:00
}
this . savedViewService . create ( savedView ) . subscribe ( ( ) = > {
2020-12-14 19:26:36 +01:00
modal . close ( )
2020-12-14 21:14:33 +01:00
this . toastService . showToast ( Toast . make ( "Information" , ` View " ${ savedView . name } " created successfully. ` ) )
2020-10-30 22:46:43 +01:00
} )
} )
}
2020-11-28 21:28:07 +01:00
2020-12-11 15:20:47 -08:00
clickTag ( tagID : number ) {
2020-12-19 22:14:52 -08:00
this . list . selectNone ( )
2020-12-21 11:12:48 -08:00
setTimeout ( ( ) = > {
this . filterEditor . toggleTag ( tagID )
} )
2020-11-28 21:28:07 +01:00
}
2020-12-11 15:20:47 -08:00
clickCorrespondent ( correspondentID : number ) {
2020-12-19 22:14:52 -08:00
this . list . selectNone ( )
2020-12-21 11:12:48 -08:00
setTimeout ( ( ) = > {
this . filterEditor . toggleCorrespondent ( correspondentID )
} )
2020-11-28 21:28:07 +01:00
}
2020-12-11 15:20:47 -08:00
clickDocumentType ( documentTypeID : number ) {
2020-12-19 22:14:52 -08:00
this . list . selectNone ( )
2020-12-21 11:12:48 -08:00
setTimeout ( ( ) = > {
this . filterEditor . toggleDocumentType ( documentTypeID )
} )
2020-11-28 22:14:12 +01:00
}
2020-12-22 02:59:09 +01:00
trackByDocumentId ( index , item : PaperlessDocument ) {
return item . id
}
2020-12-22 03:00:22 +01:00
2020-12-11 14:49:22 +01:00
private executeBulkOperation ( method : string , args ) : Observable < any > {
return this . documentService . bulkEdit ( Array . from ( this . list . selected ) , method , args ) . pipe (
map ( r = > {
this . list . reload ( )
this . list . selectNone ( )
return r
} )
)
}
2020-12-19 07:49:32 -08:00
bulkSetCorrespondent ( correspondent : PaperlessCorrespondent ) {
2020-12-19 02:26:41 -08:00
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
2020-12-22 02:08:36 -08:00
modal . componentInstance . title = "Confirm Correspondent assignment"
2020-12-19 02:26:41 -08:00
let messageFragment = correspondent ? ` assign the correspondent ${ correspondent . name } to ` : ` remove all correspondents from `
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 . confirmClicked . subscribe ( ( ) = > {
this . executeBulkOperation ( 'set_correspondent' , { "correspondent" : correspondent ? correspondent.id : null } ) . subscribe (
2020-12-11 14:49:22 +01:00
response = > {
modal . close ( )
}
)
} )
}
2020-12-22 02:08:36 -08:00
bulkRemoveCorrespondents ( correspondents : PaperlessCorrespondent [ ] ) {
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
modal . componentInstance . title = "Confirm Correspondent Removal"
modal . componentInstance . message = ` This operation will remove the correspondent(s) ${ correspondents . map ( t = > t . name ) . join ( ', ' ) } from all ${ this . list . selected . size } selected document(s). `
modal . componentInstance . btnClass = "btn-warning"
modal . componentInstance . btnCaption = "Confirm"
modal . componentInstance . confirmClicked . subscribe ( ( ) = > {
// TODO: API endpoint for remove multiple correspondents
this . executeBulkOperation ( 'remove_correspondents' , { "correspondents" : correspondents . map ( t = > t . id ) } ) . subscribe (
response = > {
modal . close ( )
}
)
} )
}
2020-12-19 07:49:32 -08:00
bulkSetDocumentType ( documentType : PaperlessDocumentType ) {
2020-12-13 15:20:24 +01:00
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
2020-12-19 02:26:41 -08:00
modal . componentInstance . title = "Confirm Document Type assignment"
let messageFragment = documentType ? ` assign the document type ${ documentType . name } to ` : ` remove all document types from `
modal . componentInstance . message = ` This operation will ${ messageFragment } all ${ this . list . selected . size } selected document(s). `
modal . componentInstance . btnClass = "btn-warning"
modal . componentInstance . btnCaption = "Confirm"
2020-12-13 15:20:24 +01:00
modal . componentInstance . confirmClicked . subscribe ( ( ) = > {
2020-12-19 02:26:41 -08:00
this . executeBulkOperation ( 'set_document_type' , { "document_type" : documentType ? documentType.id : null } ) . subscribe (
2020-12-11 14:49:22 +01:00
response = > {
modal . close ( )
}
)
} )
}
2020-12-22 02:08:36 -08:00
bulkRemoveDocumentTypes ( documentTypes : PaperlessDocumentType [ ] ) {
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
modal . componentInstance . title = "Confirm Document Type Removal"
modal . componentInstance . message = ` This operation will remove the document type(s) ${ documentTypes . map ( t = > t . name ) . join ( ', ' ) } all ${ this . list . selected . size } selected document(s). `
modal . componentInstance . btnClass = "btn-warning"
modal . componentInstance . btnCaption = "Confirm"
modal . componentInstance . confirmClicked . subscribe ( ( ) = > {
// TODO: API endpoint for remove multiple document types
this . executeBulkOperation ( 'remove_document_types' , { "document_types" : documentTypes . map ( t = > t . id ) } ) . subscribe (
response = > {
modal . close ( )
}
)
} )
}
2020-12-19 14:26:26 -08:00
bulkSetTags ( tags : PaperlessTag [ ] ) {
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
modal . componentInstance . title = "Confirm Tags assignment"
let messageFragment = tags ? ` assign the tag(s) ${ tags . map ( t = > t . name ) . join ( ', ' ) } to ` : ` remove all tags from `
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 . confirmClicked . subscribe ( ( ) = > {
// TODO: API endpoint for set multiple tags
2020-12-22 02:08:36 -08:00
this . executeBulkOperation ( 'set_tags' , { "tags" : tags ? tags . map ( t = > t . id ) : null } ) . subscribe (
response = > {
modal . close ( )
}
)
} )
}
bulkRemoveTags ( tags : PaperlessTag [ ] ) {
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
modal . componentInstance . title = "Confirm Tags Removal"
modal . componentInstance . message = ` This operation will remove the tags ${ tags . map ( t = > t . name ) . join ( ', ' ) } from all ${ this . list . selected . size } selected document(s). `
modal . componentInstance . btnClass = "btn-warning"
modal . componentInstance . btnCaption = "Confirm"
modal . componentInstance . confirmClicked . subscribe ( ( ) = > {
// TODO: API endpoint for remove multiple tags
this . executeBulkOperation ( 'remove_tags' , { "tags" : tags . map ( t = > t . id ) } ) . subscribe (
2020-12-19 14:26:26 -08:00
response = > {
modal . close ( )
}
)
} )
2020-12-19 02:08:33 -08:00
}
2020-12-11 14:49:22 +01:00
bulkDelete() {
2020-12-13 15:13:43 +01:00
let modal = this . modalService . open ( ConfirmDialogComponent , { backdrop : 'static' } )
2020-12-11 14:49:22 +01:00
modal . componentInstance . delayConfirm ( 5 )
2020-12-13 15:13:43 +01:00
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 . btnClass = "btn-danger"
modal . componentInstance . btnCaption = "Delete document(s)"
modal . componentInstance . confirmClicked . subscribe ( ( ) = > {
2020-12-11 14:49:22 +01:00
this . executeBulkOperation ( "delete" , { } ) . subscribe (
response = > {
modal . close ( )
}
)
2020-12-15 03:13:22 +01:00
} )
2020-12-11 14:49:22 +01:00
}
2020-10-27 01:10:18 +01:00
}