Unified filtering of display fields by perms / disabled

This commit is contained in:
shamoon 2024-04-21 09:16:20 -07:00
parent 2cbb97735c
commit f19a6a4add
10 changed files with 170 additions and 117 deletions

View File

@ -947,7 +947,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">206</context>
<context context-type="linenumber">209</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/document.ts</context>
@ -1795,7 +1795,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">233</context>
<context context-type="linenumber">236</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -2041,7 +2041,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">108</context>
<context context-type="linenumber">124</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/custom-fields/custom-fields.component.html</context>
@ -2457,6 +2457,10 @@
<context context-type="sourcefile">src/app/components/document-list/bulk-editor/bulk-editor.component.html</context>
<context context-type="linenumber">21</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">191</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
<context context-type="linenumber">33</context>
@ -4905,7 +4909,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">119</context>
<context context-type="linenumber">135</context>
</context-group>
</trans-unit>
<trans-unit id="872092479747931526" datatype="html">
@ -5242,7 +5246,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">215</context>
<context context-type="linenumber">218</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -5269,7 +5273,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">224</context>
<context context-type="linenumber">227</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -5938,7 +5942,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">267</context>
<context context-type="linenumber">275</context>
</context-group>
</trans-unit>
<trans-unit id="2784168796433474565" datatype="html">
@ -5949,7 +5953,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">277</context>
<context context-type="linenumber">285</context>
</context-group>
</trans-unit>
<trans-unit id="106713086593101376" datatype="html">
@ -5974,7 +5978,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">300</context>
<context context-type="linenumber">308</context>
</context-group>
</trans-unit>
<trans-unit id="157572966557284263" datatype="html">
@ -5985,7 +5989,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">307</context>
<context context-type="linenumber">315</context>
</context-group>
</trans-unit>
<trans-unit id="3727324658595204357" datatype="html">
@ -5998,6 +6002,10 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">65,66</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">82,83</context>
</context-group>
</trans-unit>
<trans-unit id="2030261243264601523" datatype="html">
<source>Added: <x id="INTERPOLATION" equiv-text="{{ document.added | customDate }}"/></source>
@ -6009,6 +6017,10 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">66,67</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">83,84</context>
</context-group>
</trans-unit>
<trans-unit id="4235671847487610290" datatype="html">
<source>Modified: <x id="INTERPOLATION" equiv-text="{{ document.modified | customDate }}"/></source>
@ -6020,6 +6032,10 @@
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">67,68</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">84,85</context>
</context-group>
</trans-unit>
<trans-unit id="5739581984228459958" datatype="html">
<source>Shared</source>
@ -6029,7 +6045,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-card-small/document-card-small.component.html</context>
<context context-type="linenumber">94</context>
<context context-type="linenumber">110</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/document.ts</context>
@ -6200,14 +6216,14 @@
<source>Sort by owner</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">193</context>
<context context-type="linenumber">196</context>
</context-group>
</trans-unit>
<trans-unit id="3715596725146409911" datatype="html">
<source>Owner</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">197</context>
<context context-type="linenumber">200</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/data/document.ts</context>
@ -6222,42 +6238,42 @@
<source>Sort by notes</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">202</context>
<context context-type="linenumber">205</context>
</context-group>
</trans-unit>
<trans-unit id="5499001829734502606" datatype="html">
<source>Sort by document type</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">211</context>
<context context-type="linenumber">214</context>
</context-group>
</trans-unit>
<trans-unit id="6213829731736042759" datatype="html">
<source>Sort by storage path</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">220</context>
<context context-type="linenumber">223</context>
</context-group>
</trans-unit>
<trans-unit id="3406167410329973166" datatype="html">
<source>Sort by created date</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">229</context>
<context context-type="linenumber">232</context>
</context-group>
</trans-unit>
<trans-unit id="3769035778779263084" datatype="html">
<source>Sort by added date</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">238</context>
<context context-type="linenumber">241</context>
</context-group>
</trans-unit>
<trans-unit id="231679111972850796" datatype="html">
<source>Added</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">242</context>
<context context-type="linenumber">245</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/filter-editor/filter-editor.component.html</context>
@ -6272,11 +6288,40 @@
<context context-type="linenumber">93</context>
</context-group>
</trans-unit>
<trans-unit id="329406837759048287" datatype="html">
<source> Shared </source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">248,250</context>
</context-group>
</trans-unit>
<trans-unit id="2179847500064178686" datatype="html">
<source>Edit document</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">273</context>
<context context-type="linenumber">281</context>
</context-group>
</trans-unit>
<trans-unit id="2807800733729323332" datatype="html">
<source>Yes</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">331</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/pipes/yes-no.pipe.ts</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit id="3542042671420335679" datatype="html">
<source>No</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.html</context>
<context context-type="linenumber">331</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/pipes/yes-no.pipe.ts</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit id="2155249406916744630" datatype="html">
@ -7485,20 +7530,6 @@
<context context-type="linenumber">11</context>
</context-group>
</trans-unit>
<trans-unit id="2807800733729323332" datatype="html">
<source>Yes</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/pipes/yes-no.pipe.ts</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit id="3542042671420335679" datatype="html">
<source>No</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/pipes/yes-no.pipe.ts</context>
<context context-type="linenumber">8</context>
</context-group>
</trans-unit>
<trans-unit id="2119857572761283468" datatype="html">
<source>Document already exists.</source>
<context-group purpose="location">
@ -7871,21 +7902,21 @@
<source>Successfully completed one-time migratration of settings to the database!</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">510</context>
<context context-type="linenumber">549</context>
</context-group>
</trans-unit>
<trans-unit id="5558341108007064934" datatype="html">
<source>Unable to migrate settings to the database, please try saving manually.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">511</context>
<context context-type="linenumber">550</context>
</context-group>
</trans-unit>
<trans-unit id="1168781785897678748" datatype="html">
<source>You can restart the tour from the settings page.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">581</context>
<context context-type="linenumber">620</context>
</context-group>
</trans-unit>
<trans-unit id="3852289441366561594" datatype="html">

