},
},
},
+ {
+ path: 'documents/:id/:section',
+ component: DocumentDetailComponent,
+ canActivate: [PermissionsGuard],
+ data: {
+ requiredPermission: {
+ action: PermissionAction.View,
+ type: PermissionType.Document,
+ },
+ },
+ },
{
path: 'asn/:id',
component: DocumentAsnComponent,
},
},
{
- path: 'tasks',
- component: TasksComponent,
+ path: 'settings/:section',
+ component: SettingsComponent,
+ canDeactivate: [DirtyFormGuard],
canActivate: [PermissionsGuard],
data: {
requiredPermission: {
action: PermissionAction.View,
- type: PermissionType.PaperlessTask,
+ type: PermissionType.UISettings,
},
},
},
path: 'settings/:section',
component: SettingsComponent,
canDeactivate: [DirtyFormGuard],
+ },
+ {
+ path: 'tasks',
+ component: TasksComponent,
canActivate: [PermissionsGuard],
data: {
requiredPermission: {
action: PermissionAction.View,
- type: PermissionType.UISettings,
+ type: PermissionType.PaperlessTask,
},
},
},
- {
- path: 'settings/:section',
- component: SettingsComponent,
- canDeactivate: [DirtyFormGuard],
- },
{ path: 'tasks', component: TasksComponent },
],
},
<form [formGroup]='documentForm' (ngSubmit)="save()">
- <ul ngbNav #nav="ngbNav" class="nav-tabs">
- <li [ngbNavItem]="1">
+ <ul ngbNav #nav="ngbNav" class="nav-tabs" (navChange)="onNavChange($event)" [(activeId)]="activeNavID">
+ <li [ngbNavItem]="DocumentDetailNavIDs.Details">
<a ngbNavLink i18n>Details</a>
<ng-template ngbNavContent>
</ng-template>
</li>
- <li [ngbNavItem]="2">
+ <li [ngbNavItem]="DocumentDetailNavIDs.Content">
<a ngbNavLink i18n>Content</a>
<ng-template ngbNavContent>
<div class="mb-3">
</ng-template>
</li>
- <li [ngbNavItem]="3">
+ <li [ngbNavItem]="DocumentDetailNavIDs.Metadata">
<a ngbNavLink i18n>Metadata</a>
<ng-template ngbNavContent>
</ng-template>
</li>
- <li [ngbNavItem]="4" class="d-md-none">
+ <li [ngbNavItem]="DocumentDetailNavIDs.Preview" class="d-md-none">
<a ngbNavLink i18n>Preview</a>
<ng-template ngbNavContent *ngIf="!pdfPreview.offsetParent">
<div class="position-relative">
</ng-template>
</li>
- <li [ngbNavItem]="5" *ngIf="commentsEnabled">
+ <li [ngbNavItem]="DocumentDetailNavIDs.Comments" *ngIf="commentsEnabled">
<a ngbNavLink i18n>Comments <span *ngIf="document?.n_comments" class="badge text-bg-secondary ms-1">{{document.n_comments}}</span></a>
<ng-template ngbNavContent>
<app-document-comments [documentId]="documentId" (updated)="commentsUpdated($event)"></app-document-comments>
</ng-template>
</li>
- <li [ngbNavItem]="6" *appIfOwner="document">
+ <li [ngbNavItem]="DocumentDetailNavIDs.Permissions" *appIfOwner="document">
<a ngbNavLink i18n>Permissions</a>
<ng-template ngbNavContent>
<div class="mb-3">
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { ActivatedRoute, Router } from '@angular/router'
-import { NgbModal, NgbNav } from '@ng-bootstrap/ng-bootstrap'
+import { NgbModal, NgbNav, NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap'
import { PaperlessCorrespondent } from 'src/app/data/paperless-correspondent'
import { PaperlessDocument } from 'src/app/data/paperless-document'
import { PaperlessDocumentMetadata } from 'src/app/data/paperless-document-metadata'
import { PaperlessUser } from 'src/app/data/paperless-user'
import { UserService } from 'src/app/services/rest/user.service'
+enum DocumentDetailNavIDs {
+ Details = 1,
+ Content = 2,
+ Metadata = 3,
+ Preview = 4,
+ Comments = 5,
+ Permissions = 6,
+}
+
@Component({
selector: 'app-document-detail',
templateUrl: './document-detail.component.html',
PermissionAction = PermissionAction
PermissionType = PermissionType
+ DocumentDetailNavIDs = DocumentDetailNavIDs
+ activeNavID: number
constructor(
private documentsService: DocumentService,
this.router.navigate(['404'])
},
})
+
+ this.route.paramMap.subscribe((paramMap) => {
+ const section = paramMap.get('section')
+ if (section) {
+ const navIDKey: string = Object.keys(DocumentDetailNavIDs).find(
+ (navID) => navID.toLowerCase() == section
+ )
+ if (navIDKey) {
+ this.activeNavID = DocumentDetailNavIDs[navIDKey]
+ }
+ }
+ })
}
ngOnDestroy(): void {
this.unsubscribeNotifier.complete()
}
+ onNavChange(navChangeEvent: NgbNavChangeEvent) {
+ const [foundNavIDkey] = Object.entries(DocumentDetailNavIDs).find(
+ ([, navIDValue]) => navIDValue == navChangeEvent.nextId
+ )
+ if (foundNavIDkey)
+ this.router.navigate([
+ 'documents',
+ this.documentId,
+ foundNavIDkey.toLowerCase(),
+ ])
+ }
+
updateComponent(doc: PaperlessDocument) {
this.document = doc
this.requiresPassword = false
<div class="list-group list-group-horizontal border-0 card-info ms-md-auto mt-2 mt-md-0">
- <button *ngIf="document.n_comments" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2" title="View comments" i18n-title>
+ <button routerLink="/documents/{{document.id}}/comments" *ngIf="document.n_comments" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2" title="View comments" i18n-title>
<svg class="metadata-icon me-2 text-muted" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
</svg>
}
}
- .metadata-icon {
- width: 0.9rem;
- height: 0.9rem;
- padding: 0.05rem;
- }
-
.search-score {
padding-top: 0.35rem !important;
}
</div>
</div>
- <div *ngIf="document.n_comments" class="document-card-comments pe-none py-2 px-1">
- <span class="badge rounded-pill bg-light border text-primary">
+ <a routerLink="/documents/{{document.id}}/comments" *ngIf="document.n_comments" class="document-card-comments py-2 px-1">
+ <span class="badge rounded-pill bg-light border text-primary">
<svg class="metadata-icon ms-1 me-1" fill="currentColor">
<use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
</svg>
{{document.n_comments}}</span>
- </div>
+ </a>
<div class="card-body p-2">
<p class="card-text">
.doc-img {
object-fit: cover;
object-position: top left;
- height: 175px;
+ height: 180px;
mix-blend-mode: multiply;
}
}
}
-.metadata-icon {
- width: 0.9rem;
- height: 0.9rem;
- padding: 0.05rem;
-}
-
.card-footer .btn {
padding-top: .10rem;
}
[currentSortReverse]="list.sortReverse"
(sort)="onSort($event)"
i18n>Title</th>
+ <th class="d-none d-xl-table-cell"
+ appSortable="n_comments"
+ [currentSortField]="list.sortField"
+ [currentSortReverse]="list.sortReverse"
+ (sort)="onSort($event)"
+ i18n>Comments</th>
<th class="d-none d-xl-table-cell"
appSortable="document_type__name"
[currentSortField]="list.sortField"
<a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
<app-tag [tag]="t" *ngFor="let t of d.tags$ | async" class="ms-1" clickable="true" linkTitle="Filter by tag" i18n-linkTitle (click)="clickTag(t.id);$event.stopPropagation()"></app-tag>
</td>
+ <td class="d-none d-xl-table-cell">
+ <a routerLink="/documents/{{d.id}}/comments" *ngIf="d.n_comments" class="btn btn-sm p-0">
+ <span class="badge rounded-pill bg-light border text-primary">
+ <svg class="metadata-icon ms-1 me-1" fill="currentColor">
+ <use xlink:href="assets/bootstrap-icons.svg#chat-left-text"/>
+ </svg>
+ {{d.n_comments}}</span>
+ </a>
+ </td>
<td class="d-none d-xl-table-cell">
<ng-container *ngIf="d.document_type">
<a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>
height: 12px;
}
+.metadata-icon {
+ width: 0.9rem;
+ height: 0.9rem;
+ padding: 0.05rem;
+}
+
table.table {
color: var(--bs-body-color);