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

@@ -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)
)
if (field.startsWith(DisplayField.CUSTOM_FIELD)) {
type = PermissionType.CustomField
}
return type &&
this.permissionsService.currentUserCan(PermissionAction.View, type)
? field
: null
})
.filter((f) => f)
}
// filter by perms etc
this.displayFields = this.displayFields.filter(
(field) =>
this.settingsService.allDisplayFields.find((f) => f.id === field) !==
undefined
)
}
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,