View File

@ -48,6 +48,8 @@ import {
InstallType,
SystemStatusItemStatus,
} from 'src/app/data/system-status'
import { DragDropSelectComponent } from '../../common/input/drag-drop-select/drag-drop-select.component'
import { DragDropModule } from '@angular/cdk/drag-drop'
const savedViews = [
{ id: 1, name: 'view1', show_in_sidebar: true, show_on_dashboard: true },
@ -96,6 +98,7 @@ describe('SettingsComponent', () => {
PermissionsGroupComponent,
IfOwnerDirective,
ConfirmButtonComponent,
DragDropSelectComponent,
],
providers: [CustomDatePipe, DatePipe, PermissionsGuard],
imports: [
@ -108,6 +111,7 @@ describe('SettingsComponent', () => {
NgSelectModule,
NgxBootstrapIconsModule.pick(allIcons),
NgbModalModule,
DragDropModule,
],
}).compileComponents()

View File

@ -542,6 +542,7 @@ export class SettingsComponent
next: () => {
this.store.next(this.settingsForm.value)
this.settings.updateAppearanceSettings()
this.settings.initializeDisplayFields()
let savedToast: Toast = {
content: $localize`Settings were saved successfully.`,
delay: 5000,

View File

@ -343,39 +343,4 @@ 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,
])
})
})

View File

