cat-documents-ng 0.1.28 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/ng-package.json +11 -0
  2. package/package.json +20 -25
  3. package/{Shared/constant/ERROR.d.ts → src/Shared/constant/ERROR.ts} +38 -36
  4. package/src/Shared/constant/PERMISSIONS.ts +16 -0
  5. package/src/Shared/constant/SHARED.ts +312 -0
  6. package/{Shared/constant/URLS.d.ts → src/Shared/constant/URLS.ts} +65 -60
  7. package/src/Shared/services/app-config.service.spec.ts +19 -0
  8. package/src/Shared/services/app-config.service.ts +73 -0
  9. package/{Shared/services/global-error.handler.d.ts → src/Shared/services/global-error.handler.ts} +29 -27
  10. package/src/Shared/services/session.service.spec.ts +16 -0
  11. package/src/Shared/services/session.service.ts +76 -0
  12. package/src/assets/config/api.config.json +20 -0
  13. package/src/lib/document/components/document-container/document-container.component.html +14 -0
  14. package/src/lib/document/components/document-container/document-container.component.scss +8 -0
  15. package/src/lib/document/components/document-container/document-container.component.spec.ts +110 -0
  16. package/src/lib/document/components/document-container/document-container.component.ts +173 -0
  17. package/src/lib/document/components/document-list/document-list.component.html +81 -0
  18. package/src/lib/document/components/document-list/document-list.component.scss +82 -0
  19. package/src/lib/document/components/document-list/document-list.component.spec.ts +96 -0
  20. package/src/lib/document/components/document-list/document-list.component.ts +244 -0
  21. package/src/lib/document/components/document-list-item/document-list-item.component.html +36 -0
  22. package/src/lib/document/components/document-list-item/document-list-item.component.scss +34 -0
  23. package/src/lib/document/components/document-list-item/document-list-item.component.spec.ts +75 -0
  24. package/src/lib/document/components/document-list-item/document-list-item.component.ts +40 -0
  25. package/src/lib/document/components/document-upload/document-upload.component.html +56 -0
  26. package/src/lib/document/components/document-upload/document-upload.component.scss +32 -0
  27. package/src/lib/document/components/document-upload/document-upload.component.spec.ts +95 -0
  28. package/src/lib/document/components/document-upload/document-upload.component.ts +162 -0
  29. package/src/lib/document/components/document-viewer/document-viewer.component.html +98 -0
  30. package/src/lib/document/components/document-viewer/document-viewer.component.scss +54 -0
  31. package/src/lib/document/components/document-viewer/document-viewer.component.spec.ts +79 -0
  32. package/src/lib/document/components/document-viewer/document-viewer.component.ts +106 -0
  33. package/src/lib/document/components/folder-block/folder-block.component.html +46 -0
  34. package/src/lib/document/components/folder-block/folder-block.component.scss +9 -0
  35. package/src/lib/document/components/folder-block/folder-block.component.spec.ts +70 -0
  36. package/{lib/document/components/folder-block/folder-block.component.d.ts → src/lib/document/components/folder-block/folder-block.component.ts} +53 -37
  37. package/src/lib/document/components/folder-container/folder-container.component.html +2 -0
  38. package/src/lib/document/components/folder-container/folder-container.component.scss +0 -0
  39. package/src/lib/document/components/folder-container/folder-container.component.spec.ts +27 -0
  40. package/src/lib/document/components/folder-container/folder-container.component.ts +37 -0
  41. package/src/lib/document/components/linked-document/linked-document.component.html +23 -0
  42. package/src/lib/document/components/linked-document/linked-document.component.scss +10 -0
  43. package/src/lib/document/components/linked-document/linked-document.component.spec.ts +61 -0
  44. package/src/lib/document/components/linked-document/linked-document.component.ts +49 -0
  45. package/src/lib/document/directives/document.directive.ts +32 -0
  46. package/src/lib/document/directives/permission.directive.spec.ts +0 -0
  47. package/src/lib/document/directives/permission.directive.ts +66 -0
  48. package/src/lib/document/document.module.ts +241 -0
  49. package/{lib/document/models/document-alert.model.d.ts → src/lib/document/models/document-alert.model.ts} +45 -38
  50. package/src/lib/document/models/document-type.model.ts +44 -0
  51. package/src/lib/document/models/document.model.ts +53 -0
  52. package/{lib/document/models/folder.model.d.ts → src/lib/document/models/folder.model.ts} +35 -29
  53. package/src/lib/document/services/document-http.service.spec.ts +119 -0
  54. package/src/lib/document/services/document-http.service.ts +125 -0
  55. package/src/lib/document/services/document-upload.service.spec.ts +99 -0
  56. package/src/lib/document/services/document-upload.service.ts +127 -0
  57. package/src/lib/document/services/document.service.ts +29 -0
  58. package/src/lib/document/services/file-format.service.spec.ts +16 -0
  59. package/src/lib/document/services/file-format.service.ts +41 -0
  60. package/src/lib/document/state/document.query.ts +52 -0
  61. package/{lib/document/state/document.service.d.ts → src/lib/document/state/document.service.ts} +95 -64
  62. package/{lib/document/state/document.state.d.ts → src/lib/document/state/document.state.ts} +52 -36
  63. package/src/lib/document/state/document.store.ts +51 -0
  64. package/{public-api.d.ts → src/public-api.ts} +10 -6
  65. package/tsconfig.lib.json +15 -0
  66. package/tsconfig.lib.prod.json +11 -0
  67. package/tsconfig.spec.json +15 -0
  68. package/Shared/constant/PERMISSIONS.d.ts +0 -15
  69. package/Shared/constant/SHARED.d.ts +0 -209
  70. package/Shared/services/app-config.service.d.ts +0 -51
  71. package/Shared/services/session.service.d.ts +0 -46
  72. package/fesm2022/cat-documents-ng.mjs +0 -2538
  73. package/fesm2022/cat-documents-ng.mjs.map +0 -1
  74. package/index.d.ts +0 -5
  75. package/lib/document/components/document-container/document-container.component.d.ts +0 -85
  76. package/lib/document/components/document-list/document-list.component.d.ts +0 -160
  77. package/lib/document/components/document-list-item/document-list-item.component.d.ts +0 -28
  78. package/lib/document/components/document-upload/document-upload.component.d.ts +0 -120
  79. package/lib/document/components/document-viewer/document-viewer.component.d.ts +0 -73
  80. package/lib/document/components/folder-container/folder-container.component.d.ts +0 -29
  81. package/lib/document/components/linked-document/linked-document.component.d.ts +0 -38
  82. package/lib/document/directives/document.directive.d.ts +0 -20
  83. package/lib/document/directives/permission.directive.d.ts +0 -38
  84. package/lib/document/document.module.d.ts +0 -40
  85. package/lib/document/models/document-type.model.d.ts +0 -37
  86. package/lib/document/models/document.model.d.ts +0 -44
  87. package/lib/document/services/document-http.service.d.ts +0 -69
  88. package/lib/document/services/document-upload.service.d.ts +0 -67
  89. package/lib/document/services/document.service.d.ts +0 -20
  90. package/lib/document/services/file-format.service.d.ts +0 -23
  91. package/lib/document/state/document.query.d.ts +0 -42
  92. package/lib/document/state/document.store.d.ts +0 -29
