cat-documents-ng 1.0.5 → 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 (211) hide show
  1. package/README.md +322 -322
  2. package/ng-package.json +10 -0
  3. package/package.json +5 -11
  4. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.html +3 -0
  5. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.scss +13 -0
  6. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.spec.ts +70 -0
  7. package/src/Shared/components/confirmation-dialog/confirmation-dialog.component.ts +133 -0
  8. package/src/Shared/components/table-primary/table-primary.component.html +66 -0
  9. package/src/Shared/components/table-primary/table-primary.component.scss +227 -0
  10. package/src/Shared/components/table-primary/table-primary.component.spec.ts +23 -0
  11. package/src/Shared/components/table-primary/table-primary.component.ts +143 -0
  12. package/src/Shared/components/table-primary/table-primary.model.ts +21 -0
  13. package/src/Shared/constant/ERROR.ts +55 -0
  14. package/src/Shared/constant/PERMISSIONS.ts +17 -0
  15. package/src/Shared/constant/SHARED.ts +936 -0
  16. package/{Shared/constant/URLS.d.ts → src/Shared/constant/URLS.ts} +31 -25
  17. package/src/Shared/services/app-config.service.spec.ts +19 -0
  18. package/src/Shared/services/app-config.service.ts +73 -0
  19. package/{Shared/services/global-error.handler.d.ts → src/Shared/services/global-error.handler.ts} +11 -9
  20. package/src/Shared/services/session.service.spec.ts +16 -0
  21. package/src/Shared/services/session.service.ts +76 -0
  22. package/src/Shared/shared.module.ts +25 -0
  23. package/src/lib/document/components/csv-viewer/csv-viewer.component.ts +1 -0
  24. package/src/lib/document/components/document-actions/document-actions.component.html +59 -0
  25. package/src/lib/document/components/document-actions/document-actions.component.scss +362 -0
  26. package/src/lib/document/components/document-actions/document-actions.component.spec.ts +297 -0
  27. package/src/lib/document/components/document-actions/document-actions.component.ts +163 -0
  28. package/src/lib/document/components/document-container/document-container.component.html +36 -0
  29. package/src/lib/document/components/document-container/document-container.component.scss +144 -0
  30. package/src/lib/document/components/document-container/document-container.component.spec.ts +110 -0
  31. package/src/lib/document/components/document-container/document-container.component.ts +363 -0
  32. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.html +332 -0
  33. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.scss +1877 -0
  34. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.spec.ts +258 -0
  35. package/src/lib/document/components/document-content-viewer/document-content-viewer.component.ts +664 -0
  36. package/src/lib/document/components/document-history/document-history.component.html +96 -0
  37. package/src/lib/document/components/document-history/document-history.component.scss +392 -0
  38. package/src/lib/document/components/document-history/document-history.component.spec.ts +93 -0
  39. package/src/lib/document/components/document-history/document-history.component.ts +373 -0
  40. package/src/lib/document/components/document-list/document-list.component.html +46 -0
  41. package/src/lib/document/components/document-list/document-list.component.scss +513 -0
  42. package/src/lib/document/components/document-list/document-list.component.spec.ts +486 -0
  43. package/src/lib/document/components/document-list/document-list.component.ts +682 -0
  44. package/src/lib/document/components/document-list-item/document-list-item.component.html +36 -0
  45. package/src/lib/document/components/document-list-item/document-list-item.component.scss +34 -0
  46. package/src/lib/document/components/document-list-item/document-list-item.component.spec.ts +75 -0
  47. package/src/lib/document/components/document-list-item/document-list-item.component.ts +40 -0
  48. package/src/lib/document/components/document-search/document-search.component.html +64 -0
  49. package/src/lib/document/components/document-search/document-search.component.scss +206 -0
  50. package/src/lib/document/components/document-search/document-search.component.spec.ts +82 -0
  51. package/src/lib/document/components/document-search/document-search.component.ts +163 -0
  52. package/src/lib/document/components/document-status/document-status.component.html +31 -0
  53. package/src/lib/document/components/document-status/document-status.component.scss +192 -0
  54. package/src/lib/document/components/document-status/document-status.component.spec.ts +23 -0
  55. package/src/lib/document/components/document-status/document-status.component.ts +87 -0
  56. package/src/lib/document/components/document-upload/document-upload.component.html +160 -0
  57. package/src/lib/document/components/document-upload/document-upload.component.scss +235 -0
  58. package/src/lib/document/components/document-upload/document-upload.component.spec.ts +95 -0
  59. package/src/lib/document/components/document-upload/document-upload.component.ts +668 -0
  60. package/src/lib/document/components/document-viewer/document-viewer.component.html +50 -0
  61. package/src/lib/document/components/document-viewer/document-viewer.component.scss +187 -0
  62. package/src/lib/document/components/document-viewer/document-viewer.component.spec.ts +79 -0
  63. package/src/lib/document/components/document-viewer/document-viewer.component.ts +261 -0
  64. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.html +48 -0
  65. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.scss +320 -0
  66. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.spec.ts +59 -0
  67. package/src/lib/document/components/document-zoom-controls/document-zoom-controls.component.ts +150 -0
  68. package/src/lib/document/components/documents-menu/documents-menu.component.html +44 -0
  69. package/src/lib/document/components/documents-menu/documents-menu.component.scss +363 -0
  70. package/src/lib/document/components/documents-menu/documents-menu.component.spec.ts +23 -0
  71. package/src/lib/document/components/documents-menu/documents-menu.component.ts +316 -0
  72. package/src/lib/document/components/folder-block/folder-block.component.html +46 -0
  73. package/src/lib/document/components/folder-block/folder-block.component.scss +9 -0
  74. package/src/lib/document/components/folder-block/folder-block.component.spec.ts +70 -0
  75. package/{lib/document/components/folder-block/folder-block.component.d.ts → src/lib/document/components/folder-block/folder-block.component.ts} +28 -12
  76. package/src/lib/document/components/folder-container/folder-container.component.html +56 -0
  77. package/src/lib/document/components/folder-container/folder-container.component.scss +20 -0
  78. package/src/lib/document/components/folder-container/folder-container.component.spec.ts +27 -0
  79. package/src/lib/document/components/folder-container/folder-container.component.ts +328 -0
  80. package/src/lib/document/components/linked-document/linked-document.component.html +23 -0
  81. package/src/lib/document/components/linked-document/linked-document.component.scss +10 -0
  82. package/src/lib/document/components/linked-document/linked-document.component.spec.ts +61 -0
  83. package/src/lib/document/components/linked-document/linked-document.component.ts +49 -0
  84. package/src/lib/document/components/request-document/request-document.component.html +86 -0
  85. package/src/lib/document/components/request-document/request-document.component.scss +16 -0
  86. package/src/lib/document/components/request-document/request-document.component.ts +278 -0
  87. package/src/lib/document/components/sidebar/sidebar.component.html +75 -0
  88. package/src/lib/document/components/sidebar/sidebar.component.scss +157 -0
  89. package/src/lib/document/components/sidebar/sidebar.component.spec.ts +114 -0
  90. package/src/lib/document/components/sidebar/sidebar.component.ts +223 -0
  91. package/src/lib/document/components/user-list/user-list.component.html +33 -0
  92. package/src/lib/document/components/user-list/user-list.component.scss +118 -0
  93. package/src/lib/document/components/user-list/user-list.component.spec.ts +23 -0
  94. package/src/lib/document/components/user-list/user-list.component.ts +181 -0
  95. package/src/lib/document/constant/DOCUMENT_HISTORY.ts +52 -0
  96. package/src/lib/document/directives/document.directive.ts +32 -0
  97. package/src/lib/document/directives/permission.directive.spec.ts +0 -0
  98. package/src/lib/document/directives/permission.directive.ts +72 -0
  99. package/src/lib/document/document.module.ts +351 -0
  100. package/{lib/document/models/document-alert.model.d.ts → src/lib/document/models/document-alert.model.ts} +11 -4
  101. package/src/lib/document/models/document-category.model.ts +30 -0
  102. package/src/lib/document/models/document-history.model.ts +109 -0
  103. package/src/lib/document/models/document-list-response.model.ts +37 -0
  104. package/src/lib/document/models/document-type.model.ts +44 -0
  105. package/src/lib/document/models/document.model.ts +53 -0
  106. package/{lib/document/models/folder.model.d.ts → src/lib/document/models/folder.model.ts} +10 -4
  107. package/src/lib/document/models/status-data.model.ts +31 -0
  108. package/src/lib/document/models/uploaded-file-response.model.ts +7 -0
  109. package/src/lib/document/models/user-list.model.ts +10 -0
  110. package/src/lib/document/services/csv-parser.service.spec.ts +97 -0
  111. package/src/lib/document/services/csv-parser.service.ts +303 -0
  112. package/src/lib/document/services/document-actions.service.ts +125 -0
  113. package/src/lib/document/services/document-content-type.service.ts +193 -0
  114. package/src/lib/document/services/document-history-style.service.ts +138 -0
  115. package/src/lib/document/services/document-history.service.ts +129 -0
  116. package/src/lib/document/services/document-http.service.spec.ts +119 -0
  117. package/src/lib/document/services/document-http.service.ts +497 -0
  118. package/src/lib/document/services/document-list.service.ts +195 -0
  119. package/src/lib/document/services/document-menu.service.ts +277 -0
  120. package/src/lib/document/services/document-scroll.service.ts +138 -0
  121. package/src/lib/document/services/document-severity.service.ts +98 -0
  122. package/src/lib/document/services/document-table-builder.service.ts +82 -0
  123. package/src/lib/document/services/document-upload-business.service.ts +326 -0
  124. package/src/lib/document/services/document-upload-data.service.ts +82 -0
  125. package/src/lib/document/services/document-upload-form.service.ts +149 -0
  126. package/src/lib/document/services/document-upload.service.spec.ts +99 -0
  127. package/src/lib/document/services/document-upload.service.ts +209 -0
  128. package/src/lib/document/services/document-viewer.service.ts +279 -0
  129. package/src/lib/document/services/document-zoom.service.spec.ts +56 -0
  130. package/src/lib/document/services/document-zoom.service.ts +164 -0
  131. package/src/lib/document/services/document.service.ts +356 -0
  132. package/src/lib/document/services/eml-parser.service.ts +444 -0
  133. package/src/lib/document/services/excel-parser.service.spec.ts +66 -0
  134. package/src/lib/document/services/excel-parser.service.ts +483 -0
  135. package/src/lib/document/services/file-format.service.spec.ts +16 -0
  136. package/src/lib/document/services/file-format.service.ts +63 -0
  137. package/src/lib/document/services/status-calculator.service.ts +44 -0
  138. package/src/lib/document/services/user-list.service.ts +77 -0
  139. package/src/lib/document/state/document.query.ts +378 -0
  140. package/{lib/document/state/document.service.d.ts → src/lib/document/state/document.service.ts} +46 -15
  141. package/src/lib/document/state/document.state.ts +100 -0
  142. package/src/lib/document/state/document.store.ts +200 -0
  143. package/{public-api.d.ts → src/public-api.ts} +4 -0
  144. package/tsconfig.lib.json +15 -0
  145. package/tsconfig.lib.prod.json +11 -0
  146. package/tsconfig.spec.json +15 -0
  147. package/Shared/components/confirmation-dialog/confirmation-dialog.component.d.ts +0 -44
  148. package/Shared/components/table-primary/table-primary.component.d.ts +0 -31
  149. package/Shared/components/table-primary/table-primary.model.d.ts +0 -19
  150. package/Shared/constant/ERROR.d.ts +0 -52
  151. package/Shared/constant/SHARED.d.ts +0 -546
  152. package/Shared/services/app-config.service.d.ts +0 -51
  153. package/Shared/services/session.service.d.ts +0 -46
  154. package/Shared/shared.module.d.ts +0 -14
  155. package/fesm2022/cat-documents-ng.mjs +0 -11392
  156. package/fesm2022/cat-documents-ng.mjs.map +0 -1
  157. package/index.d.ts +0 -5
  158. package/lib/document/components/document-actions/document-actions.component.d.ts +0 -78
  159. package/lib/document/components/document-container/document-container.component.d.ts +0 -162
  160. package/lib/document/components/document-content-viewer/document-content-viewer.component.d.ts +0 -291
  161. package/lib/document/components/document-history/document-history.component.d.ts +0 -160
  162. package/lib/document/components/document-list/document-list.component.d.ts +0 -299
  163. package/lib/document/components/document-list-item/document-list-item.component.d.ts +0 -28
  164. package/lib/document/components/document-search/document-search.component.d.ts +0 -77
  165. package/lib/document/components/document-status/document-status.component.d.ts +0 -24
  166. package/lib/document/components/document-upload/document-upload.component.d.ts +0 -321
  167. package/lib/document/components/document-viewer/document-viewer.component.d.ts +0 -137
  168. package/lib/document/components/document-zoom-controls/document-zoom-controls.component.d.ts +0 -33
  169. package/lib/document/components/documents-menu/documents-menu.component.d.ts +0 -110
  170. package/lib/document/components/folder-container/folder-container.component.d.ts +0 -162
  171. package/lib/document/components/linked-document/linked-document.component.d.ts +0 -39
  172. package/lib/document/components/request-document/request-document.component.d.ts +0 -69
  173. package/lib/document/components/sidebar/sidebar.component.d.ts +0 -109
  174. package/lib/document/components/user-list/user-list.component.d.ts +0 -34
  175. package/lib/document/constant/DOCUMENT_HISTORY.d.ts +0 -41
  176. package/lib/document/directives/document.directive.d.ts +0 -20
  177. package/lib/document/directives/permission.directive.d.ts +0 -38
  178. package/lib/document/document.module.d.ts +0 -60
  179. package/lib/document/models/document-category.model.d.ts +0 -24
  180. package/lib/document/models/document-history.model.d.ts +0 -94
  181. package/lib/document/models/document-list-response.model.d.ts +0 -33
  182. package/lib/document/models/document-type.model.d.ts +0 -37
  183. package/lib/document/models/document.model.d.ts +0 -44
  184. package/lib/document/models/status-data.model.d.ts +0 -27
  185. package/lib/document/models/uploaded-file-response.model.d.ts +0 -7
  186. package/lib/document/models/user-list.model.d.ts +0 -8
  187. package/lib/document/services/csv-parser.service.d.ts +0 -88
  188. package/lib/document/services/document-actions.service.d.ts +0 -48
  189. package/lib/document/services/document-content-type.service.d.ts +0 -85
  190. package/lib/document/services/document-history-style.service.d.ts +0 -34
  191. package/lib/document/services/document-history.service.d.ts +0 -42
  192. package/lib/document/services/document-http.service.d.ts +0 -179
  193. package/lib/document/services/document-list.service.d.ts +0 -74
  194. package/lib/document/services/document-menu.service.d.ts +0 -122
  195. package/lib/document/services/document-scroll.service.d.ts +0 -55
  196. package/lib/document/services/document-table-builder.service.d.ts +0 -38
  197. package/lib/document/services/document-upload-business.service.d.ts +0 -107
  198. package/lib/document/services/document-upload-data.service.d.ts +0 -40
  199. package/lib/document/services/document-upload-form.service.d.ts +0 -41
  200. package/lib/document/services/document-upload.service.d.ts +0 -99
  201. package/lib/document/services/document-viewer.service.d.ts +0 -97
  202. package/lib/document/services/document-zoom.service.d.ts +0 -81
  203. package/lib/document/services/document.service.d.ts +0 -161
  204. package/lib/document/services/eml-parser.service.d.ts +0 -116
  205. package/lib/document/services/excel-parser.service.d.ts +0 -169
  206. package/lib/document/services/file-format.service.d.ts +0 -34
  207. package/lib/document/services/status-calculator.service.d.ts +0 -20
  208. package/lib/document/services/user-list.service.d.ts +0 -29
  209. package/lib/document/state/document.query.d.ts +0 -243
  210. package/lib/document/state/document.state.d.ts +0 -61
  211. package/lib/document/state/document.store.d.ts +0 -56
