cat-documents-ng 1.0.4 → 1.0.6

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 (210) hide show
  1. package/ng-package.json +10 -0
  2. package/package.json +5 -11
  3. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.html +3 -0
  4. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.scss +13 -0
  5. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.spec.ts +70 -0
  6. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.ts +133 -0
  7. package/src/Shared/components/table-primary/table-primary.component.html +66 -0
  8. package/src/Shared/components/table-primary/table-primary.component.scss +227 -0
  9. package/src/Shared/components/table-primary/table-primary.component.spec.ts +23 -0
  10. package/src/Shared/components/table-primary/table-primary.component.ts +143 -0
  11. package/src/Shared/components/table-primary/table-primary.model.ts +21 -0
  12. package/src/Shared/constant/ERROR.ts +55 -0
  13. package/src/Shared/constant/PERMISSIONS.ts +17 -0
  14. package/src/Shared/constant/SHARED.ts +936 -0
  15. package/{Shared/constant/URLS.d.ts → src/Shared/constant/URLS.ts} +31 -25
  16. package/src/Shared/services/app-config.service.spec.ts +19 -0
  17. package/src/Shared/services/app-config.service.ts +73 -0
  18. package/{Shared/services/global-error.handler.d.ts → src/Shared/services/global-error.handler.ts} +11 -9
  19. package/src/Shared/services/session.service.spec.ts +16 -0
  20. package/src/Shared/services/session.service.ts +76 -0
  21. package/src/Shared/shared.module.ts +25 -0
  22. package/src/lib/document/components/csv-viewer/csv-viewer.component.ts +1 -0
  23. package/src/lib/document/components/document-actions/document-actions.component.html +59 -0
  24. package/src/lib/document/components/document-actions/document-actions.component.scss +362 -0
  25. package/src/lib/document/components/document-actions/document-actions.component.spec.ts +297 -0
  26. package/src/lib/document/components/document-actions/document-actions.component.ts +163 -0
  27. package/src/lib/document/components/document-container/document-container.component.html +36 -0
  28. package/src/lib/document/components/document-container/document-container.component.scss +144 -0
  29. package/src/lib/document/components/document-container/document-container.component.spec.ts +110 -0
  30. package/src/lib/document/components/document-container/document-container.component.ts +363 -0
  31. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.html +332 -0
  32. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.scss +1877 -0
  33. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.spec.ts +258 -0
  34. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.ts +664 -0
  35. package/src/lib/document/components/document-history/document-history.component.html +96 -0
  36. package/src/lib/document/components/document-history/document-history.component.scss +392 -0
  37. package/src/lib/document/components/document-history/document-history.component.spec.ts +93 -0
  38. package/src/lib/document/components/document-history/document-history.component.ts +373 -0
  39. package/src/lib/document/components/document-list/document-list.component.html +46 -0
  40. package/src/lib/document/components/document-list/document-list.component.scss +513 -0
  41. package/src/lib/document/components/document-list/document-list.component.spec.ts +486 -0
  42. package/src/lib/document/components/document-list/document-list.component.ts +682 -0
  43. package/src/lib/document/components/document-list-item/document-list-item.component.html +36 -0
  44. package/src/lib/document/components/document-list-item/document-list-item.component.scss +34 -0
  45. package/src/lib/document/components/document-list-item/document-list-item.component.spec.ts +75 -0
  46. package/src/lib/document/components/document-list-item/document-list-item.component.ts +40 -0
  47. package/src/lib/document/components/document-search/document-search.component.html +64 -0
  48. package/src/lib/document/components/document-search/document-search.component.scss +206 -0
  49. package/src/lib/document/components/document-search/document-search.component.spec.ts +82 -0
  50. package/src/lib/document/components/document-search/document-search.component.ts +163 -0
  51. package/src/lib/document/components/document-status/document-status.component.html +31 -0
  52. package/src/lib/document/components/document-status/document-status.component.scss +192 -0
  53. package/src/lib/document/components/document-status/document-status.component.spec.ts +23 -0
  54. package/src/lib/document/components/document-status/document-status.component.ts +87 -0
  55. package/src/lib/document/components/document-upload/document-upload.component.html +160 -0
  56. package/src/lib/document/components/document-upload/document-upload.component.scss +235 -0
  57. package/src/lib/document/components/document-upload/document-upload.component.spec.ts +95 -0
  58. package/src/lib/document/components/document-upload/document-upload.component.ts +668 -0
  59. package/src/lib/document/components/document-viewer/document-viewer.component.html +50 -0
  60. package/src/lib/document/components/document-viewer/document-viewer.component.scss +187 -0
  61. package/src/lib/document/components/document-viewer/document-viewer.component.spec.ts +79 -0
  62. package/src/lib/document/components/document-viewer/document-viewer.component.ts +261 -0
  63. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.html +48 -0
  64. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.scss +320 -0
  65. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.spec.ts +59 -0
  66. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.ts +150 -0
  67. package/src/lib/document/components/documents-menu/documents-menu.component.html +44 -0
  68. package/src/lib/document/components/documents-menu/documents-menu.component.scss +363 -0
  69. package/src/lib/document/components/documents-menu/documents-menu.component.spec.ts +23 -0
  70. package/src/lib/document/components/documents-menu/documents-menu.component.ts +316 -0
  71. package/src/lib/document/components/folder-block/folder-block.component.html +46 -0
  72. package/src/lib/document/components/folder-block/folder-block.component.scss +9 -0
  73. package/src/lib/document/components/folder-block/folder-block.component.spec.ts +70 -0
  74. package/{lib/document/components/folder-block/folder-block.component.d.ts → src/lib/document/components/folder-block/folder-block.component.ts} +28 -12
  75. package/src/lib/document/components/folder-container/folder-container.component.html +56 -0
  76. package/src/lib/document/components/folder-container/folder-container.component.scss +20 -0
  77. package/src/lib/document/components/folder-container/folder-container.component.spec.ts +27 -0
  78. package/src/lib/document/components/folder-container/folder-container.component.ts +328 -0
  79. package/src/lib/document/components/linked-document/linked-document.component.html +23 -0
  80. package/src/lib/document/components/linked-document/linked-document.component.scss +10 -0
  81. package/src/lib/document/components/linked-document/linked-document.component.spec.ts +61 -0
  82. package/src/lib/document/components/linked-document/linked-document.component.ts +49 -0
  83. package/src/lib/document/components/request-document/request-document.component.html +86 -0
  84. package/src/lib/document/components/request-document/request-document.component.scss +16 -0
  85. package/src/lib/document/components/request-document/request-document.component.ts +278 -0
  86. package/src/lib/document/components/sidebar/sidebar.component.html +75 -0
  87. package/src/lib/document/components/sidebar/sidebar.component.scss +157 -0
  88. package/src/lib/document/components/sidebar/sidebar.component.spec.ts +114 -0
  89. package/src/lib/document/components/sidebar/sidebar.component.ts +223 -0
  90. package/src/lib/document/components/user-list/user-list.component.html +33 -0
  91. package/src/lib/document/components/user-list/user-list.component.scss +118 -0
  92. package/src/lib/document/components/user-list/user-list.component.spec.ts +23 -0
  93. package/src/lib/document/components/user-list/user-list.component.ts +181 -0
  94. package/src/lib/document/constant/DOCUMENT_HISTORY.ts +52 -0
  95. package/src/lib/document/directives/document.directive.ts +32 -0
  96. package/src/lib/document/directives/permission.directive.spec.ts +0 -0
  97. package/src/lib/document/directives/permission.directive.ts +72 -0
  98. package/src/lib/document/document.module.ts +351 -0
  99. package/{lib/document/models/document-alert.model.d.ts → src/lib/document/models/document-alert.model.ts} +11 -4
  100. package/src/lib/document/models/document-category.model.ts +30 -0
  101. package/src/lib/document/models/document-history.model.ts +109 -0
  102. package/src/lib/document/models/document-list-response.model.ts +37 -0
  103. package/src/lib/document/models/document-type.model.ts +44 -0
  104. package/src/lib/document/models/document.model.ts +53 -0
  105. package/{lib/document/models/folder.model.d.ts → src/lib/document/models/folder.model.ts} +10 -4
  106. package/src/lib/document/models/status-data.model.ts +31 -0
  107. package/src/lib/document/models/uploaded-file-response.model.ts +7 -0
  108. package/src/lib/document/models/user-list.model.ts +10 -0
  109. package/src/lib/document/services/csv-parser.service.spec.ts +97 -0
  110. package/src/lib/document/services/csv-parser.service.ts +303 -0
  111. package/src/lib/document/services/document-actions.service.ts +125 -0
  112. package/src/lib/document/services/document-content-type.service.ts +193 -0
  113. package/src/lib/document/services/document-history-style.service.ts +138 -0
  114. package/src/lib/document/services/document-history.service.ts +129 -0
  115. package/src/lib/document/services/document-http.service.spec.ts +119 -0
  116. package/src/lib/document/services/document-http.service.ts +497 -0
  117. package/src/lib/document/services/document-list.service.ts +195 -0
  118. package/src/lib/document/services/document-menu.service.ts +277 -0
  119. package/src/lib/document/services/document-scroll.service.ts +138 -0
  120. package/src/lib/document/services/document-severity.service.ts +98 -0
  121. package/src/lib/document/services/document-table-builder.service.ts +82 -0
  122. package/src/lib/document/services/document-upload-business.service.ts +326 -0
  123. package/src/lib/document/services/document-upload-data.service.ts +82 -0
  124. package/src/lib/document/services/document-upload-form.service.ts +149 -0
  125. package/src/lib/document/services/document-upload.service.spec.ts +99 -0
  126. package/src/lib/document/services/document-upload.service.ts +209 -0
  127. package/src/lib/document/services/document-viewer.service.ts +279 -0
  128. package/src/lib/document/services/document-zoom.service.spec.ts +56 -0
  129. package/src/lib/document/services/document-zoom.service.ts +164 -0
  130. package/src/lib/document/services/document.service.ts +356 -0
  131. package/src/lib/document/services/eml-parser.service.ts +444 -0
  132. package/src/lib/document/services/excel-parser.service.spec.ts +66 -0
  133. package/src/lib/document/services/excel-parser.service.ts +483 -0
  134. package/src/lib/document/services/file-format.service.spec.ts +16 -0
  135. package/src/lib/document/services/file-format.service.ts +63 -0
  136. package/src/lib/document/services/status-calculator.service.ts +44 -0
  137. package/src/lib/document/services/user-list.service.ts +77 -0
  138. package/src/lib/document/state/document.query.ts +378 -0
  139. package/{lib/document/state/document.service.d.ts → src/lib/document/state/document.service.ts} +46 -15
  140. package/src/lib/document/state/document.state.ts +100 -0
  141. package/src/lib/document/state/document.store.ts +200 -0
  142. package/{public-api.d.ts → src/public-api.ts} +4 -0
  143. package/tsconfig.lib.json +15 -0
  144. package/tsconfig.lib.prod.json +11 -0
  145. package/tsconfig.spec.json +15 -0
  146. package/Shared/components/confirmation-dialog/confirmation-dialog.component.d.ts +0 -44
  147. package/Shared/components/table-primary/table-primary.component.d.ts +0 -31
  148. package/Shared/components/table-primary/table-primary.model.d.ts +0 -19
  149. package/Shared/constant/ERROR.d.ts +0 -52
  150. package/Shared/constant/SHARED.d.ts +0 -546
  151. package/Shared/services/app-config.service.d.ts +0 -51
  152. package/Shared/services/session.service.d.ts +0 -46
  153. package/Shared/shared.module.d.ts +0 -14
  154. package/fesm2022/cat-documents-ng.mjs +0 -11392
  155. package/fesm2022/cat-documents-ng.mjs.map +0 -1
  156. package/index.d.ts +0 -5
  157. package/lib/document/components/document-actions/document-actions.component.d.ts +0 -78
  158. package/lib/document/components/document-container/document-container.component.d.ts +0 -162
  159. package/lib/document/components/document-content-viewer/document-content-viewer.component.d.ts +0 -291
  160. package/lib/document/components/document-history/document-history.component.d.ts +0 -160
  161. package/lib/document/components/document-list/document-list.component.d.ts +0 -299
  162. package/lib/document/components/document-list-item/document-list-item.component.d.ts +0 -28
  163. package/lib/document/components/document-search/document-search.component.d.ts +0 -77
  164. package/lib/document/components/document-status/document-status.component.d.ts +0 -24
  165. package/lib/document/components/document-upload/document-upload.component.d.ts +0 -321
  166. package/lib/document/components/document-viewer/document-viewer.component.d.ts +0 -137
  167. package/lib/document/components/document-zoom-controls/document-zoom-controls.component.d.ts +0 -33
  168. package/lib/document/components/documents-menu/documents-menu.component.d.ts +0 -110
  169. package/lib/document/components/folder-container/folder-container.component.d.ts +0 -162
  170. package/lib/document/components/linked-document/linked-document.component.d.ts +0 -39
  171. package/lib/document/components/request-document/request-document.component.d.ts +0 -69
  172. package/lib/document/components/sidebar/sidebar.component.d.ts +0 -109
  173. package/lib/document/components/user-list/user-list.component.d.ts +0 -34
  174. package/lib/document/constant/DOCUMENT_HISTORY.d.ts +0 -41
  175. package/lib/document/directives/document.directive.d.ts +0 -20
  176. package/lib/document/directives/permission.directive.d.ts +0 -38
  177. package/lib/document/document.module.d.ts +0 -60
  178. package/lib/document/models/document-category.model.d.ts +0 -24
  179. package/lib/document/models/document-history.model.d.ts +0 -94
  180. package/lib/document/models/document-list-response.model.d.ts +0 -33
  181. package/lib/document/models/document-type.model.d.ts +0 -37
  182. package/lib/document/models/document.model.d.ts +0 -44
  183. package/lib/document/models/status-data.model.d.ts +0 -27
  184. package/lib/document/models/uploaded-file-response.model.d.ts +0 -7
  185. package/lib/document/models/user-list.model.d.ts +0 -8
  186. package/lib/document/services/csv-parser.service.d.ts +0 -88
  187. package/lib/document/services/document-actions.service.d.ts +0 -48
  188. package/lib/document/services/document-content-type.service.d.ts +0 -85
  189. package/lib/document/services/document-history-style.service.d.ts +0 -34
  190. package/lib/document/services/document-history.service.d.ts +0 -42
  191. package/lib/document/services/document-http.service.d.ts +0 -179
  192. package/lib/document/services/document-list.service.d.ts +0 -74
  193. package/lib/document/services/document-menu.service.d.ts +0 -122
  194. package/lib/document/services/document-scroll.service.d.ts +0 -55
  195. package/lib/document/services/document-table-builder.service.d.ts +0 -38
  196. package/lib/document/services/document-upload-business.service.d.ts +0 -107
  197. package/lib/document/services/document-upload-data.service.d.ts +0 -40
  198. package/lib/document/services/document-upload-form.service.d.ts +0 -41
  199. package/lib/document/services/document-upload.service.d.ts +0 -99
  200. package/lib/document/services/document-viewer.service.d.ts +0 -97
  201. package/lib/document/services/document-zoom.service.d.ts +0 -81
  202. package/lib/document/services/document.service.d.ts +0 -161
  203. package/lib/document/services/eml-parser.service.d.ts +0 -116
  204. package/lib/document/services/excel-parser.service.d.ts +0 -169
  205. package/lib/document/services/file-format.service.d.ts +0 -34
  206. package/lib/document/services/status-calculator.service.d.ts +0 -20
  207. package/lib/document/services/user-list.service.d.ts +0 -29
  208. package/lib/document/state/document.query.d.ts +0 -243
  209. package/lib/document/state/document.state.d.ts +0 -61
  210. package/lib/document/state/document.store.d.ts +0 -56
