Basic toggling of fields

This commit is contained in:
shamoon 2024-04-17 23:21:39 -07:00
parent 4ffe5d34f0
commit af94eed042
14 changed files with 346 additions and 171 deletions

View File

@ -140,6 +140,7 @@ import {
calendar, calendar,
calendarEvent, calendarEvent,
cardChecklist, cardChecklist,
cardHeading,
caretDown, caretDown,
caretUp, caretUp,
chatLeftText, chatLeftText,
@ -234,6 +235,7 @@ const icons = {
calendar, calendar,
calendarEvent, calendarEvent,
cardChecklist, cardChecklist,
cardHeading,
caretDown, caretDown,
caretUp, caretUp,
chatLeftText, chatLeftText,

View File

@ -351,8 +351,8 @@
</pngx-confirm-button> </pngx-confirm-button>
</div> </div>
</div> </div>
@if (savedViewGroup.get(view.id.toString()).get('show_on_dashboard').value) {
<div class="row"> <div class="row">
@if (savedViewGroup.get(view.id.toString()).get('show_on_dashboard').value) {
<div class="col"> <div class="col">
<pngx-input-number i18n-title title="Widget list limit" [showAdd]="false" formControlName="page_size"></pngx-input-number> <pngx-input-number i18n-title title="Widget list limit" [showAdd]="false" formControlName="page_size"></pngx-input-number>
</div> </div>
@ -363,11 +363,11 @@
<option [ngValue]="DashboardViewMode.SMALL_CARDS" i18n>Cards</option> <option [ngValue]="DashboardViewMode.SMALL_CARDS" i18n>Cards</option>
</select> </select>
</div> </div>
@if (savedViewGroup.get(view.id.toString()).get('display_mode').value === DashboardViewMode.TABLE && documentDisplayFields) { }
@if (documentDisplayFields) {
<pngx-input-drag-drop-select i18n-title title="Show" [items]="documentDisplayFields" formControlName="document_display_fields"></pngx-input-drag-drop-select> <pngx-input-drag-drop-select i18n-title title="Show" [items]="documentDisplayFields" formControlName="document_display_fields"></pngx-input-drag-drop-select>
} }
</div> </div>
}
</div> </div>
</li> </li>
} }

View File

@ -117,7 +117,9 @@ export class SettingsComponent
savedViews: SavedView[] savedViews: SavedView[]
SettingsNavIDs = SettingsNavIDs SettingsNavIDs = SettingsNavIDs
documentDisplayFields: any[] get documentDisplayFields() {
return this.settings.allDocumentDisplayFields
}
store: BehaviorSubject<any> store: BehaviorSubject<any>
storeSub: Subscription storeSub: Subscription
@ -225,24 +227,6 @@ export class SettingsComponent
}) })
} }
if (
this.permissionsService.currentUserCan(
PermissionAction.View,
PermissionType.CustomField
)
) {
this.customFieldsService.listAll().subscribe((r) => {
this.documentDisplayFields = DOCUMENT_DISPLAY_FIELDS.concat(
r.results.map((field) => {
return {
id: `${DocumentDisplayField.CUSTOM_FIELD}${field.id}` as any,
name: field.name,
}
})
)
})
}
this.activatedRoute.paramMap.subscribe((paramMap) => { this.activatedRoute.paramMap.subscribe((paramMap) => {
const section = paramMap.get('section') const section = paramMap.get('section')
if (section) { if (section) {

View File

@ -14,7 +14,7 @@
<thead> <thead>
<tr> <tr>
@for (column of savedView.document_display_fields; track column; let i = $index) { @for (column of savedView.document_display_fields; track column; let i = $index) {
@if (visibleColumns.includes(column)) { @if (activeDisplayFields.has(column)) {
<th <th
scope="col" scope="col"
[ngClass]="{ [ngClass]="{
@ -31,7 +31,7 @@
@for (doc of documents; track doc.id) { @for (doc of documents; track doc.id) {
<tr> <tr>
@for (column of savedView.document_display_fields; track column; let i = $index) { @for (column of savedView.document_display_fields; track column; let i = $index) {
@if (visibleColumns.includes(column)) { @if (activeDisplayFields.has(column)) {
<td class="py-2 py-md-3 position-relative" [ngClass]="{ 'd-none d-md-table-cell': i > 1 }"> <td class="py-2 py-md-3 position-relative" [ngClass]="{ 'd-none d-md-table-cell': i > 1 }">
@switch (column) { @switch (column) {
@case (DashboardViewTableColumn.ADDED) { @case (DashboardViewTableColumn.ADDED) {
@ -114,7 +114,16 @@
} @else if (documents.length && savedView.display_mode === DashboardViewMode.SMALL_CARDS) { } @else if (documents.length && savedView.display_mode === DashboardViewMode.SMALL_CARDS) {
<div class="row row-cols-paperless-cards my-n2"> <div class="row row-cols-paperless-cards my-n2">
@for (d of documents; track d.id) { @for (d of documents; track d.id) {
<pngx-document-card-small class="p-0" (dblClickDocument)="openDocumentDetail(d)" [document]="d" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)" (clickStoragePath)="clickStoragePath($event)" (clickDocumentType)="clickDocumentType($event)"></pngx-document-card-small> <pngx-document-card-small
class="p-0"
(dblClickDocument)="openDocumentDetail(d)"
[document]="d"
[displayFields]="activeDisplayFields"
(clickTag)="clickTag($event)"
(clickCorrespondent)="clickCorrespondent($event)"
(clickStoragePath)="clickStoragePath($event)"
(clickDocumentType)="clickDocumentType($event)">
</pngx-document-card-small>
} }
</div> </div>
} @else { } @else {

View File

@ -344,51 +344,51 @@ describe('SavedViewWidgetComponent', () => {
it('should check if column is visible including permissions', () => { it('should check if column is visible including permissions', () => {
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.TITLE) component.activeDisplayFields.includes(DocumentDisplayField.TITLE)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.CREATED) component.activeDisplayFields.includes(DocumentDisplayField.CREATED)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.ADDED) component.activeDisplayFields.includes(DocumentDisplayField.ADDED)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.TAGS) component.activeDisplayFields.includes(DocumentDisplayField.TAGS)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.CORRESPONDENT) component.activeDisplayFields.includes(DocumentDisplayField.CORRESPONDENT)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.DOCUMENT_TYPE) component.activeDisplayFields.includes(DocumentDisplayField.DOCUMENT_TYPE)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.STORAGE_PATH) component.activeDisplayFields.includes(DocumentDisplayField.STORAGE_PATH)
).toBeTruthy() ).toBeTruthy()
expect( expect(
component.visibleColumns.includes( component.activeDisplayFields.includes(
`${DocumentDisplayField.CUSTOM_FIELD}11` as any `${DocumentDisplayField.CUSTOM_FIELD}11` as any
) )
).toBeTruthy() ).toBeTruthy()
component.visibleColumns = [] component.activeDisplayFields = []
jest jest
.spyOn(component.permissionsService, 'currentUserCan') .spyOn(component.permissionsService, 'currentUserCan')
.mockReturnValue(false) .mockReturnValue(false)
component.ngOnInit() component.ngOnInit()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.TAGS) component.activeDisplayFields.includes(DocumentDisplayField.TAGS)
).toBeFalsy() ).toBeFalsy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.CORRESPONDENT) component.activeDisplayFields.includes(DocumentDisplayField.CORRESPONDENT)
).toBeFalsy() ).toBeFalsy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.DOCUMENT_TYPE) component.activeDisplayFields.includes(DocumentDisplayField.DOCUMENT_TYPE)
).toBeFalsy() ).toBeFalsy()
expect( expect(
component.visibleColumns.includes(DocumentDisplayField.STORAGE_PATH) component.activeDisplayFields.includes(DocumentDisplayField.STORAGE_PATH)
).toBeFalsy() ).toBeFalsy()
expect( expect(
component.visibleColumns.includes( component.activeDisplayFields.includes(
`${DocumentDisplayField.CUSTOM_FIELD}11` as any `${DocumentDisplayField.CUSTOM_FIELD}11` as any
) )
).toBeFalsy() ).toBeFalsy()

View File

@ -79,11 +79,11 @@ export class SavedViewWidgetComponent
mouseOnPreview = false mouseOnPreview = false
popoverHidden = true popoverHidden = true
visibleColumns: DocumentDisplayField[] = [ activeDisplayFields: Set<DocumentDisplayField> = new Set([
DocumentDisplayField.TITLE, DocumentDisplayField.TITLE,
DocumentDisplayField.CREATED, DocumentDisplayField.CREATED,
DocumentDisplayField.ADDED, DocumentDisplayField.ADDED,
] ])
docLinkDocuments: Document[] = [] docLinkDocuments: Document[] = []
@ -122,7 +122,7 @@ export class SavedViewWidgetComponent
type && type &&
this.permissionsService.currentUserCan(PermissionAction.View, type) this.permissionsService.currentUserCan(PermissionAction.View, type)
) )
this.visibleColumns.push(column) this.activeDisplayFields.add(column)
}) })
} }

