Blank out display fields for better backwards compatibility
This commit is contained in:
parent
9a2d30cb33
commit
0e1ab79773
@ -1,6 +1,6 @@
|
||||
<div class="d-flex flex-row mt-2 align-items-center">
|
||||
{{title}}:
|
||||
<div class="ms-2 d-flex flex-row gap-2 w-100"
|
||||
<span class="me-2">{{title}}:</span>
|
||||
<div class="d-flex flex-row gap-2 w-100 mh-1" style="min-height: 1em;"
|
||||
cdkDropList #selectedList="cdkDropList"
|
||||
cdkDropListOrientation="horizontal"
|
||||
(cdkDropListDropped)="drop($event)"
|
||||
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-row mt-2 align-items-center bg-light p-2">
|
||||
<div class="d-flex flex-row gap-2 w-100"
|
||||
<div class="d-flex flex-row gap-2 w-100 mh-1" style="min-height: 1em;"
|
||||
cdkDropList #unselectedList="cdkDropList"
|
||||
cdkDropListOrientation="horizontal"
|
||||
(cdkDropListDropped)="drop($event)"
|
||||
|
@ -32,6 +32,9 @@ describe('DragDropSelectComponent', () => {
|
||||
{ id: '2', name: 'Item 2' },
|
||||
{ id: '3', name: 'Item 3' },
|
||||
])
|
||||
|
||||
component.writeValue(null)
|
||||
expect(component.selectedItems).toEqual([])
|
||||
})
|
||||
|
||||
it('should update selectedItems when an item is dropped within selectedList', () => {
|
||||
|
@ -34,9 +34,8 @@ export class DragDropSelectComponent extends AbstractInputComponent<string[]> {
|
||||
|
||||
writeValue(newValue: string[]): void {
|
||||
super.writeValue(newValue)
|
||||
this.selectedItems = newValue.map((id) =>
|
||||
this.items.find((i) => i.id === id)
|
||||
)
|
||||
this.selectedItems =
|
||||
newValue?.map((id) => this.items.find((i) => i.id === id)) ?? []
|
||||
}
|
||||
|
||||
public drop(event: CdkDragDrop<string[]>) {
|
||||
|
@ -9,19 +9,19 @@
|
||||
<a class="btn-link text-decoration-none" header-buttons [routerLink]="[]" (click)="showAll()" i18n>Show all</a>
|
||||
}
|
||||
|
||||
@if (documents.length && (!savedView.display_mode || savedView.display_mode === DashboardViewMode.TABLE)) {
|
||||
@if (documents.length && displayMode === DisplayMode.TABLE) {
|
||||
<table content class="table table-hover mb-0 mt-n2 align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
@for (column of savedView.display_fields; track column; let i = $index) {
|
||||
@if (activeDisplayFields.includes(column)) {
|
||||
@for (field of displayFields; track field; let i = $index) {
|
||||
@if (displayFields.includes(field)) {
|
||||
<th
|
||||
scope="col"
|
||||
[ngClass]="{
|
||||
'd-none d-md-table-cell': i > 1,
|
||||
'w-25': column === DashboardViewTableColumn.CREATED || column === DashboardViewTableColumn.ADDED
|
||||
'w-25': field === DisplayField.CREATED || field === DisplayField.ADDED
|
||||
}">
|
||||
{{ getColumnTitle(column) }}
|
||||
{{ getColumnTitle(field) }}
|
||||
</th>
|
||||
}
|
||||
}
|
||||
@ -30,44 +30,44 @@
|
||||
<tbody>
|
||||
@for (doc of documents; track doc.id) {
|
||||
<tr>
|
||||
@for (column of savedView.display_fields; track column; let i = $index) {
|
||||
@if (activeDisplayFields.includes(column)) {
|
||||
@for (field of displayFields; track field; let i = $index) {
|
||||
@if (displayFields.includes(field)) {
|
||||
<td class="py-2 py-md-3 position-relative" [ngClass]="{ 'd-none d-md-table-cell': i > 1 }">
|
||||
@switch (column) {
|
||||
@case (DashboardViewTableColumn.ADDED) {
|
||||
@switch (field) {
|
||||
@case (DisplayField.ADDED) {
|
||||
<a routerLink="/documents/{{doc.id}}" class="btn-link text-dark text-decoration-none py-2 py-md-3">{{doc.added | customDate}}</a>
|
||||
}
|
||||
@case (DashboardViewTableColumn.CREATED) {
|
||||
@case (DisplayField.CREATED) {
|
||||
<a routerLink="/documents/{{doc.id}}" class="btn-link text-dark text-decoration-none py-2 py-md-3">{{doc.created_date | customDate}}</a>
|
||||
}
|
||||
@case (DashboardViewTableColumn.TITLE) {
|
||||
@case (DisplayField.TITLE) {
|
||||
<a routerLink="/documents/{{doc.id}}" title="Edit" i18n-title class="btn-link text-dark text-decoration-none py-2 py-md-3">{{doc.title | documentTitle}}</a>
|
||||
}
|
||||
@case (DashboardViewTableColumn.CORRESPONDENT) {
|
||||
@case (DisplayField.CORRESPONDENT) {
|
||||
@if (doc.correspondent) {
|
||||
<a class="btn-link text-dark text-decoration-none" type="button" (click)="clickCorrespondent(doc.correspondent, $event)">{{(doc.correspondent$ | async)?.name}}</a>
|
||||
}
|
||||
}
|
||||
@case (DashboardViewTableColumn.TAGS) {
|
||||
@case (DisplayField.TAGS) {
|
||||
@for (t of doc.tags$ | async; track t) {
|
||||
<pngx-tag [tag]="t" class="ms-1" (click)="clickTag(t.id, $event)"></pngx-tag>
|
||||
}
|
||||
}
|
||||
@case (DashboardViewTableColumn.DOCUMENT_TYPE) {
|
||||
@case (DisplayField.DOCUMENT_TYPE) {
|
||||
@if (doc.document_type) {
|
||||
<a class="btn-link text-dark text-decoration-none" type="button" (click)="clickDocType(doc.document_type, $event)">{{(doc.document_type$ | async)?.name}}</a>
|
||||
}
|
||||
}
|
||||
@case (DashboardViewTableColumn.STORAGE_PATH) {
|
||||
@case (DisplayField.STORAGE_PATH) {
|
||||
@if (doc.storage_path) {
|
||||
<a class="btn-link text-dark text-decoration-none" type="button" (click)="clickStoragePath(doc.storage_path, $event)">{{(doc.storage_path$ | async)?.name}}</a>
|
||||
}
|
||||
}
|
||||
}
|
||||
@if (column.startsWith(DashboardViewTableColumn.CUSTOM_FIELD)) {
|
||||
<pngx-custom-field-display [document]="doc" [fieldDisplayKey]="column"></pngx-custom-field-display>
|
||||
@if (field.startsWith(DisplayField.CUSTOM_FIELD)) {
|
||||
<pngx-custom-field-display [document]="doc" [fieldDisplayKey]="field"></pngx-custom-field-display>
|
||||
}
|
||||
@if (i === savedView.display_fields.length - 1) {
|
||||
@if (i === displayFields.length - 1) {
|
||||
<div class="btn-group position-absolute top-50 end-0 translate-middle-y">
|
||||
<a [href]="getPreviewUrl(doc)" title="View Preview" i18n-title target="_blank" class="btn px-4 btn-dark border-dark-subtle"
|
||||
[ngbPopover]="previewContent" [popoverTitle]="doc.title | documentTitle"
|
||||
@ -89,14 +89,14 @@
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
} @else if (documents.length && savedView.display_mode === DashboardViewMode.SMALL_CARDS) {
|
||||
} @else if (documents.length && displayMode === DisplayMode.SMALL_CARDS) {
|
||||
<div class="row row-cols-paperless-cards my-n2">
|
||||
@for (d of documents; track d.id) {
|
||||
<pngx-document-card-small
|
||||
class="p-0"
|
||||
(dblClickDocument)="openDocumentDetail(d)"
|
||||
[document]="d"
|
||||
[displayFields]="activeDisplayFields"
|
||||
[displayFields]="displayFields"
|
||||
(clickTag)="clickTag($event)"
|
||||
(clickCorrespondent)="clickCorrespondent($event)"
|
||||
(clickStoragePath)="clickStoragePath($event)"
|
||||
@ -104,13 +104,13 @@
|
||||
</pngx-document-card-small>
|
||||
}
|
||||
</div>
|
||||
} @else if (documents.length && savedView.display_mode === DashboardViewMode.LARGE_CARDS) {
|
||||
} @else if (documents.length && displayMode === DisplayMode.LARGE_CARDS) {
|
||||
<div class="row my-n2">
|
||||
@for (d of documents; track d.id) {
|
||||
<pngx-document-card-large
|
||||
(dblClickDocument)="openDocumentDetail(d)"
|
||||
[document]="d"
|
||||
[displayFields]="activeDisplayFields"
|
||||
[displayFields]="displayFields"
|
||||
(clickTag)="clickTag($event)"
|
||||
(clickCorrespondent)="clickCorrespondent($event)"
|
||||
(clickStoragePath)="clickStoragePath($event)"
|
||||
|
@ -342,4 +342,39 @@ describe('SavedViewWidgetComponent', () => {
|
||||
'Storage path'
|
||||
)
|
||||
})
|
||||
|
||||
it('should hide fields if no perms', () => {
|
||||
fixture = TestBed.createComponent(SavedViewWidgetComponent)
|
||||
component = fixture.componentInstance
|
||||
component.savedView = {
|
||||
sort_field: 'added',
|
||||
sort_reverse: true,
|
||||
show_in_sidebar: true,
|
||||
show_on_dashboard: true,
|
||||
filter_rules: [],
|
||||
display_fields: [DisplayField.TITLE, 'foo' as any, 'bar' as any],
|
||||
}
|
||||
component.ngOnInit()
|
||||
expect(component.displayFields).toEqual([DisplayField.TITLE])
|
||||
})
|
||||
|
||||
it('should use fallback display settings', () => {
|
||||
fixture = TestBed.createComponent(SavedViewWidgetComponent)
|
||||
component = fixture.componentInstance
|
||||
component.savedView = {
|
||||
sort_field: 'added',
|
||||
sort_reverse: true,
|
||||
show_in_sidebar: true,
|
||||
show_on_dashboard: true,
|
||||
filter_rules: [],
|
||||
}
|
||||
component.ngOnInit()
|
||||
expect(component.displayMode).toEqual(DisplayMode.TABLE)
|
||||
expect(component.displayFields).toEqual([
|
||||
DisplayField.CREATED,
|
||||
DisplayField.TITLE,
|
||||
DisplayField.TAGS,
|
||||
DisplayField.CORRESPONDENT,
|
||||
])
|
||||
})
|
||||
})
|
||||
|
@ -46,8 +46,8 @@ export class SavedViewWidgetComponent
|
||||
extends ComponentWithPermissions
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
public DashboardViewMode = DisplayMode
|
||||
public DashboardViewTableColumn = DisplayField
|
||||
public DisplayMode = DisplayMode
|
||||
public DisplayField = DisplayField
|
||||
public CustomFieldDataType = CustomFieldDataType
|
||||
|
||||
loading: boolean = true
|
||||
@ -80,14 +80,18 @@ export class SavedViewWidgetComponent
|
||||
mouseOnPreview = false
|
||||
popoverHidden = true
|
||||
|
||||
activeDisplayFields: DisplayField[] = [
|
||||
DisplayField.TITLE,
|
||||
displayMode: DisplayMode
|
||||
|
||||
displayFields: DisplayField[] = [
|
||||
DisplayField.CREATED,
|
||||
DisplayField.ADDED,
|
||||
DisplayField.TITLE,
|
||||
DisplayField.TAGS,
|
||||
DisplayField.CORRESPONDENT,
|
||||
]
|
||||
|
||||
ngOnInit(): void {
|
||||
this.reload()
|
||||
this.displayMode = this.savedView.display_mode ?? DisplayMode.TABLE
|
||||
this.consumerStatusService
|
||||
.onDocumentConsumptionFinished()
|
||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||
@ -109,19 +113,32 @@ export class SavedViewWidgetComponent
|
||||
})
|
||||
}
|
||||
|
||||
this.savedView.display_fields?.forEach((column) => {
|
||||
if (this.savedView.display_fields) {
|
||||
this.displayFields = this.savedView.display_fields
|
||||
?.map((field) => {
|
||||
if (
|
||||
[
|
||||
DisplayField.TITLE,
|
||||
DisplayField.CREATED,
|
||||
DisplayField.ADDED,
|
||||
].includes(field)
|
||||
) {
|
||||
return field
|
||||
}
|
||||
|
||||
let type: PermissionType = Object.values(PermissionType).find((t) =>
|
||||
t.includes(column)
|
||||
t.includes(field)
|
||||
)
|
||||
if (column.startsWith(DisplayField.CUSTOM_FIELD)) {
|
||||
if (field.startsWith(DisplayField.CUSTOM_FIELD)) {
|
||||
type = PermissionType.CustomField
|
||||
}
|
||||
if (
|
||||
type &&
|
||||
return type &&
|
||||
this.permissionsService.currentUserCan(PermissionAction.View, type)
|
||||
)
|
||||
this.activeDisplayFields.push(column)
|
||||
? field
|
||||
: null
|
||||
})
|
||||
.filter((f) => f)
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
@ -102,9 +102,11 @@ export class DocumentListComponent
|
||||
this.unmodifiedSavedView.sort_reverse !== this.list.sortReverse ||
|
||||
(this.unmodifiedSavedView.page_size &&
|
||||
this.unmodifiedSavedView.page_size !== this.list.pageSize) ||
|
||||
this.unmodifiedSavedView.display_mode !== this.list.displayMode ||
|
||||
(this.unmodifiedSavedView.display_mode &&
|
||||
this.unmodifiedSavedView.display_mode !== this.list.displayMode) ||
|
||||
(this.unmodifiedSavedView.display_fields &&
|
||||
this.unmodifiedSavedView.display_fields.join(',') !==
|
||||
this.activeDisplayFields.join(',') ||
|
||||
this.activeDisplayFields.join(',')) ||
|
||||
filterRulesDiffer(
|
||||
this.unmodifiedSavedView.filter_rules,
|
||||
this.list.filterRules
|
||||
@ -190,12 +192,6 @@ export class DocumentListComponent
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!view.display_mode) {
|
||||
view.display_mode = this.list.displayMode
|
||||
}
|
||||
if (!view.display_fields) {
|
||||
view.display_fields = this.list.displayFields
|
||||
}
|
||||
this.unmodifiedSavedView = view
|
||||
this.list.activateSavedViewWithQueryParams(
|
||||
view,
|
||||
|
@ -42,6 +42,7 @@ class Migration(migrations.Migration):
|
||||
model_name="savedview",
|
||||
name="display_fields",
|
||||
field=multiselectfield.db.fields.MultiSelectField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("title", "Title"),
|
||||
("created", "Created"),
|
||||
@ -51,8 +52,9 @@ class Migration(migrations.Migration):
|
||||
("correspondent", "Correspondent"),
|
||||
("storagepath", "Storage Path"),
|
||||
],
|
||||
default="created,title,tag,correspondent",
|
||||
max_length=128,
|
||||
null=True,
|
||||
verbose_name="Document display fields",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
@ -606,7 +606,8 @@ class SavedView(ModelWithOwner):
|
||||
verbose_name=_("Document display fields"),
|
||||
choices=DisplayFields.choices,
|
||||
dyanmic_choices=[DynamicDisplayFields.CUSTOM_FIELD],
|
||||
default=f"{DisplayFields.CREATED},{DisplayFields.TITLE},{DisplayFields.TAGS},{DisplayFields.CORRESPONDENT}",
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
Loading…
x
Reference in New Issue
Block a user