@ -37,6 +37,7 @@ import {
} from 'src/app/services/permissions.service'
import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
import { SettingsService } from 'src/app/services/settings.service'
@Component({
selector: 'pngx-saved-view-widget',
@ -63,6 +64,7 @@ export class SavedViewWidgetComponent
public openDocumentsService: OpenDocumentsService,
public documentListViewService: DocumentListViewService,
public permissionsService: PermissionsService,
private settingsService: SettingsService,
private customFieldService: CustomFieldsService
) {
super()
@ -111,30 +113,14 @@ export class SavedViewWidgetComponent
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(field)
// filter by perms etc
this.displayFields = this.displayFields.filter(
(field) =>
this.settingsService.allDisplayFields.find((f) => f.id === field) !==
undefined
)
if (field.startsWith(DisplayField.CUSTOM_FIELD)) {
type = PermissionType.CustomField
}
return type &&
this.permissionsService.currentUserCan(PermissionAction.View, type)
? field
: null
})
.filter((f) => f)
}
}
ngOnDestroy(): void {

View File

@ -643,9 +643,11 @@ describe('DocumentListComponent', () => {
it('should get custom field title', () => {
fixture.detectChanges()
settingsService.allDisplayFields = [
{ id: 'custom_field_1', name: 'Custom Field 1' },
]
jest
.spyOn(settingsService, 'allDisplayFields', 'get')
.mockReturnValue([
{ id: 'custom_field_1' as any, name: 'Custom Field 1' },
])
expect(component.getDisplayCustomFieldTitle('custom_field_1')).toEqual(
'Custom Field 1'
)

View File

@ -18,6 +18,8 @@ describe('ConsumerStatusService', () => {
let httpTestingController: HttpTestingController
let consumerStatusService: ConsumerStatusService
let documentService: DocumentService
let settingsService: SettingsService
const server = new WS(
`${environment.webSocketProtocol}//${environment.webSocketHost}${environment.webSocketBaseUrl}status/`,
{ jsonProtocol: true }
@ -25,25 +27,17 @@ describe('ConsumerStatusService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ConsumerStatusService,
DocumentService,
SettingsService,
{
provide: SettingsService,
useValue: {
currentUser: {
id: 1,
username: 'testuser',
is_superuser: false,
},
},
},
],
providers: [ConsumerStatusService, DocumentService, SettingsService],
imports: [HttpClientTestingModule],
})
httpTestingController = TestBed.inject(HttpTestingController)
settingsService = TestBed.inject(SettingsService)
settingsService.currentUser = {
id: 1,
username: 'testuser',
is_superuser: false,
}
consumerStatusService = TestBed.inject(ConsumerStatusService)
documentService = TestBed.inject(DocumentService)
})

View File

@ -420,7 +420,10 @@ export class DocumentListViewService {
if (!this.activeListViewState.displayFields) {
fields = fields.filter((f) => f !== DisplayField.ADDED)
}
return fields
return fields.filter(
(field) =>
this.settings.allDisplayFields.find((f) => f.id === field) !== undefined
)
}
set displayFields(fields: DisplayField[]) {

View File

@ -338,6 +338,33 @@ describe('SettingsService', () => {
httpTestingController.expectOne(`${environment.apiBaseUrl}ui_settings/`)
})
it('should hide fields if no perms or disabled', () => {
jest.spyOn(permissionService, 'currentUserCan').mockReturnValue(false)
const req = httpTestingController.expectOne(
`${environment.apiBaseUrl}ui_settings/`
)
req.flush(ui_settings)
settingsService.initializeDisplayFields()
expect(
settingsService.allDisplayFields.includes(DEFAULT_DISPLAY_FIELDS[0])
).toBeTruthy() // title
expect(
settingsService.allDisplayFields.includes(DEFAULT_DISPLAY_FIELDS[4])
).toBeFalsy() // correspondent
settingsService.set(SETTINGS_KEYS.NOTES_ENABLED, false)
settingsService.initializeDisplayFields()
expect(
settingsService.allDisplayFields.includes(DEFAULT_DISPLAY_FIELDS[8])
).toBeFalsy() // notes
jest.spyOn(permissionService, 'currentUserCan').mockReturnValue(true)
settingsService.initializeDisplayFields()
expect(
settingsService.allDisplayFields.includes(DEFAULT_DISPLAY_FIELDS[4])
).toBeTruthy() // correspondent
})
it('should dynamically create display fields options including custom fields', () => {
jest.spyOn(permissionService, 'currentUserCan').mockReturnValue(true)
jest.spyOn(customFieldsService, 'listAll').mockReturnValue(

View File

@ -263,7 +263,11 @@ export class SettingsService {
public globalDropzoneActive: boolean = false
public organizingSidebarSavedViews: boolean = false
public allDisplayFields: any
private _allDisplayFields: Array<{ id: DisplayField; name: string }> =
DEFAULT_DISPLAY_FIELDS
public get allDisplayFields(): Array<{ id: DisplayField; name: string }> {
return this._allDisplayFields
}
constructor(
rendererFactory: RendererFactory2,
@ -304,7 +308,43 @@ export class SettingsService {
}
public initializeDisplayFields() {
this.allDisplayFields = DEFAULT_DISPLAY_FIELDS
this._allDisplayFields = DEFAULT_DISPLAY_FIELDS
this._allDisplayFields = this._allDisplayFields
?.map((field) => {
if (
field.id === DisplayField.NOTES &&
!this.get(SETTINGS_KEYS.NOTES_ENABLED)
) {
return null
}
if (
[
DisplayField.TITLE,
DisplayField.CREATED,
DisplayField.ADDED,
DisplayField.ASN,
DisplayField.SHARED,
].includes(field.id)
) {
return field
}
let type: PermissionType = Object.values(PermissionType).find((t) =>
t.includes(field.id)
)
if (field.id === DisplayField.OWNER) {
type = PermissionType.User
}
return this.permissionsService.currentUserCan(
PermissionAction.View,
type
)
? field
: null
})
.filter((f) => f)
if (
this.permissionsService.currentUserCan(
@ -313,7 +353,7 @@ export class SettingsService {
)
) {
this.customFieldsService.listAll().subscribe((r) => {
this.allDisplayFields = DEFAULT_DISPLAY_FIELDS.concat(
this._allDisplayFields = this._allDisplayFields.concat(
r.results.map((field) => {
return {
id: `${DisplayField.CUSTOM_FIELD}${field.id}` as any,