View File

@ -15,7 +15,7 @@
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h5 class="card-title"> <h5 class="card-title">
@if (document.correspondent) { @if (displayFields.has(DocumentDisplayField.CORRESPONDENT) && document.correspondent) {
@if (clickCorrespondent.observers.length ) { @if (clickCorrespondent.observers.length ) {
<a title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a> <a title="Filter by correspondent" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name}}</a>
} @else { } @else {
@ -23,10 +23,14 @@
} }
: :
} }
@if (displayFields.has(DocumentDisplayField.TITLE)) {
{{document.title | documentTitle}} {{document.title | documentTitle}}
}
@if (displayFields.has(DocumentDisplayField.TAGS)) {
@for (t of document.tags$ | async; track t) { @for (t of document.tags$ | async; track t) {
<pngx-tag [tag]="t" linkTitle="Filter by tag" i18n-linkTitle class="ms-1" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="clickTag.observers.length"></pngx-tag> <pngx-tag [tag]="t" linkTitle="Filter by tag" i18n-linkTitle class="ms-1" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="clickTag.observers.length"></pngx-tag>
} }
}
</h5> </h5>
</div> </div>
<p class="card-text"> <p class="card-text">
@ -66,28 +70,29 @@
</div> </div>
<div class="list-group list-group-horizontal border-0 card-info ms-md-auto mt-2 mt-md-0"> <div class="list-group list-group-horizontal border-0 card-info ms-md-auto mt-2 mt-md-0">
@if (notesEnabled && document.notes.length) { @if (displayFields.has(DocumentDisplayField.NOTES) && notesEnabled && document.notes.length) {
<button routerLink="/documents/{{document.id}}/notes" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2 d-flex align-items-center" title="View notes" i18n-title> <button routerLink="/documents/{{document.id}}/notes" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2 d-flex align-items-center" title="View notes" i18n-title>
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="chat-left-text"></i-bs><small i18n>{{document.notes.length}} Notes</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="chat-left-text"></i-bs><small i18n>{{document.notes.length}} Notes</small>
</button> </button>
} }
@if (document.document_type) { @if (displayFields.has(DocumentDisplayField.DOCUMENT_TYPE) && document.document_type) {
<button type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2 d-flex align-items-center" title="Filter by document type" i18n-title <button type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2 d-flex align-items-center" title="Filter by document type" i18n-title
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()"> (click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="file-earmark"></i-bs><small>{{(document.document_type$ | async)?.name}}</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="file-earmark"></i-bs><small>{{(document.document_type$ | async)?.name}}</small>
</button> </button>
} }
@if (document.storage_path) { @if (displayFields.has(DocumentDisplayField.STORAGE_PATH) && document.storage_path) {
<button type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2 d-flex align-items-center" title="Filter by storage path" i18n-title <button type="button" class="list-group-item btn btn-sm bg-light text-dark p-1 border-0 me-2 d-flex align-items-center" title="Filter by storage path" i18n-title
(click)="clickStoragePath.emit(document.storage_path);$event.stopPropagation()"> (click)="clickStoragePath.emit(document.storage_path);$event.stopPropagation()">
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="archive"></i-bs><small>{{(document.storage_path$ | async)?.name}}</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="archive"></i-bs><small>{{(document.storage_path$ | async)?.name}}</small>
</button> </button>
} }
@if (document.archive_serial_number | isNumber) { @if (displayFields.has(DocumentDisplayField.ASN) && document.archive_serial_number | isNumber) {
<div class="list-group-item me-2 bg-light text-dark p-1 border-0 d-flex align-items-center"> <div class="list-group-item me-2 bg-light text-dark p-1 border-0 d-flex align-items-center">
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="upc-scan"></i-bs><small>#{{document.archive_serial_number}}</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="upc-scan"></i-bs><small>#{{document.archive_serial_number}}</small>
</div> </div>
} }
@if (displayFields.has(DocumentDisplayField.CREATED) || displayFields.has(DocumentDisplayField.ADDED)) {
<ng-template #dateTooltip> <ng-template #dateTooltip>
<div class="d-flex flex-column text-light"> <div class="d-flex flex-column text-light">
<span i18n>Created: {{ document.created | customDate }}</span> <span i18n>Created: {{ document.created | customDate }}</span>
@ -96,14 +101,18 @@
</div> </div>
</ng-template> </ng-template>
<div class="list-group-item bg-light text-dark p-1 border-0 d-flex align-items-center" [ngbTooltip]="dateTooltip"> <div class="list-group-item bg-light text-dark p-1 border-0 d-flex align-items-center" [ngbTooltip]="dateTooltip">
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="calendar-event"></i-bs><small>{{document.created_date | customDate:'mediumDate'}}</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="calendar-event"></i-bs><small>
@if (displayFields.has(DocumentDisplayField.CREATED)) { {{document.created_date | customDate:'mediumDate'}} }
@else { {{document.added | customDate:'mediumDate'}} }
</small>
</div> </div>
@if (document.owner && document.owner !== settingsService.currentUser.id) { }
@if (displayFields.has(DocumentDisplayField.OWNER) && document.owner && document.owner !== settingsService.currentUser.id) {
<div class="list-group-item bg-light text-dark p-1 border-0 d-flex align-items-center"> <div class="list-group-item bg-light text-dark p-1 border-0 d-flex align-items-center">
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="person-fill-lock"></i-bs><small>{{document.owner | username}}</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="person-fill-lock"></i-bs><small>{{document.owner | username}}</small>
</div> </div>
} }
@if (document.is_shared_by_requester) { @if (displayFields.has(DocumentDisplayField.SHARED) && document.is_shared_by_requester) {
<div class="list-group-item bg-light text-dark p-1 border-0 d-flex align-items-center"> <div class="list-group-item bg-light text-dark p-1 border-0 d-flex align-items-center">
<i-bs width=".9em" height=".9em" class="me-2 text-muted" name="people-fill"></i-bs><small i18n>Shared</small> <i-bs width=".9em" height=".9em" class="me-2 text-muted" name="people-fill"></i-bs><small i18n>Shared</small>
</div> </div>

View File

@ -11,6 +11,7 @@ import { SettingsService } from 'src/app/services/settings.service'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
import { DocumentDisplayField } from 'src/app/data/saved-view'
@Component({ @Component({
selector: 'pngx-document-card-large', selector: 'pngx-document-card-large',
@ -18,6 +19,8 @@ import { ComponentWithPermissions } from '../../with-permissions/with-permission
styleUrls: ['./document-card-large.component.scss'], styleUrls: ['./document-card-large.component.scss'],
}) })
export class DocumentCardLargeComponent extends ComponentWithPermissions { export class DocumentCardLargeComponent extends ComponentWithPermissions {
DocumentDisplayField = DocumentDisplayField
constructor( constructor(
private documentService: DocumentService, private documentService: DocumentService,
public settingsService: SettingsService public settingsService: SettingsService
@ -28,6 +31,9 @@ export class DocumentCardLargeComponent extends ComponentWithPermissions {
@Input() @Input()
selected = false selected = false
@Input()
displayFields: Set<DocumentDisplayField>
@Output() @Output()
toggleSelected = new EventEmitter() toggleSelected = new EventEmitter()

View File

@ -10,6 +10,7 @@
</div> </div>
</div> </div>
@if (displayFields?.has(DocumentDisplayField.TAGS)) {
<div class="tags d-flex flex-column text-end position-absolute me-1 fs-6"> <div class="tags d-flex flex-column text-end position-absolute me-1 fs-6">
@for (t of getTagsLimited$() | async; track t) { @for (t of getTagsLimited$() | async; track t) {
<pngx-tag [tag]="t" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="true" linkTitle="Toggle tag filter" i18n-linkTitle></pngx-tag> <pngx-tag [tag]="t" (click)="clickTag.emit(t.id);$event.stopPropagation()" [clickable]="true" linkTitle="Toggle tag filter" i18n-linkTitle></pngx-tag>
@ -20,9 +21,10 @@
</div> </div>
} }
</div> </div>
}
</div> </div>
@if (notesEnabled && document.notes.length) { @if (displayFields.has(DocumentDisplayField.NOTES) && notesEnabled && document.notes.length) {
<a routerLink="/documents/{{document.id}}/notes" class="document-card-notes py-2 px-1"> <a routerLink="/documents/{{document.id}}/notes" class="document-card-notes py-2 px-1">
<span class="badge rounded-pill bg-light border text-primary"> <span class="badge rounded-pill bg-light border text-primary">
<i-bs width="1.2em" height="1.2em" class="ms-1 me-1" name="chat-left-text"></i-bs> <i-bs width="1.2em" height="1.2em" class="ms-1 me-1" name="chat-left-text"></i-bs>
@ -32,28 +34,31 @@
<div class="card-body bg-light p-2"> <div class="card-body bg-light p-2">
<p class="card-text"> <p class="card-text">
@if (document.correspondent) { @if (displayFields.has(DocumentDisplayField.CORRESPONDENT) && document.correspondent) {
<a title="Toggle correspondent filter" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name ?? privateName}}</a>: <a title="Toggle correspondent filter" i18n-title (click)="clickCorrespondent.emit(document.correspondent);$event.stopPropagation()" class="fw-bold btn-link">{{(document.correspondent$ | async)?.name ?? privateName}}</a>:
} }
@if (displayFields.has(DocumentDisplayField.TITLE)) {
{{document.title | documentTitle}} {{document.title | documentTitle}}
}
</p> </p>
</div> </div>
<div class="card-footer pt-0 pb-2 px-2"> <div class="card-footer pt-0 pb-2 px-2">
<div class="list-group list-group-flush border-0 pt-1 pb-2 card-info"> <div class="list-group list-group-flush border-0 pt-1 pb-2 card-info">
@if (document.document_type) { @if (displayFields.has(DocumentDisplayField.DOCUMENT_TYPE) && document.document_type) {
<button type="button" class="list-group-item list-group-item-action bg-transparent ps-0 p-1 border-0" title="Toggle document type filter" i18n-title <button type="button" class="list-group-item list-group-item-action bg-transparent ps-0 p-1 border-0" title="Toggle document type filter" i18n-title
(click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()"> (click)="clickDocumentType.emit(document.document_type);$event.stopPropagation()">
<i-bs width="1em" height="1em" class="me-2 text-muted" name="file-earmark"></i-bs> <i-bs width="1em" height="1em" class="me-2 text-muted" name="file-earmark"></i-bs>
<small>{{(document.document_type$ | async)?.name ?? privateName}}</small> <small>{{(document.document_type$ | async)?.name ?? privateName}}</small>
</button> </button>
} }
@if (document.storage_path) { @if (displayFields.has(DocumentDisplayField.STORAGE_PATH) && document.storage_path) {
<button type="button" class="list-group-item list-group-item-action bg-transparent ps-0 p-1 border-0" title="Toggle storage path filter" i18n-title <button type="button" class="list-group-item list-group-item-action bg-transparent ps-0 p-1 border-0" title="Toggle storage path filter" i18n-title
(click)="clickStoragePath.emit(document.storage_path);$event.stopPropagation()"> (click)="clickStoragePath.emit(document.storage_path);$event.stopPropagation()">
<i-bs width="1em" height="1em" class="me-2 text-muted" name="folder"></i-bs> <i-bs width="1em" height="1em" class="me-2 text-muted" name="folder"></i-bs>
<small>{{(document.storage_path$ | async)?.name ?? privateName}}</small> <small>{{(document.storage_path$ | async)?.name ?? privateName}}</small>
</button> </button>
} }
@if (displayFields.has(DocumentDisplayField.CREATED) || displayFields.has(DocumentDisplayField.ADDED)) {
<div class="list-group-item bg-transparent p-0 border-0 d-flex flex-wrap-reverse justify-content-between"> <div class="list-group-item bg-transparent p-0 border-0 d-flex flex-wrap-reverse justify-content-between">
<ng-template #dateTooltip> <ng-template #dateTooltip>
<div class="d-flex flex-column text-light"> <div class="d-flex flex-column text-light">
@ -64,22 +69,26 @@
</ng-template> </ng-template>
<div class="ps-0 p-1" placement="top" [ngbTooltip]="dateTooltip"> <div class="ps-0 p-1" placement="top" [ngbTooltip]="dateTooltip">
<i-bs width="1em" height="1em" class="me-2 text-muted" name="calendar-event"></i-bs> <i-bs width="1em" height="1em" class="me-2 text-muted" name="calendar-event"></i-bs>
<small>{{document.created_date | customDate:'mediumDate'}}</small> <small>
@if (displayFields.has(DocumentDisplayField.CREATED)) { {{document.created | customDate:'mediumDate'}} }
@else { {{document.added | customDate:'mediumDate'}} }
</small>
</div> </div>
</div> </div>
@if (document.archive_serial_number | isNumber) { }
@if (displayFields.has(DocumentDisplayField.ASN) && document.archive_serial_number | isNumber) {
<div class="ps-0 p-1"> <div class="ps-0 p-1">
<i-bs width="1em" height="1em" class="me-2 text-muted" name="upc-scan"></i-bs> <i-bs width="1em" height="1em" class="me-2 text-muted" name="upc-scan"></i-bs>
<small>#{{document.archive_serial_number}}</small> <small>#{{document.archive_serial_number}}</small>
</div> </div>
} }
@if (document.owner && document.owner !== settingsService.currentUser.id) { @if (displayFields.has(DocumentDisplayField.OWNER) && document.owner && document.owner !== settingsService.currentUser.id) {
<div class="ps-0 p-1"> <div class="ps-0 p-1">
<i-bs width="1em" height="1em" class="me-2 text-muted" name="person-fill-lock"></i-bs> <i-bs width="1em" height="1em" class="me-2 text-muted" name="person-fill-lock"></i-bs>
<small>{{document.owner | username}}</small> <small>{{document.owner | username}}</small>
</div> </div>
} }
@if (document.is_shared_by_requester) { @if (displayFields.has(DocumentDisplayField.SHARED) && document.is_shared_by_requester) {
<div class="ps-0 p-1"> <div class="ps-0 p-1">
<i-bs width="1em" height="1em" class="me-2 text-muted" name="people-fill"></i-bs> <i-bs width="1em" height="1em" class="me-2 text-muted" name="people-fill"></i-bs>
<small i18n>Shared</small> <small i18n>Shared</small>

View File

@ -12,6 +12,7 @@ import { SettingsService } from 'src/app/services/settings.service'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
import { DocumentDisplayField } from 'src/app/data/saved-view'
@Component({ @Component({
selector: 'pngx-document-card-small', selector: 'pngx-document-card-small',
@ -19,6 +20,8 @@ import { ComponentWithPermissions } from '../../with-permissions/with-permission
styleUrls: ['./document-card-small.component.scss'], styleUrls: ['./document-card-small.component.scss'],
}) })
export class DocumentCardSmallComponent extends ComponentWithPermissions { export class DocumentCardSmallComponent extends ComponentWithPermissions {
DocumentDisplayField = DocumentDisplayField
constructor( constructor(
private documentService: DocumentService, private documentService: DocumentService,
public settingsService: SettingsService public settingsService: SettingsService
@ -35,6 +38,9 @@ export class DocumentCardSmallComponent extends ComponentWithPermissions {
@Input() @Input()
document: Document document: Document
@Input()
displayFields: Set<DocumentDisplayField>
@Output() @Output()
dblClickDocument = new EventEmitter() dblClickDocument = new EventEmitter()

View File

@ -11,8 +11,24 @@
<button ngbDropdownItem (click)="list.selectAll()" i18n>Select all</button> <button ngbDropdownItem (click)="list.selectAll()" i18n>Select all</button>
</div> </div>
</div> </div>
<div ngbDropdown class="d-flex">
<button class="btn btn-sm btn-outline-primary" id="dropdownDisplayFields" ngbDropdownToggle>
<i-bs name="card-heading"></i-bs>
<div class="d-none d-sm-inline">&nbsp;<ng-container i18n>Show</ng-container></div>
</button>
<div ngbDropdownMenu aria-labelledby="dropdownDisplayFields" class="shadow">
<div class="px-3">
@for (field of settingsService.allDocumentDisplayFields; track field.id) {
<div class="form-check small">
<input type="checkbox" class="form-check-input" id="displayField{{field.id}}" [checked]="activeDisplayFields.has(field.id)" (change)="toggleDisplayField(field.id)">
<label class="form-check-label small" for="displayField{{field.id}}">{{field.name}}</label>
</div>
}
</div>
</div>
</div>
<div class="btn-group flex-fill" role="group"> <div class="btn-group flex-fill" role="group">
<input type="radio" class="btn-check" [(ngModel)]="displayMode" value="details" (ngModelChange)="saveDisplayMode()" id="displayModeDetails" name="displayModeDetails"> <input type="radio" class="btn-check" [(ngModel)]="displayMode" value="table" (ngModelChange)="saveDisplayMode()" id="displayModeDetails" name="displayModeDetails">
<label for="displayModeDetails" class="btn btn-outline-primary btn-sm"> <label for="displayModeDetails" class="btn btn-outline-primary btn-sm">
<i-bs name="list-ul"></i-bs> <i-bs name="list-ul"></i-bs>
</label> </label>
@ -125,15 +141,26 @@
@if (displayMode === 'largeCards') { @if (displayMode === 'largeCards') {
<div> <div>
@for (d of list.documents; track trackByDocumentId($index, d)) { @for (d of list.documents; track trackByDocumentId($index, d)) {
<pngx-document-card-large [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" (dblClickDocument)="openDocumentDetail(d)" [document]="d" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)" (clickDocumentType)="clickDocumentType($event)" (clickStoragePath)="clickStoragePath($event)" (clickMoreLike)="clickMoreLike(d.id)"> <pngx-document-card-large
[selected]="list.isSelected(d)"
(toggleSelected)="toggleSelected(d, $event)"
(dblClickDocument)="openDocumentDetail(d)"
[document]="d"
[displayFields]="activeDisplayFields"
(clickTag)="clickTag($event)"
(clickCorrespondent)="clickCorrespondent($event)"
(clickDocumentType)="clickDocumentType($event)"
(clickStoragePath)="clickStoragePath($event)"
(clickMoreLike)="clickMoreLike(d.id)">
</pngx-document-card-large> </pngx-document-card-large>
} }
</div> </div>
} }
@if (displayMode === 'details') { @if (displayMode === 'details' || displayMode === 'table') {
<table class="table table-sm align-middle border shadow-sm"> <table class="table table-sm align-middle border shadow-sm">
<thead> <thead>
<th></th> <th></th>
@if (activeDisplayFields.has(DocumentDisplayField.ASN)) {
<th class="d-none d-lg-table-cell" <th class="d-none d-lg-table-cell"
pngxSortable="archive_serial_number" pngxSortable="archive_serial_number"
title="Sort by ASN" i18n-title title="Sort by ASN" i18n-title
@ -141,7 +168,8 @@
[currentSortReverse]="list.sortReverse" [currentSortReverse]="list.sortReverse"
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>ASN</th> i18n>ASN</th>
@if (permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) { }
@if (activeDisplayFields.has(DocumentDisplayField.CORRESPONDENT) && permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
<th class="d-none d-md-table-cell" <th class="d-none d-md-table-cell"
pngxSortable="correspondent__name" pngxSortable="correspondent__name"
title="Sort by correspondent" i18n-title title="Sort by correspondent" i18n-title
@ -150,6 +178,7 @@
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Correspondent</th> i18n>Correspondent</th>
} }
@if (activeDisplayFields.has(DocumentDisplayField.TITLE)) {
<th <th
pngxSortable="title" pngxSortable="title"
title="Sort by title" i18n-title title="Sort by title" i18n-title
@ -158,6 +187,8 @@
[currentSortReverse]="list.sortReverse" [currentSortReverse]="list.sortReverse"
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Title</th> i18n>Title</th>
}
@if (activeDisplayFields.has(DocumentDisplayField.OWNER)) {
<th class="d-none d-xl-table-cell" <th class="d-none d-xl-table-cell"
pngxSortable="owner" pngxSortable="owner"
title="Sort by owner" i18n-title title="Sort by owner" i18n-title
@ -165,7 +196,8 @@
[currentSortReverse]="list.sortReverse" [currentSortReverse]="list.sortReverse"
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Owner</th> i18n>Owner</th>
@if (notesEnabled) { }
@if (activeDisplayFields.has(DocumentDisplayField.NOTES) && notesEnabled) {
<th class="d-none d-xl-table-cell" <th class="d-none d-xl-table-cell"
pngxSortable="num_notes" pngxSortable="num_notes"
title="Sort by notes" i18n-title title="Sort by notes" i18n-title
@ -174,7 +206,7 @@
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Notes</th> i18n>Notes</th>
} }
@if (permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) { @if (activeDisplayFields.has(DocumentDisplayField.DOCUMENT_TYPE) && permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
<th class="d-none d-xl-table-cell" <th class="d-none d-xl-table-cell"
pngxSortable="document_type__name" pngxSortable="document_type__name"
title="Sort by document type" i18n-title title="Sort by document type" i18n-title
@ -183,7 +215,7 @@
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Document type</th> i18n>Document type</th>
} }
@if (permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) { @if (activeDisplayFields.has(DocumentDisplayField.STORAGE_PATH) && permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
<th class="d-none d-xl-table-cell" <th class="d-none d-xl-table-cell"
pngxSortable="storage_path__name" pngxSortable="storage_path__name"
title="Sort by storage path" i18n-title title="Sort by storage path" i18n-title
@ -192,6 +224,7 @@
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Storage path</th> i18n>Storage path</th>
} }
@if (activeDisplayFields.has(DocumentDisplayField.CREATED)) {
<th <th
pngxSortable="created" pngxSortable="created"
title="Sort by created date" i18n-title title="Sort by created date" i18n-title
@ -199,6 +232,8 @@
[currentSortReverse]="list.sortReverse" [currentSortReverse]="list.sortReverse"
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Created</th> i18n>Created</th>
}
@if (activeDisplayFields.has(DocumentDisplayField.ADDED)) {
<th class="d-none d-xl-table-cell" <th class="d-none d-xl-table-cell"
pngxSortable="added" pngxSortable="added"
title="Sort by added date" i18n-title title="Sort by added date" i18n-title
@ -206,6 +241,7 @@
[currentSortReverse]="list.sortReverse" [currentSortReverse]="list.sortReverse"
(sort)="onSort($event)" (sort)="onSort($event)"
i18n>Added</th> i18n>Added</th>
}
</thead> </thead>
<tbody> <tbody>
@for (d of list.documents; track trackByDocumentId($index, d)) { @for (d of list.documents; track trackByDocumentId($index, d)) {
@ -216,10 +252,12 @@
<label class="form-check-label" for="docCheck{{d.id}}"></label> <label class="form-check-label" for="docCheck{{d.id}}"></label>
</div> </div>
</td> </td>
@if (activeDisplayFields.has(DocumentDisplayField.ASN)) {
<td class="d-none d-lg-table-cell"> <td class="d-none d-lg-table-cell">
{{d.archive_serial_number}} {{d.archive_serial_number}}
</td> </td>
@if (permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) { }
@if (activeDisplayFields.has(DocumentDisplayField.CORRESPONDENT) && permissionService.currentUserCan(PermissionAction.View, PermissionType.Correspondent)) {
<td class="d-none d-md-table-cell"> <td class="d-none d-md-table-cell">
@if (d.correspondent) { @if (d.correspondent) {
<a (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent" i18n-title>{{(d.correspondent$ | async)?.name}}</a> <a (click)="clickCorrespondent(d.correspondent);$event.stopPropagation()" title="Filter by correspondent" i18n-title>{{(d.correspondent$ | async)?.name}}</a>
@ -227,15 +265,21 @@
</td> </td>
} }
<td> <td>
@if (activeDisplayFields.has(DocumentDisplayField.TITLE)) {
<a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a> <a routerLink="/documents/{{d.id}}" title="Edit document" i18n-title style="overflow-wrap: anywhere;">{{d.title | documentTitle}}</a>
}
@if (activeDisplayFields.has(DocumentDisplayField.TAGS)) {
@for (t of d.tags$ | async; track t) { @for (t of d.tags$ | async; track t) {
<pngx-tag [tag]="t" class="ms-1" clickable="true" linkTitle="Filter by tag" i18n-linkTitle (click)="clickTag(t.id);$event.stopPropagation()"></pngx-tag> <pngx-tag [tag]="t" class="ms-1" clickable="true" linkTitle="Filter by tag" i18n-linkTitle (click)="clickTag(t.id);$event.stopPropagation()"></pngx-tag>
} }
}
</td> </td>
@if (activeDisplayFields.has(DocumentDisplayField.OWNER)) {
<td> <td>
{{d.owner | username}} {{d.owner | username}}
</td> </td>
@if (notesEnabled) { }
@if (activeDisplayFields.has(DocumentDisplayField.NOTES) && notesEnabled) {
<td class="d-none d-xl-table-cell"> <td class="d-none d-xl-table-cell">
@if (d.notes.length) { @if (d.notes.length) {
<a routerLink="/documents/{{d.id}}/notes" class="btn btn-sm p-0"> <a routerLink="/documents/{{d.id}}/notes" class="btn btn-sm p-0">
@ -246,26 +290,30 @@
} }
</td> </td>
} }
@if (permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) { @if (activeDisplayFields.has(DocumentDisplayField.DOCUMENT_TYPE) && permissionService.currentUserCan(PermissionAction.View, PermissionType.DocumentType)) {
<td class="d-none d-xl-table-cell"> <td class="d-none d-xl-table-cell">
@if (d.document_type) { @if (d.document_type) {
<a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a> <a (click)="clickDocumentType(d.document_type);$event.stopPropagation()" title="Filter by document type" i18n-title>{{(d.document_type$ | async)?.name}}</a>
} }
</td> </td>
} }
@if (permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) { @if (activeDisplayFields.has(DocumentDisplayField.STORAGE_PATH) && permissionService.currentUserCan(PermissionAction.View, PermissionType.StoragePath)) {
<td class="d-none d-xl-table-cell"> <td class="d-none d-xl-table-cell">
@if (d.storage_path) { @if (d.storage_path) {
<a (click)="clickStoragePath(d.storage_path);$event.stopPropagation()" title="Filter by storage path" i18n-title>{{(d.storage_path$ | async)?.name}}</a> <a (click)="clickStoragePath(d.storage_path);$event.stopPropagation()" title="Filter by storage path" i18n-title>{{(d.storage_path$ | async)?.name}}</a>
} }
</td> </td>
} }
@if (activeDisplayFields.has(DocumentDisplayField.CREATED)) {
<td> <td>
{{d.created_date | customDate}} {{d.created_date | customDate}}
</td> </td>
}
@if (activeDisplayFields.has(DocumentDisplayField.ADDED)) {
<td class="d-none d-xl-table-cell"> <td class="d-none d-xl-table-cell">
{{d.added | customDate}} {{d.added | customDate}}
</td> </td>
}
</tr> </tr>
} }
</tbody> </tbody>
@ -274,7 +322,17 @@
@if (displayMode === 'smallCards') { @if (displayMode === 'smallCards') {
<div class="row row-cols-paperless-cards"> <div class="row row-cols-paperless-cards">
@for (d of list.documents; track trackByDocumentId($index, d)) { @for (d of list.documents; track trackByDocumentId($index, d)) {
<pngx-document-card-small class="p-0" [selected]="list.isSelected(d)" (toggleSelected)="toggleSelected(d, $event)" (dblClickDocument)="openDocumentDetail(d)" [document]="d" (clickTag)="clickTag($event)" (clickCorrespondent)="clickCorrespondent($event)" (clickStoragePath)="clickStoragePath($event)" (clickDocumentType)="clickDocumentType($event)"></pngx-document-card-small> <pngx-document-card-small class="p-0"
[selected]="list.isSelected(d)"
(toggleSelected)="toggleSelected(d, $event)"
(dblClickDocument)="openDocumentDetail(d)"
[document]="d"
(clickTag)="clickTag($event)"
[displayFields]="activeDisplayFields"
(clickCorrespondent)="clickCorrespondent($event)"
(clickStoragePath)="clickStoragePath($event)"
(clickDocumentType)="clickDocumentType($event)">
</pngx-document-card-small>
} }
</div> </div>
} }

View File

@ -16,7 +16,11 @@ import {
} from 'src/app/utils/filter-rules' } from 'src/app/utils/filter-rules'
import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type' import { FILTER_FULLTEXT_MORELIKE } from 'src/app/data/filter-rule-type'
import { Document } from 'src/app/data/document' import { Document } from 'src/app/data/document'
import { DisplayMode, SavedView } from 'src/app/data/saved-view' import {
DisplayMode,
DocumentDisplayField,
SavedView,
} from 'src/app/data/saved-view'
import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
import { import {
SortableDirective, SortableDirective,
@ -46,6 +50,8 @@ export class DocumentListComponent
extends ComponentWithPermissions extends ComponentWithPermissions
implements OnInit, OnDestroy implements OnInit, OnDestroy
{ {
DocumentDisplayField = DocumentDisplayField
constructor( constructor(
public list: DocumentListViewService, public list: DocumentListViewService,
public savedViewService: SavedViewService, public savedViewService: SavedViewService,
@ -55,7 +61,7 @@ export class DocumentListComponent
private modalService: NgbModal, private modalService: NgbModal,
private consumerStatusService: ConsumerStatusService, private consumerStatusService: ConsumerStatusService,
public openDocumentsService: OpenDocumentsService, public openDocumentsService: OpenDocumentsService,
private settingsService: SettingsService, public settingsService: SettingsService,
public permissionService: PermissionsService public permissionService: PermissionsService
) { ) {
super() super()
@ -67,6 +73,18 @@ export class DocumentListComponent
@ViewChildren(SortableDirective) headers: QueryList<SortableDirective> @ViewChildren(SortableDirective) headers: QueryList<SortableDirective>
displayMode: string = DisplayMode.SMALL_CARDS // largeCards, smallCards, details displayMode: string = DisplayMode.SMALL_CARDS // largeCards, smallCards, details
activeDisplayFields: Set<string> = new Set([
DocumentDisplayField.TITLE,
DocumentDisplayField.CORRESPONDENT,
DocumentDisplayField.CREATED,
DocumentDisplayField.TAGS,
DocumentDisplayField.DOCUMENT_TYPE,
DocumentDisplayField.STORAGE_PATH,
DocumentDisplayField.NOTES,
DocumentDisplayField.OWNER,
DocumentDisplayField.ASN,
DocumentDisplayField.SHARED,
])
unmodifiedFilterRules: FilterRule[] = [] unmodifiedFilterRules: FilterRule[] = []
private unmodifiedSavedView: SavedView private unmodifiedSavedView: SavedView
@ -131,11 +149,33 @@ export class DocumentListComponent
localStorage.setItem('document-list:displayMode', this.displayMode) localStorage.setItem('document-list:displayMode', this.displayMode)
} }
saveDisplayFields() {
localStorage.setItem(
'document-list:displayFields',
JSON.stringify(Array.from(this.activeDisplayFields))
)
}
toggleDisplayField(field: string) {
if (this.activeDisplayFields.has(field)) {
this.activeDisplayFields.delete(field)
} else {
this.activeDisplayFields.add(field)
}
this.saveDisplayFields()
}
ngOnInit(): void { ngOnInit(): void {
if (localStorage.getItem('document-list:displayMode') != null) { if (localStorage.getItem('document-list:displayMode') != null) {
this.displayMode = localStorage.getItem('document-list:displayMode') this.displayMode = localStorage.getItem('document-list:displayMode')
} }
if (localStorage.getItem('document-list:displayFields') != null) {
this.activeDisplayFields = new Set(
JSON.parse(localStorage.getItem('document-list:displayFields'))
)
}
this.consumerStatusService this.consumerStatusService
.onDocumentConsumptionFinished() .onDocumentConsumptionFinished()
.pipe(takeUntil(this.unsubscribeNotifier)) .pipe(takeUntil(this.unsubscribeNotifier))

View File

@ -15,6 +15,10 @@ export enum DocumentDisplayField {
DOCUMENT_TYPE = 'documenttype', DOCUMENT_TYPE = 'documenttype',
STORAGE_PATH = 'storagepath', STORAGE_PATH = 'storagepath',
CUSTOM_FIELD = 'custom_field_', CUSTOM_FIELD = 'custom_field_',
NOTES = 'note',
OWNER = 'owner',
SHARED = 'shared',
ASN = 'asn',
} }
export const DOCUMENT_DISPLAY_FIELDS = [ export const DOCUMENT_DISPLAY_FIELDS = [
@ -46,6 +50,22 @@ export const DOCUMENT_DISPLAY_FIELDS = [
id: DocumentDisplayField.STORAGE_PATH, id: DocumentDisplayField.STORAGE_PATH,
name: $localize`Storage path`, name: $localize`Storage path`,
}, },
{
id: DocumentDisplayField.NOTES,
name: $localize`Notes`,
},
{
id: DocumentDisplayField.OWNER,
name: $localize`Owner`,
},
{
id: DocumentDisplayField.SHARED,
name: $localize`Shared`,
},
{
id: DocumentDisplayField.ASN,
name: $localize`ASN`,
},
] ]
export interface SavedView extends ObjectWithPermissions { export interface SavedView extends ObjectWithPermissions {

View File

@ -19,9 +19,18 @@ import {
import { environment } from 'src/environments/environment' import { environment } from 'src/environments/environment'
import { UiSettings, SETTINGS, SETTINGS_KEYS } from '../data/ui-settings' import { UiSettings, SETTINGS, SETTINGS_KEYS } from '../data/ui-settings'
import { User } from '../data/user' import { User } from '../data/user'
import { PermissionsService } from './permissions.service' import {
PermissionAction,
PermissionType,
PermissionsService,
} from './permissions.service'
import { ToastService } from './toast.service' import { ToastService } from './toast.service'
import { SavedView } from '../data/saved-view' import {
DOCUMENT_DISPLAY_FIELDS,
DocumentDisplayField,
SavedView,
} from '../data/saved-view'
import { CustomFieldsService } from './rest/custom-fields.service'
export interface LanguageOption { export interface LanguageOption {
code: string code: string
@ -257,6 +266,8 @@ export class SettingsService {
public globalDropzoneActive: boolean = false public globalDropzoneActive: boolean = false
public organizingSidebarSavedViews: boolean = false public organizingSidebarSavedViews: boolean = false
public allDocumentDisplayFields: any
constructor( constructor(
rendererFactory: RendererFactory2, rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document, @Inject(DOCUMENT) private document,
@ -265,7 +276,8 @@ export class SettingsService {
@Inject(LOCALE_ID) private localeId: string, @Inject(LOCALE_ID) private localeId: string,
protected http: HttpClient, protected http: HttpClient,
private toastService: ToastService, private toastService: ToastService,
private permissionsService: PermissionsService private permissionsService: PermissionsService,
private customFieldsService: CustomFieldsService
) { ) {
this._renderer = rendererFactory.createRenderer(null, null) this._renderer = rendererFactory.createRenderer(null, null)
} }
@ -288,6 +300,26 @@ export class SettingsService {
uisettings.permissions, uisettings.permissions,
this.currentUser this.currentUser
) )
this.allDocumentDisplayFields = DOCUMENT_DISPLAY_FIELDS
if (
this.permissionsService.currentUserCan(
PermissionAction.View,
PermissionType.CustomField
)
) {
this.customFieldsService.listAll().subscribe((r) => {
this.allDocumentDisplayFields = DOCUMENT_DISPLAY_FIELDS.concat(
r.results.map((field) => {
return {
id: `${DocumentDisplayField.CUSTOM_FIELD}${field.id}` as any,
name: field.name,
}
})
)
})
}
}) })
) )
} }