diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 87b786c96..c5cf09b4a 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -947,7 +947,7 @@ src/app/components/document-list/document-list.component.html - 206 + 209 src/app/data/document.ts @@ -1795,7 +1795,7 @@ src/app/components/document-list/document-list.component.html - 233 + 236 src/app/components/document-list/filter-editor/filter-editor.component.html @@ -2041,7 +2041,7 @@ src/app/components/document-list/document-card-small/document-card-small.component.html - 108 + 124 src/app/components/manage/custom-fields/custom-fields.component.html @@ -2457,6 +2457,10 @@ src/app/components/document-list/bulk-editor/bulk-editor.component.html 21 + + src/app/components/document-list/document-list.component.html + 191 + src/app/components/document-list/filter-editor/filter-editor.component.html 33 @@ -4905,7 +4909,7 @@ src/app/components/document-list/document-card-small/document-card-small.component.html - 119 + 135 @@ -5242,7 +5246,7 @@ src/app/components/document-list/document-list.component.html - 215 + 218 src/app/components/document-list/filter-editor/filter-editor.component.html @@ -5269,7 +5273,7 @@ src/app/components/document-list/document-list.component.html - 224 + 227 src/app/components/document-list/filter-editor/filter-editor.component.html @@ -5938,7 +5942,7 @@ src/app/components/document-list/document-list.component.html - 267 + 275 @@ -5949,7 +5953,7 @@ src/app/components/document-list/document-list.component.html - 277 + 285 @@ -5974,7 +5978,7 @@ src/app/components/document-list/document-list.component.html - 300 + 308 @@ -5985,7 +5989,7 @@ src/app/components/document-list/document-list.component.html - 307 + 315 @@ -5998,6 +6002,10 @@ src/app/components/document-list/document-card-small/document-card-small.component.html 65,66 + + src/app/components/document-list/document-card-small/document-card-small.component.html + 82,83 + Added: @@ -6009,6 +6017,10 @@ src/app/components/document-list/document-card-small/document-card-small.component.html 66,67 + + src/app/components/document-list/document-card-small/document-card-small.component.html + 83,84 + Modified: @@ -6020,6 +6032,10 @@ src/app/components/document-list/document-card-small/document-card-small.component.html 67,68 + + src/app/components/document-list/document-card-small/document-card-small.component.html + 84,85 + Shared @@ -6029,7 +6045,7 @@ src/app/components/document-list/document-card-small/document-card-small.component.html - 94 + 110 src/app/data/document.ts @@ -6200,14 +6216,14 @@ Sort by owner src/app/components/document-list/document-list.component.html - 193 + 196 Owner src/app/components/document-list/document-list.component.html - 197 + 200 src/app/data/document.ts @@ -6222,42 +6238,42 @@ Sort by notes src/app/components/document-list/document-list.component.html - 202 + 205 Sort by document type src/app/components/document-list/document-list.component.html - 211 + 214 Sort by storage path src/app/components/document-list/document-list.component.html - 220 + 223 Sort by created date src/app/components/document-list/document-list.component.html - 229 + 232 Sort by added date src/app/components/document-list/document-list.component.html - 238 + 241 Added src/app/components/document-list/document-list.component.html - 242 + 245 src/app/components/document-list/filter-editor/filter-editor.component.html @@ -6272,11 +6288,40 @@ 93 + + Shared + + src/app/components/document-list/document-list.component.html + 248,250 + + Edit document src/app/components/document-list/document-list.component.html - 273 + 281 + + + + Yes + + src/app/components/document-list/document-list.component.html + 331 + + + src/app/pipes/yes-no.pipe.ts + 8 + + + + No + + src/app/components/document-list/document-list.component.html + 331 + + + src/app/pipes/yes-no.pipe.ts + 8 @@ -7485,20 +7530,6 @@ 11 - - Yes - - src/app/pipes/yes-no.pipe.ts - 8 - - - - No - - src/app/pipes/yes-no.pipe.ts - 8 - - Document already exists. @@ -7871,21 +7902,21 @@ Successfully completed one-time migratration of settings to the database! src/app/services/settings.service.ts - 510 + 549 Unable to migrate settings to the database, please try saving manually. src/app/services/settings.service.ts - 511 + 550 You can restart the tour from the settings page. src/app/services/settings.service.ts - 581 + 620 diff --git a/src-ui/src/app/components/admin/settings/settings.component.spec.ts b/src-ui/src/app/components/admin/settings/settings.component.spec.ts index 2f76ec361..7b23edc21 100644 --- a/src-ui/src/app/components/admin/settings/settings.component.spec.ts +++ b/src-ui/src/app/components/admin/settings/settings.component.spec.ts @@ -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() diff --git a/src-ui/src/app/components/admin/settings/settings.component.ts b/src-ui/src/app/components/admin/settings/settings.component.ts index 6bfe9f485..7df90e3de 100644 --- a/src-ui/src/app/components/admin/settings/settings.component.ts +++ b/src-ui/src/app/components/admin/settings/settings.component.ts @@ -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, diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts index 292dccdfc..52b0bf5bb 100644 --- a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.spec.ts @@ -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, - ]) - }) }) diff --git a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts index e035cf598..476531947 100644 --- a/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts +++ b/src-ui/src/app/components/dashboard/widgets/saved-view-widget/saved-view-widget.component.ts @@ -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 { diff --git a/src-ui/src/app/components/document-list/document-list.component.spec.ts b/src-ui/src/app/components/document-list/document-list.component.spec.ts index e8d3a1e6e..04d33dff3 100644 --- a/src-ui/src/app/components/document-list/document-list.component.spec.ts +++ b/src-ui/src/app/components/document-list/document-list.component.spec.ts @@ -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' ) diff --git a/src-ui/src/app/services/consumer-status.service.spec.ts b/src-ui/src/app/services/consumer-status.service.spec.ts index d3867e889..b9066bbc0 100644 --- a/src-ui/src/app/services/consumer-status.service.spec.ts +++ b/src-ui/src/app/services/consumer-status.service.spec.ts @@ -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) }) diff --git a/src-ui/src/app/services/document-list-view.service.ts b/src-ui/src/app/services/document-list-view.service.ts index 1073e9b70..715095266 100644 --- a/src-ui/src/app/services/document-list-view.service.ts +++ b/src-ui/src/app/services/document-list-view.service.ts @@ -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[]) { diff --git a/src-ui/src/app/services/settings.service.spec.ts b/src-ui/src/app/services/settings.service.spec.ts index f0ce0d1c9..ae8976726 100644 --- a/src-ui/src/app/services/settings.service.spec.ts +++ b/src-ui/src/app/services/settings.service.spec.ts @@ -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( diff --git a/src-ui/src/app/services/settings.service.ts b/src-ui/src/app/services/settings.service.ts index 447fa058d..4a411bafc 100644 --- a/src-ui/src/app/services/settings.service.ts +++ b/src-ui/src/app/services/settings.service.ts @@ -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,