@@ -0,0 +1,277 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { DocumentCategory, DocumentCategoryItem } from '../models/document-category.model';
3
+ import { DocumentStore } from '../state/document.store';
4
+ import { DocumentListResponse } from '../models/document-list-response.model';
5
+ import { SHARED } from '../../../Shared/constant/SHARED';
6
+
7
+ @Injectable({
8
+ providedIn: 'root'
9
+ })
10
+ export class DocumentMenuService {
11
+
12
+ constructor(private documentStore: DocumentStore) {}
13
+
14
+ /**
15
+ * Sorts categories alphabetically by label
16
+ * @param categories - The list of document categories to sort
17
+ * @returns Sorted categories array
18
+ */
19
+ sortCategoriesAlphabetically(categories: DocumentCategory[]): DocumentCategory[] {
20
+ return [...categories].sort((a, b) => a.label.localeCompare(b.label));
21
+ }
22
+
23
+ /**
24
+ * Sorts menu items within each category alphabetically by label
25
+ * @param categories - The list of document categories to sort
26
+ * @returns Categories with sorted menu items
27
+ */
28
+ sortMenuItemsAlphabetically(categories: DocumentCategory[]): DocumentCategory[] {
29
+ return categories.map(category => ({
30
+ ...category,
31
+ items: category.items ? [...category.items].sort((a, b) => a.label.localeCompare(b.label)) : category.items
32
+ }));
33
+ }
34
+
35
+ /**
36
+ * Sorts both categories and their menu items alphabetically
37
+ * @param categories - The list of document categories to sort
38
+ * @returns Fully sorted categories array
39
+ */
40
+ sortCategoriesAndMenuItems(categories: DocumentCategory[]): DocumentCategory[] {
41
+ const sortedCategories = this.sortCategoriesAlphabetically(categories);
42
+ return this.sortMenuItemsAlphabetically(sortedCategories);
43
+ }
44
+
45
+ /**
46
+ * Gets the category name for a given menu item _id
47
+ * @param menuItemId - The _id of the menu item
48
+ * @param categories - The list of document categories
49
+ * @returns The category name or null if not found
50
+ */
51
+ getMenuItemCategory(menuItemId: string, categories: DocumentCategory[]): string | null {
52
+ for (const category of categories) {
53
+ if (category.items?.some((menuItem: DocumentCategoryItem) => menuItem._id === menuItemId)) {
54
+ return category.label;
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+
60
+ /**
61
+ * Gets the menu item by its _id
62
+ * @param menuItemId - The _id of the menu item
63
+ * @param categories - The list of document categories
64
+ * @returns The menu item or null if not found
65
+ */
66
+ getMenuItemById(menuItemId: string, categories: DocumentCategory[]): DocumentCategoryItem | null {
67
+ for (const category of categories) {
68
+ if (category.items) {
69
+ const item = category.items.find((menuItem: DocumentCategoryItem) => menuItem._id === menuItemId);
70
+ if (item) {
71
+ return item;
72
+ }
73
+ }
74
+ }
75
+ return null;
76
+ }
77
+
78
+ /**
79
+ * Handles user list visibility based on menu item category
80
+ * @param menuItemId - The _id of the menu item
81
+ * @param categories - The list of document categories
82
+ */
83
+ handleUserListVisibility(menuItemId: string, categories: DocumentCategory[]): void {
84
+ const category = this.getMenuItemCategory(menuItemId, categories);
85
+ this.documentStore.setShowUserList(true);
86
+ }
87
+
88
+ /**
89
+ * Calculates total documents for a menu item
90
+ * @param item - The menu item
91
+ * @returns Total number of documents
92
+ */
93
+ getTotalDocuments(item: DocumentCategoryItem): number {
94
+ const status = item.status;
95
+ // Handle both uppercase and lowercase keys
96
+ const pending = status.Pending || status.pending || 0;
97
+ const reviewing = status.Reviewing || status.reviewing || 0;
98
+ const accepted = status.Accepted || status.approved || 0; // Note: approved maps to Accepted
99
+ const rejected = status.Rejected || status.rejected || 0;
100
+
101
+ return pending + reviewing + accepted + rejected;
102
+ }
103
+
104
+
105
+
106
+ /**
107
+ * Gets badge value for a menu item
108
+ * @param item - The menu item
109
+ * @returns Badge value string (e.g., "2/3")
110
+ */
111
+ getBadgeValue(item: DocumentCategoryItem): string {
112
+ const approved = this.getApprovedDocuments(item);
113
+ const total = this.getTotalDocuments(item);
114
+ return `${approved}/${total}`;
115
+ }
116
+
117
+ /**
118
+ * Gets badge severity based on status
119
+ * @param item - The menu item
120
+ * @returns Badge severity for PrimeNG
121
+ */
122
+ getBadgeSeverity(item: DocumentCategoryItem): 'success' | 'info' | 'warning' | 'danger' {
123
+ const status = item.status;
124
+ const total = this.getTotalDocuments(item);
125
+ const pending = status.Pending || status.pending || 0;
126
+ const rejected = status.Rejected || status.rejected || 0;
127
+ const reviewing = status.Reviewing || status.reviewing || 0;
128
+ const approved = this.getApprovedDocuments(item);
129
+
130
+ if (total === 0) return 'info';
131
+ if (pending > 0) return 'info';
132
+ if (rejected > 0) return 'danger';
133
+ if (reviewing > 0) return 'warning';
134
+ if (approved === total && total > 0) return 'success';
135
+ return 'warning';
136
+ }
137
+
138
+ /**
139
+ * Checks if badge should be shown for a menu item
140
+ * @param item - The menu item
141
+ * @returns True if badge should be shown
142
+ */
143
+ shouldShowBadge(item: DocumentCategoryItem): boolean {
144
+ return this.getTotalDocuments(item) > 0;
145
+ }
146
+
147
+ /**
148
+ * Calculates approved documents for a menu item
149
+ * @param item - The menu item
150
+ * @returns Number of approved documents
151
+ */
152
+ getApprovedDocuments(item: DocumentCategoryItem): number {
153
+ const status = item.status;
154
+ // Handle both uppercase and lowercase keys, with approved mapping to Accepted
155
+ return status.Accepted || status.approved || 0;
156
+ }
157
+
158
+ /**
159
+ * Checks if a menu item's section is visible in the filtered document list
160
+ * @param menuItemId - The ID of the menu item to check
161
+ * @param documentListResponse - The filtered document list response
162
+ * @returns True if the section is visible, false otherwise
163
+ */
164
+ isMenuItemSectionVisible(menuItemId: string, documentListResponse: DocumentListResponse[] | null, menuItemLabel?: string): boolean {
165
+ if (!menuItemId || !documentListResponse || documentListResponse.length === 0) {
166
+ return false;
167
+ }
168
+
169
+ return documentListResponse.some(category => {
170
+ if (!category.label || !category.list || category.list.length === 0) {
171
+ return false;
172
+ }
173
+
174
+ const categoryLabelLower = category.label.toLowerCase();
175
+ if (menuItemLabel) {
176
+ const menuItemLabelLower = menuItemLabel.toLowerCase();
177
+ if (categoryLabelLower === menuItemLabelLower) {
178
+ return true;
179
+ }
180
+ if (this.isSmartPartialMatch(menuItemLabelLower, categoryLabelLower)) {
181
+ return true;
182
+ }
183
+ }
184
+ const menuItemIdLower = menuItemId.toLowerCase();
185
+ if (this.isSmartPartialMatch(menuItemIdLower, categoryLabelLower)) {
186
+ return true;
187
+ }
188
+
189
+ return false;
190
+ });
191
+ }
192
+
193
+ /**
194
+ * Performs smart partial matching to prevent substring conflicts
195
+ * @param menuLabel - The menu item label to match
196
+ * @param categoryLabel - The category label to match against
197
+ * @returns True if it's a valid partial match, false otherwise
198
+ */
199
+ private isSmartPartialMatch(menuLabel: string, categoryLabel: string): boolean {
200
+ // If the category label is significantly longer than menu label, it's likely a different section
201
+ if (categoryLabel.length > menuLabel.length + 3) {
202
+ return false;
203
+ }
204
+ const menuWords = menuLabel.split(/\s+/);
205
+ const categoryWords = categoryLabel.split(/\s+/);
206
+ return menuWords.every(word =>
207
+ categoryWords.some(catWord =>
208
+ catWord.toLowerCase().startsWith(word.toLowerCase()) ||
209
+ word.toLowerCase().startsWith(catWord.toLowerCase())
210
+ )
211
+ );
212
+ }
213
+
214
+
215
+ /**
216
+ * Deselects a menu item if its section is not visible in the filtered document list
217
+ * @param menuItemId - The ID of the menu item to check
218
+ * @param documentListResponse - The filtered document list response
219
+ * @param menuItemLabel - The label of the menu item (optional)
220
+ * @returns True if the menu item was deselected, false otherwise
221
+ */
222
+ deselectMenuItemIfSectionNotVisible(menuItemId: string, documentListResponse: DocumentListResponse[] | null, menuItemLabel?: string): boolean {
223
+ if (!this.isMenuItemSectionVisible(menuItemId, documentListResponse, menuItemLabel)) {
224
+ this.documentStore.setSelectedMenuItem(null);
225
+ return true;
226
+ }
227
+ return false;
228
+ }
229
+
230
+ /**
231
+ * Checks if a menu item should be selectable based on the filtered document list
232
+ * @param menuItemId - The ID of the menu item to check
233
+ * @param documentListResponse - The filtered document list response
234
+ * @param menuItemLabel - The label of the menu item (optional)
235
+ * @returns True if the menu item should be selectable, false otherwise
236
+ */
237
+ isMenuItemSelectable(menuItemId: string, documentListResponse: DocumentListResponse[] | null, menuItemLabel?: string): boolean {
238
+ return this.isMenuItemSectionVisible(menuItemId, documentListResponse, menuItemLabel);
239
+ }
240
+
241
+ /**
242
+ * Gets the selectability status for all menu items in categories
243
+ * @param categories - The document categories containing menu items
244
+ * @param documentListResponse - The filtered document list response
245
+ * @returns Map of menu item IDs to their selectability status
246
+ */
247
+ getMenuItemsSelectabilityStatus(categories: DocumentCategory[], documentListResponse: DocumentListResponse[] | null): Map<string, boolean> {
248
+ const selectabilityMap = new Map<string, boolean>();
249
+
250
+ categories.forEach(category => {
251
+ if (category.items) {
252
+ category.items.forEach(item => {
253
+ const isSelectable = this.isMenuItemSelectable(item._id, documentListResponse);
254
+ selectabilityMap.set(item._id, isSelectable);
255
+ });
256
+ }
257
+ });
258
+
259
+ return selectabilityMap;
260
+ }
261
+
262
+ /**
263
+ * Updates menu items with selectability status
264
+ * @param categories - The document categories containing menu items
265
+ * @param documentListResponse - The filtered document list response
266
+ * @returns Updated categories with selectability information
267
+ */
268
+ updateMenuItemsWithSelectabilityStatus(categories: DocumentCategory[], documentListResponse: DocumentListResponse[] | null): DocumentCategory[] {
269
+ return categories.map(category => ({
270
+ ...category,
271
+ items: category.items?.map(item => ({
272
+ ...item,
273
+ isSelectable: this.isMenuItemSelectable(item._id, documentListResponse, item.label)
274
+ }))
275
+ }));
276
+ }
277
+ }
@@ -0,0 +1,138 @@
1
+ import { Injectable, OnDestroy } from '@angular/core';
2
+ import { DocumentStore } from '../state/document.store';
3
+
4
+ export interface ScrollTarget {
5
+ element: Element;
6
+ menuItemId: string;
7
+ }
8
+
9
+ @Injectable({
10
+ providedIn: 'root'
11
+ })
12
+ export class DocumentScrollService implements OnDestroy {
13
+ private sectionObserver: IntersectionObserver | null = null;
14
+ private currentObservedSection: Element | null = null;
15
+ private isScrolling: boolean = false;
16
+ private scrollHandler: (() => void) | null = null;
17
+ private scrollTimeout: any = null;
18
+
19
+ constructor(private documentStore: DocumentStore) {}
20
+
21
+ /**
22
+ * Sets up scroll event listeners to track scrolling state
23
+ * @param containerElement - The container element to monitor for scroll events
24
+ */
25
+ setupScrollListeners(containerElement: HTMLElement): void {
26
+ if (containerElement) {
27
+ this.scrollHandler = () => {
28
+ this.isScrolling = true;
29
+ if (this.scrollTimeout) {
30
+ clearTimeout(this.scrollTimeout);
31
+ }
32
+ this.scrollTimeout = setTimeout(() => {
33
+ this.isScrolling = false;
34
+ }, 150);
35
+ };
36
+
37
+ containerElement.addEventListener('scroll', this.scrollHandler);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Sets up intersection observer to detect when the selected section scrolls out of view
43
+ * @param sectionElement - The section element to observe
44
+ * @param menuItemId - The ID of the selected menu item
45
+ */
46
+ setupSectionObserver(sectionElement: Element, menuItemId: string): void {
47
+ this.disconnectSectionObserver();
48
+
49
+ setTimeout(() => {
50
+ if (!menuItemId || this.isScrolling) {
51
+ return;
52
+ }
53
+
54
+ this.sectionObserver = new IntersectionObserver(
55
+ (entries) => {
56
+ entries.forEach(entry => {
57
+ if (entry.intersectionRatio === 0 ) {
58
+ setTimeout(() => {
59
+ if (this.sectionObserver && menuItemId && entry.intersectionRatio === 0) {
60
+ this.documentStore.setSelectedMenuItem(null);
61
+ this.disconnectSectionObserver();
62
+ }
63
+ }, 200);
64
+ }
65
+ });
66
+ },
67
+ {
68
+ threshold: [0, 0.1, 0.5, 1],
69
+ rootMargin: '0px'
70
+ }
71
+ );
72
+
73
+ // Always start observing regardless of current visibility
74
+ // The IntersectionObserver will handle visibility changes automatically
75
+ this.sectionObserver.observe(sectionElement);
76
+ this.currentObservedSection = sectionElement;
77
+ }, 1200);
78
+ }
79
+
80
+ /**
81
+ * Disconnects the section observer
82
+ */
83
+ disconnectSectionObserver(): void {
84
+ if (this.sectionObserver) {
85
+ this.sectionObserver.disconnect();
86
+ this.sectionObserver = null;
87
+ this.currentObservedSection = null;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Sets the scrolling flag to true (called when starting a scroll operation)
93
+ */
94
+ setScrolling(): void {
95
+ this.isScrolling = true;
96
+ }
97
+
98
+ /**
99
+ * Resets the scrolling flag after a specified delay
100
+ * @param delay - Delay in milliseconds before resetting the flag
101
+ */
102
+ resetScrollingAfterDelay(delay: number = 1200): void {
103
+ setTimeout(() => {
104
+ this.isScrolling = false;
105
+ }, delay);
106
+ }
107
+
108
+ /**
109
+ * Gets the current scrolling state
110
+ */
111
+ get isCurrentlyScrolling(): boolean {
112
+ return this.isScrolling;
113
+ }
114
+
115
+ /**
116
+ * Cleans up all resources
117
+ */
118
+ ngOnDestroy(): void {
119
+ this.disconnectSectionObserver();
120
+ this.cleanupScrollListeners();
121
+ }
122
+
123
+ /**
124
+ * Removes scroll event listeners
125
+ * @param containerElement - The container element to remove listeners from
126
+ */
127
+ cleanupScrollListeners(containerElement?: HTMLElement): void {
128
+ if (containerElement && this.scrollHandler) {
129
+ containerElement.removeEventListener('scroll', this.scrollHandler);
130
+ this.scrollHandler = null;
131
+ }
132
+
133
+ if (this.scrollTimeout) {
134
+ clearTimeout(this.scrollTimeout);
135
+ this.scrollTimeout = null;
136
+ }
137
+ }
138
+ }
@@ -0,0 +1,98 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { SHARED } from '../../../Shared/constant/SHARED';
3
+ import { DocumentListItem } from '../models/document-list-response.model';
4
+
5
+ export type SeverityLevel = 'success' | 'info' | 'warning' | 'danger';
6
+
7
+ @Injectable({
8
+ providedIn: 'root'
9
+ })
10
+ export class DocumentSeverityService {
11
+
12
+ constructor() {}
13
+
14
+ /**
15
+ * Calculate severity for a list of documents based on their statuses
16
+ * This is the centralized severity calculation logic used across the application
17
+ * @param documents The list of documents to calculate severity for
18
+ * @returns Severity level for the document list
19
+ */
20
+ calculateSeverity(documents: DocumentListItem[]): SeverityLevel {
21
+ if (!documents || documents.length === 0) {
22
+ return 'info';
23
+ }
24
+
25
+ const total = documents.length;
26
+ const pending = documents.filter(doc =>
27
+ doc.status.toLowerCase() === SHARED.PENDING_STATUS
28
+ ).length;
29
+ const rejected = documents.filter(doc =>
30
+ doc.status.toLowerCase() === SHARED.REJECTED_STATUS
31
+ ).length;
32
+ const reviewing = documents.filter(doc =>
33
+ doc.status.toLowerCase() === SHARED.REVIEWING_STATUS
34
+ ).length;
35
+ const approved = documents.filter(doc =>
36
+ doc.status.toLowerCase() === SHARED.APPROVED_STATUS ||
37
+ doc.status.toLowerCase() === SHARED.UPLOADED_STATUS
38
+ ).length;
39
+
40
+ // Severity calculation logic:
41
+ // - info (grey): No documents or has pending documents
42
+ // - danger (red): Has rejected documents
43
+ // - warning (orange): Has documents under review or mixed status
44
+ // - success (green): All documents are approved
45
+ if (total === 0) return 'info';
46
+ if (pending > 0) return 'info';
47
+ if (rejected > 0) return 'danger';
48
+ if (reviewing > 0) return 'warning';
49
+ if (approved === total && total > 0) return 'success';
50
+ return 'warning';
51
+ }
52
+
53
+ /**
54
+ * Calculate severity for a category based on document statuses
55
+ * @param category The document category
56
+ * @returns Severity level for the category
57
+ */
58
+ calculateCategorySeverity(category: any): SeverityLevel {
59
+ if (!category.list || category.list.length === 0) {
60
+ return 'info';
61
+ }
62
+ return this.calculateSeverity(category.list);
63
+ }
64
+
65
+ /**
66
+ * Calculate severity for a menu item based on status counts
67
+ * @param status The status object with counts
68
+ * @returns Severity level for the menu item
69
+ */
70
+ calculateMenuItemSeverity(status: any): SeverityLevel {
71
+ const total = this.getTotalFromStatus(status);
72
+ const pending = status.Pending || status.pending || 0;
73
+ const rejected = status.Rejected || status.rejected || 0;
74
+ const reviewing = status.Reviewing || status.reviewing || 0;
75
+ const approved = status.Accepted || status.approved || 0;
76
+
77
+ if (total === 0) return 'info';
78
+ if (pending > 0) return 'info';
79
+ if (rejected > 0) return 'danger';
80
+ if (reviewing > 0) return 'warning';
81
+ if (approved === total && total > 0) return 'success';
82
+ return 'warning';
83
+ }
84
+
85
+ /**
86
+ * Helper method to get total count from status object
87
+ * @param status The status object
88
+ * @returns Total count
89
+ */
90
+ private getTotalFromStatus(status: any): number {
91
+ const pending = status.Pending || status.pending || 0;
92
+ const reviewing = status.Reviewing || status.reviewing || 0;
93
+ const accepted = status.Accepted || status.approved || 0;
94
+ const rejected = status.Rejected || status.rejected || 0;
95
+
96
+ return pending + reviewing + accepted + rejected;
97
+ }
98
+ }
@@ -0,0 +1,82 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { DocumentListResponse, DocumentListItem } from '../models/document-list-response.model';
3
+ import { SHARED } from '../../../Shared/constant/SHARED';
4
+ import { TableData } from '../../../Shared/components/table-primary/table-primary.model';
5
+
6
+ @Injectable({
7
+ providedIn: 'root'
8
+ })
9
+ export class DocumentTableBuilderService {
10
+
11
+ constructor() { }
12
+
13
+ /**
14
+ * Builds a single table from document list items
15
+ * @param documents Array of document list items
16
+ * @returns TableData object
17
+ */
18
+ buildDocumentTable(documents: DocumentListItem[]): TableData {
19
+ const columns = SHARED.DOCUMENT_TABLE_COLUMNS.filter(col => col.type !== SHARED.ACTIONS);
20
+
21
+ return {
22
+ columns: columns,
23
+ data: documents
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Gets completion count for a category
29
+ * @param category Document category
30
+ * @returns Completion string (e.g., "2/4")
31
+ */
32
+ getCompletionCount(category: DocumentListResponse): string {
33
+ const total = category.list.length;
34
+ const completed = category.list.filter(doc =>
35
+ doc.status.toLowerCase() === SHARED.APPROVED ||
36
+ doc.status.toLowerCase() === SHARED.UPLOADED
37
+ ).length;
38
+ return `${completed}/${total}`;
39
+ }
40
+
41
+ /**
42
+ * Gets pending document count for a category
43
+ * @param category Document category
44
+ * @returns Number of pending documents
45
+ */
46
+ getPendingDocumentCount(category: DocumentListResponse): number {
47
+ return category.totalDocs - category.acceptedDocs;
48
+ }
49
+
50
+ /**
51
+ * Gets approved document count for a category
52
+ * @param category Document category
53
+ * @returns Number of approved documents
54
+ */
55
+ getApprovedDocumentCount(category: DocumentListResponse): number {
56
+ return category.acceptedDocs;
57
+ }
58
+
59
+ /**
60
+ * Transforms document model to document list item
61
+ * @param documents Array of DocumentModel
62
+ * @returns Array of DocumentListItem
63
+ */
64
+ transformDocumentModelToListItem(documents: any[]): DocumentListItem[] {
65
+ return documents.map(doc => {
66
+ return {
67
+ _id: doc._id || SHARED.EMPTY,
68
+ fileName: doc.fileName || SHARED.EMPTY,
69
+ docName: doc.docName || doc.documentName || SHARED.EMPTY,
70
+ fileSize: doc.fileSize || SHARED.EMPTY,
71
+ documentUrl: doc.documentUrl || doc.url || SHARED.EMPTY,
72
+ status: doc.status || SHARED.PENDING,
73
+ uploadedOn: doc.uploadedOn || doc.uploadDate || SHARED.EMPTY,
74
+ ownerName: doc.ownerName || doc.applicantName || SHARED.EMPTY,
75
+ contentType: doc.contentType || SHARED.EMPTY,
76
+ isUploaded: doc.isUploaded || false,
77
+ documentType: doc.documentType || SHARED.EMPTY,
78
+ aliasName: doc.aliasName || SHARED.EMPTY
79
+ };
80
+ });
81
+ }
82
+ }