mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Bulk editor enabling/disabling by permissions
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| <div class="btn-group w-100" ngbDropdown role="group" (openChange)="dropdownOpenChange($event)" #dropdown="ngbDropdown"> | ||||
|   <button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="!editing && selectionModel.selectionSize() > 0 ? 'btn-primary' : 'btn-outline-primary'"> | ||||
|   <button class="btn btn-sm" id="dropdown{{title}}" ngbDropdownToggle [ngClass]="!editing && selectionModel.selectionSize() > 0 ? 'btn-primary' : 'btn-outline-primary'" [disabled]="disabled"> | ||||
|     <svg class="toolbaricon" fill="currentColor"> | ||||
|       <use attr.xlink:href="assets/bootstrap-icons.svg#{{icon}}" /> | ||||
|     </svg> | ||||
| @@ -25,10 +25,10 @@ | ||||
|       </div> | ||||
|       <div *ngIf="selectionModel.items" class="items"> | ||||
|         <ng-container *ngFor="let item of selectionModel.itemsSorted | filter: filterText"> | ||||
|           <app-toggleable-dropdown-button *ngIf="allowSelectNone || item.id" [item]="item" [state]="selectionModel.get(item.id)" (toggle)="selectionModel.toggle(item.id)" (exclude)="excludeClicked(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)" (exclude)="excludeClicked(item.id)" [disabled]="disabled"></app-toggleable-dropdown-button> | ||||
|         </ng-container> | ||||
|       </div> | ||||
|       <button *ngIf="editing" class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!modelIsDirty"> | ||||
|       <button *ngIf="editing" class="list-group-item list-group-item-action bg-light" (click)="applyClicked()" [disabled]="!modelIsDirty || disabled"> | ||||
|         <small class="ms-2" [ngClass]="{'fw-bold': modelIsDirty}" i18n>Apply</small> | ||||
|         <svg width="1.5em" height="1em" viewBox="0 0 16 16" fill="currentColor"> | ||||
|           <use xlink:href="assets/bootstrap-icons.svg#arrow-right" /> | ||||
|   | ||||
| @@ -317,6 +317,9 @@ export class FilterableDropdownComponent { | ||||
|   @Input() | ||||
|   applyOnClose = false | ||||
|  | ||||
|   @Input() | ||||
|   disabled = false | ||||
|  | ||||
|   @Output() | ||||
|   apply = new EventEmitter<ChangedItems>() | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="toggleItem($event)"> | ||||
| <button class="list-group-item list-group-item-action d-flex align-items-center p-2 border-top-0 border-start-0 border-end-0 border-bottom" role="menuitem" (click)="toggleItem($event)" [disabled]="disabled"> | ||||
|   <div class="selected-icon me-1"> | ||||
|     <ng-container *ngIf="isChecked()"> | ||||
|       <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16"> | ||||
|   | ||||
| @@ -23,6 +23,9 @@ export class ToggleableDropdownButtonComponent { | ||||
|   @Input() | ||||
|   count: number | ||||
|  | ||||
|   @Input() | ||||
|   disabled: boolean = false | ||||
|  | ||||
|   @Output() | ||||
|   toggle = new EventEmitter() | ||||
|  | ||||
|   | ||||
| @@ -28,6 +28,7 @@ | ||||
|       <app-filterable-dropdown class="me-2 me-md-3" title="Tags" icon="tag-fill" i18n-title | ||||
|         filterPlaceholder="Filter tags" i18n-filterPlaceholder | ||||
|         [items]="tags" | ||||
|         [disabled]="!userCanEditAll" | ||||
|         [editing]="true" | ||||
|         [multiple]="true" | ||||
|         [applyOnClose]="applyOnClose" | ||||
| @@ -38,6 +39,7 @@ | ||||
|       <app-filterable-dropdown class="me-2 me-md-3" title="Correspondent" icon="person-fill" i18n-title | ||||
|         filterPlaceholder="Filter correspondents" i18n-filterPlaceholder | ||||
|         [items]="correspondents" | ||||
|         [disabled]="!userCanEditAll" | ||||
|         [editing]="true" | ||||
|         [applyOnClose]="applyOnClose" | ||||
|         (open)="openCorrespondentDropdown()" | ||||
| @@ -47,6 +49,7 @@ | ||||
|       <app-filterable-dropdown class="me-2 me-md-3" title="Document type" icon="file-earmark-fill" i18n-title | ||||
|         filterPlaceholder="Filter document types" i18n-filterPlaceholder | ||||
|         [items]="documentTypes" | ||||
|         [disabled]="!userCanEditAll" | ||||
|         [editing]="true" | ||||
|         [applyOnClose]="applyOnClose" | ||||
|         (open)="openDocumentTypeDropdown()" | ||||
| @@ -56,6 +59,7 @@ | ||||
|       <app-filterable-dropdown class="me-2 me-md-3" title="Storage path" icon="folder-fill" i18n-title | ||||
|         filterPlaceholder="Filter storage paths" i18n-filterPlaceholder | ||||
|         [items]="storagePaths" | ||||
|         [disabled]="!userCanEditAll" | ||||
|         [editing]="true" | ||||
|         [applyOnClose]="applyOnClose" | ||||
|         (open)="openStoragePathDropdown()" | ||||
| @@ -67,7 +71,7 @@ | ||||
|   <div class="col-auto ms-auto mb-2 mb-xl-0 d-flex"> | ||||
|     <div class="btn-toolbar me-2"> | ||||
|  | ||||
|       <button type="button" class="btn btn-sm btn-outline-primary me-2" (click)="setPermissions()"> | ||||
|       <button type="button" class="btn btn-sm btn-outline-primary me-2" (click)="setPermissions()" [disabled]="!userOwnsAll"> | ||||
|         <svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor"> | ||||
|           <use xlink:href="assets/bootstrap-icons.svg#person-fill-lock" /> | ||||
|         </svg> <ng-container i18n>Permissions</ng-container> | ||||
| @@ -93,11 +97,11 @@ | ||||
|               <span class="visually-hidden">Preparing download...</span> | ||||
|             </div> | ||||
|           </button> | ||||
|           <button ngbDropdownItem (click)="redoOcrSelected()" i18n>Redo OCR</button> | ||||
|           <button ngbDropdownItem (click)="redoOcrSelected()" [disabled]="!userCanEditAll" i18n>Redo OCR</button> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|     <button type="button" class="btn btn-sm btn-outline-danger" (click)="applyDelete()" *ifPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }"> | ||||
|     <button type="button" class="btn btn-sm btn-outline-danger" (click)="applyDelete()" *ifPermissions="{ action: PermissionAction.Delete, type: PermissionType.Document }" [disabled]="!userOwnsAll"> | ||||
|       <svg width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor"> | ||||
|         <use xlink:href="assets/bootstrap-icons.svg#trash" /> | ||||
|       </svg> <ng-container i18n>Delete</ng-container> | ||||
|   | ||||
| @@ -27,6 +27,7 @@ import { PaperlessStoragePath } from 'src/app/data/paperless-storage-path' | ||||
| import { SETTINGS_KEYS } from 'src/app/data/paperless-uisettings' | ||||
| import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' | ||||
| import { PermissionsDialogComponent } from '../../common/permissions-dialog/permissions-dialog.component' | ||||
| import { PermissionsService } from 'src/app/services/permissions.service' | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-bulk-editor', | ||||
| @@ -55,7 +56,8 @@ export class BulkEditorComponent extends ComponentWithPermissions { | ||||
|     private openDocumentService: OpenDocumentsService, | ||||
|     private settings: SettingsService, | ||||
|     private toastService: ToastService, | ||||
|     private storagePathService: StoragePathService | ||||
|     private storagePathService: StoragePathService, | ||||
|     private permissionService: PermissionsService | ||||
|   ) { | ||||
|     super() | ||||
|   } | ||||
| @@ -67,6 +69,25 @@ export class BulkEditorComponent extends ComponentWithPermissions { | ||||
|     SETTINGS_KEYS.BULK_EDIT_CONFIRMATION_DIALOGS | ||||
|   ) | ||||
|  | ||||
|   get userCanEditAll(): boolean { | ||||
|     let canEdit: boolean = true | ||||
|     const docs = this.list.documents.filter((d) => this.list.selected.has(d.id)) | ||||
|     canEdit = docs.every((d) => | ||||
|       this.permissionService.currentUserHasObjectPermissions( | ||||
|         this.PermissionAction.Change, | ||||
|         d | ||||
|       ) | ||||
|     ) | ||||
|     return canEdit | ||||
|   } | ||||
|  | ||||
|   get userOwnsAll(): boolean { | ||||
|     let ownsAll: boolean = true | ||||
|     const docs = this.list.documents.filter((d) => this.list.selected.has(d.id)) | ||||
|     ownsAll = docs.every((d) => this.permissionService.currentUserOwnsObject(d)) | ||||
|     return ownsAll | ||||
|   } | ||||
|  | ||||
|   ngOnInit() { | ||||
|     this.tagService | ||||
|       .listAll() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Shamoon
					Michael Shamoon