@@ -0,0 +1,36 @@
1
+ <div class="grid m-0">
2
+ <div
3
+ class="col-12 flex align-items-center justify-content-between md:col-12 xl:col-12"
4
+ >
5
+ <div
6
+ class="col-5 flex cursor-pointer align-items-center pl-0"
7
+ (click)="handleOpenDocument(document)"
8
+ >
9
+ <img src="../../../../assets/images/Frame.png" alt="" />
10
+ <span class="ml-4 file-name-wrapper document-text-wrapper">{{ document.fileName }}</span>
11
+ </div>
12
+ <div class="col-4 flex align-items-center justify-content-center">
13
+ <span
14
+ [class]="'product-badge status-' + document.status?.toLowerCase()"
15
+ class="flex align-items-center justify-content-center pl-2 pr-2 pt-1 pb-1"
16
+ >
17
+ <ng-container *ngIf="document.status?.toLowerCase() === 'pending'">
18
+ <i class="pi pi-clock pr-1" style="font-size: 12px;"></i>
19
+ Pending
20
+ </ng-container>
21
+ <ng-container *ngIf="document.status?.toLowerCase() === 'verified'">
22
+ <i class="pi pi-check-circle pr-1" style="font-size: 12px;"></i>
23
+ Verified
24
+ </ng-container>
25
+ <ng-container *ngIf="document.status?.toLowerCase() === 'alert'">
26
+ <i class="pi pi-bell pr-1" style="font-size: 12px;"></i>
27
+ Alert
28
+ </ng-container>
29
+ </span>
30
+ </div>
31
+ <div class="document-type file-name-wrapper document-text-wrapper">
32
+ {{document.documentTypeName}}
33
+ </div>
34
+ </div>
35
+ </div>
36
+
@@ -0,0 +1,34 @@
1
+ .product-badge.status-pending {
2
+ background: #e9b127;
3
+ color: #ffffff;
4
+ border-radius: 4px;
5
+ }
6
+ .product-badge.status-verified {
7
+ background: #4caf50;
8
+ color: #ffffff;
9
+ border-radius: 4px;
10
+ }
11
+ .product-badge.status-alert {
12
+ background: #f57c00;
13
+ color: #ffffff;
14
+ border-radius: 4px;
15
+ }
16
+ .product-badge {
17
+ text-transform: none;
18
+ font-weight: 500;
19
+ font-size: 12px;
20
+
21
+ }
22
+
23
+ .file-name-wrapper{
24
+ font-size: 15px;
25
+ font-weight: 500;
26
+ }
27
+
28
+ .document-text-wrapper{
29
+ display: -webkit-box;
30
+ -webkit-line-clamp: 1;
31
+ -webkit-box-orient: vertical;
32
+ overflow: hidden;
33
+ text-overflow: ellipsis;
34
+ }
@@ -0,0 +1,75 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { DocumentListItemComponent } from './document-list-item.component';
3
+ import { CommonModule } from '@angular/common';
4
+ import { By } from '@angular/platform-browser';
5
+ import { DocumentModel } from '../../models/document.model';
6
+
7
+ describe('DocumentListItemComponent', () => {
8
+ let component: DocumentListItemComponent;
9
+ let fixture: ComponentFixture<DocumentListItemComponent>;
10
+
11
+ beforeEach(async () => {
12
+ await TestBed.configureTestingModule({
13
+ declarations: [DocumentListItemComponent],
14
+ imports: [CommonModule],
15
+ }).compileComponents();
16
+
17
+ fixture = TestBed.createComponent(DocumentListItemComponent);
18
+ component = fixture.componentInstance;
19
+ component.document = {
20
+ _id : "1",
21
+ fileName : 'test',
22
+ }
23
+ fixture.detectChanges();
24
+ });
25
+
26
+ it('should create', () => {
27
+ expect(component).toBeTruthy();
28
+ });
29
+
30
+ it('should emit the selected document when handleOpenDocument is called', () => {
31
+ spyOn(component.documentClick, 'emit');
32
+ const mockDocument = { _id: "1", fileName: 'test' } as DocumentModel;
33
+ component.handleOpenDocument(mockDocument);
34
+ expect(component.documentClick.emit).toHaveBeenCalledWith(mockDocument);
35
+ });
36
+
37
+ it('should log an error when handleOpenDocument is called with null', () => {
38
+ spyOn(console, 'error');
39
+ component.handleOpenDocument(null as unknown as DocumentModel);
40
+
41
+ expect(console.error).toHaveBeenCalledWith('Error: Document is null or undefined:', null);
42
+ });
43
+
44
+ it('should emit documentClick event when document is clicked', () => {
45
+ spyOn(component.documentClick, 'emit');
46
+ const clickableElement = fixture.debugElement.query(By.css('.cursor-pointer'));
47
+ clickableElement.triggerEventHandler('click', null);
48
+
49
+ expect(component.documentClick.emit).toHaveBeenCalledWith(component.document);
50
+ });
51
+
52
+ it('should display Pending status with the correct icon', () => {
53
+ component.document.status = 'Pending';
54
+ fixture.detectChanges();
55
+
56
+ const statusElement = fixture.debugElement.query(By.css('.status-pending')).nativeElement;
57
+ const iconElement = fixture.debugElement.query(By.css('.pi-clock')).nativeElement;
58
+
59
+ expect(statusElement.textContent).toContain('Pending');
60
+ expect(iconElement).toBeTruthy();
61
+ });
62
+
63
+ it('should display Verified status with the correct icon', () => {
64
+ component.document.status = 'Verified';
65
+ fixture.detectChanges();
66
+
67
+ const statusElement = fixture.debugElement.query(By.css('.status-verified')).nativeElement;
68
+ const iconElement = fixture.debugElement.query(By.css('.pi-check-circle')).nativeElement;
69
+
70
+ expect(statusElement.textContent).toContain('Verified');
71
+ expect(iconElement).toBeTruthy();
72
+ });
73
+
74
+
75
+ });
@@ -0,0 +1,40 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { DocumentModel } from '../../models/document.model';
3
+
4
+ /**
5
+ * DocumentListItemComponent
6
+ *
7
+ * This component displays individual document items within a list.
8
+ * It accepts a list of documents as input and handles interactions with documents.
9
+ */
10
+ @Component({
11
+ selector: 'lib-document-list-item',
12
+ standalone: false,
13
+ templateUrl: './document-list-item.component.html',
14
+ styleUrls: ['./document-list-item.component.scss']
15
+ })
16
+ export class DocumentListItemComponent {
17
+ /**
18
+ * Emit the selected document.
19
+ * @type {EventEmitter<DocumentModel>}
20
+ */
21
+ @Output() documentClick = new EventEmitter<DocumentModel>();
22
+
23
+ /**
24
+ * The document to display.
25
+ * @type {DocumentModel[]}
26
+ */
27
+ @Input() document!: DocumentModel;
28
+
29
+ /**
30
+ * Handles interactions with a document.
31
+ * @param {DocumentModel} document - The document to be opened or interacted with.
32
+ */
33
+ handleOpenDocument(document: DocumentModel): void {
34
+ if (!document) {
35
+ console.error('Error: Document is null or undefined:', document);
36
+ return;
37
+ }
38
+ this.documentClick.emit(document);
39
+ }
40
+ }
@@ -0,0 +1,64 @@
1
+ <div class="search-container">
2
+ <div class="search-header">
3
+ <h2 class="ml-3 document-heading">Documents</h2>
4
+ </div>
5
+ <div class="search-input-wrapper">
6
+ <i class="pi pi-search search-icon"></i>
7
+ <input
8
+ type="text"
9
+ [(ngModel)]="searchTerm"
10
+ (ngModelChange)="onSearchInputChange($event)"
11
+ class="search-input"
12
+ placeholder="Search by document name, category, type, status or applicant name..."
13
+ [attr.aria-label]="'Search documents'"
14
+ />
15
+ <button
16
+ *ngIf="searchTerm"
17
+ type="button"
18
+ class="clear-button"
19
+ (click)="onClearSearch()"
20
+ [attr.aria-label]="'Clear search'"
21
+ >
22
+ <i class="pi pi-times"></i>
23
+ </button>
24
+ </div>
25
+
26
+ <button
27
+ *ngIf="shouldShowClearAll"
28
+ type="button"
29
+ class="clear-all-filters-link"
30
+ (click)="onClearAllFilters()"
31
+ [attr.aria-label]="'Clear all'"
32
+ >
33
+ Clear All
34
+ <i class="pi pi-times"></i>
35
+ </button>
36
+
37
+ <div class="filters-section">
38
+ <div class="actions-menu">
39
+ <button
40
+ type="button"
41
+ class="actions-btn"
42
+ (click)="toggleActionsMenu()"
43
+ [class.active]="showActionsMenu"
44
+ [attr.aria-label]="'Open actions menu'"
45
+ [attr.aria-expanded]="showActionsMenu"
46
+ >
47
+ Actions
48
+ <i class="pi pi-chevron-down" [class.rotated]="showActionsMenu"></i>
49
+ </button>
50
+
51
+ <!-- Actions Dropdown Menu -->
52
+ <div class="actions-dropdown" *ngIf="showActionsMenu">
53
+ <div class="dropdown-item" (click)="handleUploadDocument()">
54
+ <i class="pi pi-upload"></i>
55
+ <span>Upload Document</span>
56
+ </div>
57
+ <div class="dropdown-item" (click)="handleRequestDocument()">
58
+ <i class="pi pi-file"></i>
59
+ <span>Request Document</span>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
@@ -0,0 +1,206 @@
1
+ .search-container {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 1rem;
5
+ width: 100%;
6
+ justify-content: flex-start;
7
+ padding: 10px;
8
+ }
9
+
10
+ .search-input-wrapper {
11
+ position: relative;
12
+ flex: 1;
13
+ display: flex;
14
+ align-items: center;
15
+ max-width: 50%;
16
+ min-width: 300px;
17
+ }
18
+
19
+ .clear-all-filters-link {
20
+ background: none;
21
+ border: none;
22
+ color: #0F8BFD;
23
+ cursor: pointer;
24
+ padding: 8px 12px;
25
+ border-radius: 4px;
26
+ font-size: 16px;
27
+ font-weight: 500;
28
+ text-decoration: none !important;
29
+ transition: background-color 0.2s ease, color 0.2s ease;
30
+ white-space: nowrap;
31
+ flex-shrink: 0;
32
+ display: flex;
33
+ justify-content: center;
34
+ align-items: center;
35
+ gap: 4px;
36
+ }
37
+
38
+ .filters-section {
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 1rem;
42
+ flex-shrink: 0;
43
+ margin-left: auto;
44
+
45
+ .actions-menu {
46
+ position: relative;
47
+
48
+ .actions-btn {
49
+ background: #0F8BFD;
50
+ border: none;
51
+ border-radius: 8px;
52
+ padding: 8px 10px;
53
+ color: white;
54
+ font-size: 12px;
55
+ font-weight: bold;
56
+ cursor: pointer;
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 0.5rem;
60
+ transition: all 0.2s ease;
61
+ white-space: nowrap;
62
+
63
+ &:hover {
64
+ background: #0d7ae6;
65
+ transform: translateY(-1px);
66
+ }
67
+
68
+ &:active {
69
+ transform: translateY(0);
70
+ }
71
+
72
+ &.active {
73
+ background: #0d7ae6;
74
+ }
75
+
76
+ &:focus {
77
+ outline: none;
78
+ box-shadow: 0 0 0 3px rgba(15, 139, 253, 0.3);
79
+ }
80
+
81
+ i {
82
+ font-size: 0.75rem;
83
+ transition: transform 0.2s;
84
+
85
+ &.rotated {
86
+ transform: rotate(180deg);
87
+ }
88
+ }
89
+ }
90
+
91
+ .actions-dropdown {
92
+ position: absolute;
93
+ top: calc(100% + 0.5rem);
94
+ right: 0;
95
+ background: #ffffff;
96
+ border: 1px solid #d1d5db;
97
+ border-radius: 8px;
98
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
99
+ z-index: 1000;
100
+ min-width: 200px;
101
+ overflow: hidden;
102
+
103
+ .dropdown-item {
104
+ padding: 0.75rem 1rem;
105
+ cursor: pointer;
106
+ color: #374151;
107
+ font-size: 0.875rem;
108
+ transition: background-color 0.2s;
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 0.75rem;
112
+
113
+ i {
114
+ font-size: 1rem;
115
+ color: #6b7280;
116
+ }
117
+
118
+ &:hover {
119
+ background-color: #f3f4f6;
120
+ }
121
+
122
+ &:not(:last-child) {
123
+ border-bottom: 1px solid #f3f4f6;
124
+ }
125
+
126
+ &:active {
127
+ background-color: #e5e7eb;
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+
134
+ .search-icon {
135
+ position: absolute;
136
+ left: 12px;
137
+ color: #6c757d;
138
+ z-index: 1;
139
+ }
140
+
141
+ .search-input {
142
+ width: 100%;
143
+ padding: 12px 40px 12px 40px;
144
+ border: 1px solid #dee2e6;
145
+ border-radius: 8px;
146
+ font-size: 14px;
147
+ outline: none;
148
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
149
+
150
+ &:focus {
151
+ border-color: #0F8BFD;
152
+ box-shadow: 0 0 0 3px rgba(15, 139, 253, 0.1);
153
+ }
154
+
155
+ &::placeholder {
156
+ color: #6c757d;
157
+ }
158
+ }
159
+
160
+ .clear-button {
161
+ position: absolute;
162
+ right: 12px;
163
+ background: none;
164
+ border: none;
165
+ color: #6c757d;
166
+ cursor: pointer;
167
+ padding: 4px;
168
+ border-radius: 4px;
169
+ transition: background-color 0.2s ease, color 0.2s ease;
170
+
171
+ &:hover {
172
+ background-color: #f8f9fa;
173
+ color: #495057;
174
+ }
175
+ }
176
+
177
+ // Responsive Design
178
+ @media (max-width: 768px) {
179
+ .search-container {
180
+ flex-direction: column;
181
+ gap: 0.75rem;
182
+ }
183
+
184
+ .search-input-wrapper {
185
+ max-width: 100%;
186
+ }
187
+
188
+ .filters-section {
189
+ width: 100%;
190
+ justify-content: center;
191
+ gap: 0.5rem;
192
+
193
+ .actions-menu {
194
+ .actions-btn {
195
+ width: auto;
196
+ justify-content: center;
197
+ }
198
+
199
+ .actions-dropdown {
200
+ left: 50%;
201
+ transform: translateX(-50%);
202
+ right: auto;
203
+ }
204
+ }
205
+ }
206
+ }
@@ -0,0 +1,82 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { FormsModule } from '@angular/forms';
3
+ import { DocumentSearchComponent } from './document-search.component';
4
+ import { DocumentHelperService } from '../../services/document.service';
5
+
6
+ describe('DocumentSearchComponent', () => {
7
+ let component: DocumentSearchComponent;
8
+ let fixture: ComponentFixture<DocumentSearchComponent>;
9
+ let mockDocumentHelperService: jasmine.SpyObj<DocumentHelperService>;
10
+
11
+ beforeEach(async () => {
12
+ const spy = jasmine.createSpyObj('DocumentHelperService', ['setSearchKey']);
13
+
14
+ await TestBed.configureTestingModule({
15
+ declarations: [ DocumentSearchComponent ],
16
+ imports: [ FormsModule ],
17
+ providers: [
18
+ { provide: DocumentHelperService, useValue: spy }
19
+ ]
20
+ })
21
+ .compileComponents();
22
+
23
+ mockDocumentHelperService = TestBed.inject(DocumentHelperService) as jasmine.SpyObj<DocumentHelperService>;
24
+ });
25
+
26
+ beforeEach(() => {
27
+ fixture = TestBed.createComponent(DocumentSearchComponent);
28
+ component = fixture.componentInstance;
29
+ fixture.detectChanges();
30
+ });
31
+
32
+ it('should create', () => {
33
+ expect(component).toBeTruthy();
34
+ });
35
+
36
+ it('should initialize with empty search term', () => {
37
+ expect(component.searchTerm).toBe('');
38
+ });
39
+
40
+ it('should call setSearchKey when search term changes', (done) => {
41
+ component.onSearchInputChange('test search');
42
+
43
+ setTimeout(() => {
44
+ expect(mockDocumentHelperService.setSearchKey).toHaveBeenCalledWith('test search');
45
+ done();
46
+ }, 600); // Wait for debounce time
47
+ });
48
+
49
+ it('should clear search when clear button is clicked', () => {
50
+ component.searchTerm = 'test';
51
+ component.onClearSearch();
52
+
53
+ expect(component.searchTerm).toBe('');
54
+ expect(mockDocumentHelperService.setSearchKey).toHaveBeenCalledWith(null);
55
+ });
56
+
57
+ it('should normalize search term by trimming whitespace', (done) => {
58
+ component.onSearchInputChange(' test search ');
59
+
60
+ setTimeout(() => {
61
+ expect(mockDocumentHelperService.setSearchKey).toHaveBeenCalledWith('test search');
62
+ done();
63
+ }, 600);
64
+ });
65
+
66
+ it('should set search key to null for empty search term', (done) => {
67
+ component.onSearchInputChange('');
68
+
69
+ setTimeout(() => {
70
+ expect(mockDocumentHelperService.setSearchKey).toHaveBeenCalledWith(null);
71
+ done();
72
+ }, 600);
73
+ });
74
+
75
+ it('should clear all filters when clear all filters button is clicked', () => {
76
+ component.searchTerm = 'test';
77
+ component.onClearAllFilters();
78
+
79
+ expect(component.searchTerm).toBe('');
80
+ expect(mockDocumentHelperService.clearSelectionState).toHaveBeenCalled();
81
+ });
82
+ });
@@ -0,0 +1,163 @@
1
+ import { Component, Input, OnInit, OnDestroy, Output, EventEmitter } from '@angular/core';
2
+ import { Subject, takeUntil, debounceTime, distinctUntilChanged } from 'rxjs';
3
+ import { SHARED } from '../../../../Shared/constant/SHARED';
4
+ import { DocumentHelperService } from '../../services/document.service';
5
+ import { DocumentQuery } from '../../state/document.query';
6
+
7
+ @Component({
8
+ selector: 'document-search',
9
+ templateUrl: './document-search.component.html',
10
+ styleUrls: ['./document-search.component.scss'],
11
+ standalone: false
12
+ })
13
+ export class DocumentSearchComponent implements OnInit, OnDestroy {
14
+ readonly SHARED = SHARED;
15
+
16
+ @Input() contextId: string = SHARED.EMPTY;
17
+ @Output() onActionClick = new EventEmitter<void>();
18
+ @Output() onRequestClick = new EventEmitter<void>();
19
+
20
+ searchTerm: string = SHARED.EMPTY;
21
+ showActionsMenu: boolean = false;
22
+ private destroy$ = new Subject<void>();
23
+ private searchSubject = new Subject<string>();
24
+ private hasActiveFilters: boolean = false;
25
+
26
+ constructor(
27
+ private documentHelperService: DocumentHelperService,
28
+ private documentQuery: DocumentQuery
29
+ ) {}
30
+
31
+ ngOnInit(): void {
32
+ this.setupSearchSubscription();
33
+ this.setupFilterSubscription();
34
+ this.setupClickOutsideListener();
35
+ }
36
+
37
+ ngOnDestroy(): void {
38
+ this.destroy$.next();
39
+ this.destroy$.complete();
40
+ this.removeClickOutsideListener();
41
+ }
42
+
43
+ /**
44
+ * Sets up the search input subscription with debouncing
45
+ */
46
+ private setupSearchSubscription(): void {
47
+ const searchSubject = new Subject<string>();
48
+ searchSubject.pipe(
49
+ takeUntil(this.destroy$),
50
+ debounceTime(500),
51
+ distinctUntilChanged()
52
+ ).subscribe(searchTerm => {
53
+ this.onSearchChange(searchTerm);
54
+ });
55
+
56
+ this.searchSubject = searchSubject;
57
+ }
58
+
59
+ /**
60
+ * Sets up subscription to monitor all filter states
61
+ */
62
+ private setupFilterSubscription(): void {
63
+ this.documentQuery.selectSelectionState().pipe(
64
+ takeUntil(this.destroy$)
65
+ ).subscribe(selectionState => {
66
+ this.hasActiveFilters = Boolean(
67
+ selectionState.searchKey ||
68
+ selectionState.userId ||
69
+ selectionState.status ||
70
+ selectionState.menuItem
71
+ );
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Handles search term changes from ngModel
77
+ * @param searchTerm - The search term entered by the user
78
+ */
79
+ onSearchInputChange(searchTerm: string): void {
80
+ this.searchSubject.next(searchTerm);
81
+ }
82
+
83
+ /**
84
+ * Handles search term changes
85
+ * @param searchTerm - The search term entered by the user
86
+ */
87
+ private onSearchChange(searchTerm: string): void {
88
+ const normalizedSearchTerm = searchTerm?.trim() || null;
89
+ this.documentHelperService.setSearchKey(normalizedSearchTerm);
90
+ }
91
+
92
+ /**
93
+ * Clears the search input
94
+ */
95
+ onClearSearch(): void {
96
+ this.searchTerm = SHARED.EMPTY;
97
+ this.documentHelperService.setSearchKey(null);
98
+ }
99
+
100
+ /**
101
+ * Clears all filters including search, menu item, user, and status selections
102
+ */
103
+ onClearAllFilters(): void {
104
+ this.searchTerm = SHARED.EMPTY;
105
+ this.documentHelperService.clearSelectionState();
106
+ }
107
+
108
+ /**
109
+ * Determines if the Clear All button should be visible
110
+ */
111
+ get shouldShowClearAll(): boolean {
112
+ return this.hasActiveFilters;
113
+ }
114
+
115
+ /**
116
+ * Toggles the actions dropdown menu
117
+ */
118
+ toggleActionsMenu(): void {
119
+ this.showActionsMenu = !this.showActionsMenu;
120
+ }
121
+
122
+ /**
123
+ * Handles upload document action
124
+ */
125
+ handleUploadDocument(): void {
126
+ this.showActionsMenu = false;
127
+ this.onActionClick.emit();
128
+ }
129
+
130
+ /**
131
+ * Handles request document action
132
+ */
133
+ handleRequestDocument(): void {
134
+ this.showActionsMenu = false;
135
+ this.onRequestClick.emit();
136
+ }
137
+
138
+ /**
139
+ * Sets up click outside listener to close dropdown
140
+ */
141
+ private setupClickOutsideListener(): void {
142
+ document.addEventListener('click', this.handleClickOutside);
143
+ }
144
+
145
+ /**
146
+ * Removes click outside listener
147
+ */
148
+ private removeClickOutsideListener(): void {
149
+ document.removeEventListener('click', this.handleClickOutside);
150
+ }
151
+
152
+ /**
153
+ * Handles clicks outside the dropdown to close it
154
+ */
155
+ private handleClickOutside = (event: MouseEvent): void => {
156
+ const target = event.target as HTMLElement;
157
+ const actionsMenu = target.closest('.actions-menu');
158
+
159
+ if (!actionsMenu && this.showActionsMenu) {
160
+ this.showActionsMenu = false;
161
+ }
162
+ }
163
+ }