import { NgComponentOutlet } from '@angular/common' import { Component, inject, OnDestroy, OnInit, QueryList, Type, ViewChild, ViewChildren, } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { NgbDropdownModule, NgbNavChangeEvent, NgbNavModule, } from '@ng-bootstrap/ng-bootstrap' import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons' import { Subject, takeUntil } from 'rxjs' import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' import { PermissionAction, PermissionsService, PermissionType, } from 'src/app/services/permissions.service' import { ClearableBadgeComponent } from '../../common/clearable-badge/clearable-badge.component' import { PageHeaderComponent } from '../../common/page-header/page-header.component' import { CustomFieldsComponent } from './custom-fields/custom-fields.component' import { CorrespondentListComponent } from './management-list/correspondent-list/correspondent-list.component' import { DocumentTypeListComponent } from './management-list/document-type-list/document-type-list.component' import { ManagementListComponent } from './management-list/management-list.component' import { StoragePathListComponent } from './management-list/storage-path-list/storage-path-list.component' import { TagListComponent } from './management-list/tag-list/tag-list.component' enum DocumentAttributesNavIDs { Tags = 1, Correspondents = 2, DocumentTypes = 3, StoragePaths = 4, CustomFields = 5, } type DocumentAttributesSectionKind = 'attributeList' | 'customFields' interface DocumentAttributesSection { id: DocumentAttributesNavIDs path: string label: string icon: string permissionType: PermissionType kind: DocumentAttributesSectionKind component: Type } @Component({ selector: 'pngx-document-attributes', templateUrl: './document-attributes.component.html', styleUrls: ['./document-attributes.component.scss'], imports: [ PageHeaderComponent, NgbNavModule, NgbDropdownModule, NgComponentOutlet, NgxBootstrapIconsModule, IfPermissionsDirective, ClearableBadgeComponent, ], }) export class DocumentAttributesComponent implements OnInit, OnDestroy { private readonly permissionsService = inject(PermissionsService) private readonly activatedRoute = inject(ActivatedRoute) private readonly router = inject(Router) private readonly unsubscribeNotifier = new Subject() protected readonly PermissionAction = PermissionAction protected readonly PermissionType = PermissionType readonly sections: DocumentAttributesSection[] = [ { id: DocumentAttributesNavIDs.Tags, path: 'tags', label: $localize`Tags`, icon: 'tags', permissionType: PermissionType.Tag, kind: 'attributeList', component: TagListComponent, }, { id: DocumentAttributesNavIDs.Correspondents, path: 'correspondents', label: $localize`Correspondents`, icon: 'person', permissionType: PermissionType.Correspondent, kind: 'attributeList', component: CorrespondentListComponent, }, { id: DocumentAttributesNavIDs.DocumentTypes, path: 'documenttypes', label: $localize`Document types`, icon: 'hash', permissionType: PermissionType.DocumentType, kind: 'attributeList', component: DocumentTypeListComponent, }, { id: DocumentAttributesNavIDs.StoragePaths, path: 'storagepaths', label: $localize`Storage paths`, icon: 'folder', permissionType: PermissionType.StoragePath, kind: 'attributeList', component: StoragePathListComponent, }, { id: DocumentAttributesNavIDs.CustomFields, path: 'customfields', label: $localize`Custom fields`, icon: 'ui-radios', permissionType: PermissionType.CustomField, kind: 'customFields', component: CustomFieldsComponent, }, ] @ViewChildren(ManagementListComponent) private attributeLists?: QueryList> @ViewChild(CustomFieldsComponent) private customFields?: CustomFieldsComponent activeNavID: number = null get visibleSections(): DocumentAttributesSection[] { return this.sections.filter((section) => this.permissionsService.currentUserCan( PermissionAction.View, section.permissionType ) ) } get activeSection(): DocumentAttributesSection | null { return ( this.visibleSections.find((section) => section.id === this.activeNavID) ?? null ) } get activeAttributeList(): ManagementListComponent | null { if (this.activeSection?.kind !== 'attributeList') return null const permissionType = this.activeSection.permissionType return ( this.attributeLists?.find( (list) => list.permissionType === permissionType ) ?? null ) } get activeCustomFields(): CustomFieldsComponent | null { return this.activeSection?.kind === 'customFields' ? (this.customFields ?? null) : null } get activeTabLabel(): string { return this.activeSection?.label ?? '' } get activeHeaderLoading(): boolean { return ( this.activeAttributeList?.loading ?? this.activeCustomFields?.loading ?? false ) } ngOnInit(): void { this.activatedRoute.paramMap .pipe(takeUntil(this.unsubscribeNotifier)) .subscribe((paramMap) => { const section = paramMap.get('section') const navIDFromSection = this.getNavIDForSection(section) ?? this.getDefaultNavID() if (navIDFromSection == null) { this.router.navigate(['/dashboard'], { replaceUrl: true }) return } if (this.activeNavID !== navIDFromSection) { this.activeNavID = navIDFromSection } if (!section || this.getNavIDForSection(section) == null) { this.router.navigate( ['attributes', this.getSectionForNavID(this.activeNavID)], { replaceUrl: true } ) } }) } ngOnDestroy(): void { this.unsubscribeNotifier.next() this.unsubscribeNotifier.complete() } onNavChange(navChangeEvent: NgbNavChangeEvent): void { const nextSection = this.getSectionForNavID(navChangeEvent.nextId) if (!nextSection) { return } this.router.navigate(['attributes', nextSection]) } private getDefaultNavID(): DocumentAttributesNavIDs | null { return this.visibleSections[0]?.id ?? null } private getNavIDForSection(section: string): DocumentAttributesNavIDs | null { const path = section?.toLowerCase() if (!path) return null const found = this.visibleSections.find((s) => s.path === path) return found?.id ?? null } private getSectionForNavID(navID: number): string | null { const section = this.visibleSections.find((s) => s.id === navID) return section?.path ?? null } }