@@ -0,0 +1,70 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { FolderBlockComponent } from './folder-block.component';
3
+ import { SHARED } from '../../../../Shared/constant/SHARED';
4
+ import { DocumentStore } from '../../state/document.store';
5
+ import { FolderBlockModel } from '../../models/folder.model';
6
+
7
+ describe('FolderBlockComponent', () => {
8
+ let component: FolderBlockComponent;
9
+ let fixture: ComponentFixture<FolderBlockComponent>;
10
+ let mockDocumentStore: jasmine.SpyObj<DocumentStore>;
11
+
12
+ beforeEach(async () => {
13
+ mockDocumentStore = jasmine.createSpyObj('DocumentStore', ['setParentDocumentTypeId']); // Include the method here
14
+
15
+ await TestBed.configureTestingModule({
16
+ declarations: [FolderBlockComponent],
17
+ providers: [
18
+ { provide: DocumentStore, useValue: mockDocumentStore }
19
+ ],
20
+ }).compileComponents();
21
+
22
+ fixture = TestBed.createComponent(FolderBlockComponent);
23
+ component = fixture.componentInstance;
24
+
25
+ // Mock folder blocks input
26
+ component.folderList = [
27
+ { _id: '1', folderName: 'Folder 1', documentCount: 5 },
28
+ { _id: '2', folderName: 'Folder 2', documentCount: 3 },
29
+ ] as FolderBlockModel[];
30
+
31
+ fixture.detectChanges();
32
+ });
33
+
34
+
35
+ it('should create', () => {
36
+ expect(component).toBeTruthy();
37
+ });
38
+
39
+ it('should render the folder blocks correctly', () => {
40
+ const folderElements = fixture.debugElement.nativeElement.querySelectorAll('.grid .col-12');
41
+ expect(folderElements.length).toBe(2); // Should match the length of folderBlocks input
42
+ });
43
+
44
+ it('should display the correct file count for each folder', () => {
45
+ const folderTextElements = fixture.debugElement.nativeElement.querySelectorAll('.text-600');
46
+ expect(folderTextElements[0].textContent).toContain('5 Files');
47
+ expect(folderTextElements[1].textContent).toContain('3 Files');
48
+ });
49
+
50
+ it('should return correct folderBlockId from handleClickForFilter', () => {
51
+ const validFolderBlockId = '1';
52
+ const invalidFolderBlockId = '';
53
+
54
+ expect(component.handleClickForFilter(validFolderBlockId)).toBe(validFolderBlockId);
55
+ expect(component.handleClickForFilter(invalidFolderBlockId)).toBe(SHARED.EMPTY);
56
+ });
57
+
58
+ it('should display the missing and pending file counts correctly', () => {
59
+ const missingFileCountElements = fixture.debugElement.nativeElement.querySelectorAll('.text-pink-500');
60
+ const pendingFileCountElements = fixture.debugElement.nativeElement.querySelectorAll('.text-yellow-500');
61
+
62
+ expect(missingFileCountElements.length).toBeGreaterThan(0); // Check if any element with `text-pink-500` class is present
63
+ expect(pendingFileCountElements.length).toBeGreaterThan(0); // Check if any element with `text-yellow-500` class is present
64
+ });
65
+
66
+ it('should set the missingFileCount and pendingFileCount to SHARED constants', () => {
67
+ expect(component.missingFileCount).toBe(SHARED.MISSINGCOUNT);
68
+ expect(component.pendingFileCount).toBe(SHARED.PENDINGCOUNT);
69
+ });
70
+ });
@@ -1,37 +1,53 @@
1
- import { DocumentStore } from '../../state/document.store';
2
- import { FolderBlockModel } from '../../models/folder.model';
3
- import * as i0 from "@angular/core";
4
- /**
5
- * The `FolderBlockComponent` is responsible for displaying a block of folders and
6
- * providing filtering functionality based on folder IDs.
7
- *
8
- * It uses data from the `DocumentStore` and constants from the `SHARED` configuration
9
- * to display missing and pending file counts.
10
- */
11
- export declare class FolderBlockComponent {
12
- documentStore: DocumentStore;
13
- /**
14
- * Array of folder blocks data to display.
15
- * Each folder is represented as a `FolderBlockModel`.
16
- */
17
- folderList: FolderBlockModel[];
18
- /** Number of missing files, sourced from the `SHARED` constants. */
19
- missingFileCount: number;
20
- /** Number of pending files, sourced from the `SHARED` constants. */
21
- pendingFileCount: number;
22
- /**
23
- * Injects the `DocumentStore` service to manage and access document-related state.
24
- * @param {DocumentStore} documentStore - The state management store for documents.
25
- */
26
- constructor(documentStore: DocumentStore);
27
- /**
28
- * Handles the click event for filtering based on the provided folder ID.
29
- * This method validates the folder ID and returns it for further processing.
30
- * If the folder ID is not provided, an empty string is returned.
31
- * @param {string} folderBlockId - The unique identifier of the folder to filter by.
32
- * @returns {string} The validated folder ID, or an empty string if the input is invalid.
33
- */
34
- handleClickForFilter(folderBlockId: any): string;
35
- static ɵfac: i0.ɵɵFactoryDeclaration<FolderBlockComponent, never>;
36
- static ɵcmp: i0.ɵɵComponentDeclaration<FolderBlockComponent, "lib-folder-block", never, { "folderList": { "alias": "folderList"; "required": false; }; }, {}, never, never, false, never>;
37
- }
1
+ import { Component, Input } from '@angular/core';
2
+ import { DocumentStore } from '../../state/document.store';
3
+ import { FolderBlockModel } from '../../models/folder.model';
4
+ import { SHARED } from '../../../../Shared/constant/SHARED';
5
+
6
+ /**
7
+ * The `FolderBlockComponent` is responsible for displaying a block of folders and
8
+ * providing filtering functionality based on folder IDs.
9
+ *
10
+ * It uses data from the `DocumentStore` and constants from the `SHARED` configuration
11
+ * to display missing and pending file counts.
12
+ */
13
+ @Component({
14
+ selector: 'lib-folder-block',
15
+ standalone: false,
16
+ templateUrl: './folder-block.component.html',
17
+ styleUrl: './folder-block.component.scss'
18
+ })
19
+ export class FolderBlockComponent {
20
+ /**
21
+ * Array of folder blocks data to display.
22
+ * Each folder is represented as a `FolderBlockModel`.
23
+ */
24
+ @Input() folderList : FolderBlockModel[] = SHARED.EMPTY_ARRAY;
25
+
26
+ /** Number of missing files, sourced from the `SHARED` constants. */
27
+ missingFileCount = SHARED.MISSINGCOUNT;
28
+
29
+ /** Number of pending files, sourced from the `SHARED` constants. */
30
+ pendingFileCount = SHARED.PENDINGCOUNT;
31
+
32
+ /**
33
+ * Injects the `DocumentStore` service to manage and access document-related state.
34
+ * @param {DocumentStore} documentStore - The state management store for documents.
35
+ */
36
+ constructor(public documentStore: DocumentStore) {}
37
+
38
+ /**
39
+ * Handles the click event for filtering based on the provided folder ID.
40
+ * This method validates the folder ID and returns it for further processing.
41
+ * If the folder ID is not provided, an empty string is returned.
42
+ * @param {string} folderBlockId - The unique identifier of the folder to filter by.
43
+ * @returns {string} The validated folder ID, or an empty string if the input is invalid.
44
+ */
45
+ handleClickForFilter(folderBlockId: string): string {
46
+ if (!folderBlockId) {
47
+ return SHARED.EMPTY;
48
+ }
49
+ this.documentStore.setParentDocumentTypeId(folderBlockId);
50
+ return folderBlockId;
51
+ }
52
+
53
+ }
@@ -0,0 +1,2 @@
1
+
2
+ <lib-folder-block [folderList]="folderList"></lib-folder-block>
@@ -0,0 +1,27 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { Listbox, ListboxModule } from 'primeng/listbox';
3
+ import { TimelineModule } from 'primeng/timeline';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { CheckboxModule } from 'primeng/checkbox';
6
+ import { FolderContainerComponent } from './folder-container.component';
7
+ import { FolderBlockComponent } from '../folder-block/folder-block.component';
8
+
9
+ describe('FolderContainerComponent', () => {
10
+ let component: FolderContainerComponent;
11
+ let fixture: ComponentFixture<FolderContainerComponent>;
12
+
13
+ beforeEach(async () => {
14
+ await TestBed.configureTestingModule({
15
+ declarations: [FolderContainerComponent , FolderBlockComponent],
16
+ imports : [ListboxModule, TimelineModule, FormsModule, CheckboxModule]
17
+ }).compileComponents();
18
+
19
+ fixture = TestBed.createComponent(FolderContainerComponent);
20
+ component = fixture.componentInstance;
21
+ fixture.detectChanges();
22
+ });
23
+
24
+ it('should create', () => {
25
+ expect(component).toBeTruthy();
26
+ });
27
+ });
@@ -0,0 +1,37 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { FOLDERPANEL, SHARED } from '../../../../Shared/constant/SHARED';
3
+ import { DocumentModel } from '../../models/document.model';
4
+ import { FolderBlockModel } from '../../models/folder.model';
5
+
6
+ /**
7
+ * The `FolderContainerComponent` is responsible for rendering a container
8
+ * that displays a list of documents and associated folder panel data.
9
+ *
10
+ * This component utilizes the `FOLDERPANEL` constant for folder panel data
11
+ * and accepts a document list input of type `DocumentModel`.
12
+ */
13
+ @Component({
14
+ selector: 'lib-folder-container',
15
+ standalone: false,
16
+ templateUrl: './folder-container.component.html',
17
+ styleUrl: './folder-container.component.scss'
18
+ })
19
+ export class FolderContainerComponent {
20
+ /**
21
+ * A list of documents passed as input to the component.
22
+ * Represents the document data to be displayed in the folder container.
23
+ */
24
+ @Input() documentList?: DocumentModel[];
25
+ /**
26
+ * A list of documents passed as input to the component.
27
+ * Represents the document data to be displayed in the folder container.
28
+ */
29
+ @Input() folderList: FolderBlockModel[] = SHARED.EMPTY_ARRAY;
30
+
31
+ /**
32
+ * The context ID for the folder container.
33
+ * @type {string}
34
+ */
35
+ @Input() contextId: string = SHARED.EMPTY;
36
+
37
+ }
@@ -0,0 +1,23 @@
1
+ <div class="summary-card mb-4 pb-1">
2
+ <div class="card p-0 mb-0"
3
+ style="border-bottom: 1px solid;border-color: rgba(68, 72, 109, 0.2); border-bottom-right-radius: 0px;border-bottom-left-radius: 0px; background-color: #F9fafb;">
4
+ <div class="p-0">
5
+ <h4 class="m-0 pt-3 pl-3 mb-3" style="font-size: 21px; font-weight: bold; ">Linked Documents</h4>
6
+ </div>
7
+ </div>
8
+ <div class="card mb-0" style="border-top-right-radius: 0px;border-top-left-radius: 0px;">
9
+ @for(document of documentList; track document){
10
+ <div class="linkedDocument documentName m-2">
11
+ <div class="documentName" [class.selected]="document._id === selectedDocument?._id"
12
+ (click)="handleDocumentClick(document)">
13
+ <span class="pi pi-link"></span>
14
+ {{document.fileName}}
15
+ </div>
16
+ </div>
17
+ }
18
+
19
+ </div>
20
+
21
+
22
+ </div>
23
+
@@ -0,0 +1,10 @@
1
+ .documentName{
2
+ font-family: inherit;
3
+ text-decoration: underline;
4
+ cursor: pointer;
5
+ width: max-content;
6
+ }
7
+ .selected{
8
+ color: var(--primary-color);
9
+
10
+ }
@@ -0,0 +1,61 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { LinkedDocumentComponent } from './linked-document.component';
3
+ import { DocumentModel } from '../../models/document.model';
4
+ import { Component, Input } from '@angular/core';
5
+
6
+ /**
7
+ * A mock child component used for testing the LinkedDocumentComponent.
8
+ * It mimics a real child component that receives document-related inputs.
9
+ */
10
+ @Component({
11
+ selector: 'app-mock-child',
12
+ template: ''
13
+ })
14
+ class MockChildComponent {
15
+ /**
16
+ * Represents the currently selected document.
17
+ */
18
+ @Input() selectedDocument?: DocumentModel;
19
+
20
+ /**
21
+ * A list of available documents.
22
+ */
23
+ @Input() documentList?: DocumentModel[];
24
+ }
25
+
26
+ describe('LinkedDocumentComponent', () => {
27
+ let component: LinkedDocumentComponent;
28
+ let fixture: ComponentFixture<LinkedDocumentComponent>;
29
+
30
+ beforeEach(async () => {
31
+ await TestBed.configureTestingModule({
32
+ declarations: [LinkedDocumentComponent],
33
+ }).compileComponents();
34
+ });
35
+
36
+ beforeEach(() => {
37
+ fixture = TestBed.createComponent(LinkedDocumentComponent);
38
+ component = fixture.componentInstance;
39
+ fixture.detectChanges();
40
+ });
41
+
42
+ /**
43
+ * Ensures that the component is created successfully.
44
+ */
45
+ it('should create', () => {
46
+ expect(component).toBeTruthy();
47
+ });
48
+
49
+ /**
50
+ * Tests whether the `handleDocumentClick` method correctly emits
51
+ * the `selectedDocumentChange` event with the expected document data.
52
+ */
53
+ it('should emit selectedDocumentChange event when handleDocumentClick is called', () => {
54
+ spyOn(component.selectedDocumentChange, 'emit');
55
+ const document: DocumentModel = { _id: '1', fileName: 'Doc1' };
56
+
57
+ component.handleDocumentClick(document);
58
+
59
+ expect(component.selectedDocumentChange.emit).toHaveBeenCalledWith(document);
60
+ });
61
+ });
@@ -0,0 +1,49 @@
1
+ import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
2
+ import { DocumentQuery } from '../../state/document.query';
3
+ import { DocumentModel } from '../../models/document.model';
4
+
5
+ /**
6
+ * Description placeholder
7
+ * @class LinkedDocumentComponent
8
+ * @typedef {LinkedDocumentComponent}
9
+ * @implements {OnChanges}
10
+ */
11
+ @Component({
12
+ selector: 'app-linked-document',
13
+ templateUrl: './linked-document.component.html',
14
+ styleUrl: './linked-document.component.scss',
15
+ standalone : false
16
+ })
17
+ export class LinkedDocumentComponent {
18
+ /**
19
+ * Selected document for view.
20
+ * @type {?DocumentModel}
21
+ */
22
+ @Input() selectedDocument?: DocumentModel;
23
+ /**
24
+ * Whole document list.
25
+ * @type {?DocumentModel[]}
26
+ */
27
+ @Input() documentList?: DocumentModel[];
28
+ /**
29
+ * Changed selected document.
30
+ * @type {*}
31
+ */
32
+ @Output() selectedDocumentChange = new EventEmitter<DocumentModel>();
33
+
34
+ /**
35
+ * Filtered documents.
36
+ * @type {DocumentModel[]}
37
+ */
38
+ filteredDocuments: DocumentModel[] = [];
39
+
40
+ /**
41
+ * Handle the click on the document.
42
+ * @param {DocumentModel} document - Clicked document.
43
+ */
44
+ handleDocumentClick(document: DocumentModel): void {
45
+ this.selectedDocument = document;
46
+ this.selectedDocumentChange.emit(this.selectedDocument);
47
+ }
48
+
49
+ }
@@ -0,0 +1,32 @@
1
+ import { Directive, TemplateRef, ViewContainerRef } from "@angular/core";
2
+ import { DocumentService } from "../services/document.service";
3
+ import { DocumentModel } from "../models/document.model";
4
+
5
+ /**
6
+ * Directive to display the document data
7
+ */
8
+ @Directive({
9
+ selector: '[doc]',
10
+ standalone: false
11
+ })
12
+ export class DocumentDirective {
13
+
14
+ /**
15
+ * Creates an instance of DocumentDirective.
16
+ * @param documentService Service to get the document data.
17
+ * @param templateRef Reference to the template.
18
+ * @param vcr View container reference to manage the view.
19
+ */
20
+ constructor(
21
+ private documentService: DocumentService,
22
+ private templateRef: TemplateRef<any>,
23
+ private vcr: ViewContainerRef
24
+ ) {
25
+ this.documentService.get().subscribe((document: DocumentModel | null) => {
26
+ this.vcr.clear();
27
+ if (document) {
28
+ this.vcr.createEmbeddedView(this.templateRef, { $implicit: document });
29
+ }
30
+ });
31
+ }
32
+ }
@@ -0,0 +1,66 @@
1
+ import { Directive, Input, ElementRef, Renderer2, SimpleChanges, OnChanges } from '@angular/core';
2
+ import { SessionService } from '../../../Shared/services/session.service';
3
+
4
+ /**
5
+ * Directive to conditionally show or hide elements based on user permissions.
6
+ * @class HasPermissionDirective
7
+ * @typedef {HasPermissionDirective}
8
+ */
9
+ @Directive({
10
+ selector: '[permission]',
11
+ standalone: false
12
+ })
13
+ export class HasPermissionDirective implements OnChanges {
14
+
15
+ /**
16
+ * The required permission(s) to display the element.
17
+ * Accepts a single string or an array of strings.
18
+ * @type {string | string[]}
19
+ */
20
+ @Input() permission?: string | string[];
21
+
22
+ /**
23
+ * Creates an instance of HasPermissionDirective.
24
+ * @param {ElementRef} el - Reference to the host element.
25
+ * @param {Renderer2} renderer - Angular Renderer for DOM manipulation.
26
+ * @param {SessionService} sessionService - Service to retrieve user permissions.
27
+ */
28
+ constructor(
29
+ private el: ElementRef,
30
+ private renderer: Renderer2,
31
+ public sessionService: SessionService
32
+ ) {}
33
+
34
+ /**
35
+ * Lifecycle hook that is called when input properties change.
36
+ * @param {SimpleChanges} changes - The changes in input properties.
37
+ */
38
+ ngOnChanges(changes: SimpleChanges) {
39
+ if (changes['permission']) {
40
+ this.checkPermission();
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Checks if the user has the required permission(s).
46
+ * Hides the element if the permission is not found.
47
+ */
48
+ private checkPermission() {
49
+ const userPermissionsObjects = this.sessionService.getUserPermissions();
50
+ const userPermissionNames = userPermissionsObjects?.map((perm: any) => perm.name) || [];
51
+
52
+ const requiredPermissions = Array.isArray(this.permission)
53
+ ? this.permission
54
+ : [this.permission];
55
+
56
+ const hasPermission = requiredPermissions.some(permission =>
57
+ userPermissionNames.includes(permission)
58
+ );
59
+
60
+ if (!hasPermission) {
61
+ this.renderer.setStyle(this.el.nativeElement, 'display', 'none');
62
+ } else {
63
+ this.renderer.removeStyle(this.el.nativeElement, 'display');
64
+ }
65
+ }
66
+ }