@unifylib/ui-lib 1.0.3 → 1.1.3

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 (155) hide show
  1. package/ng-package.json +7 -7
  2. package/package.json +14 -12
  3. package/src/lib/base-model/SearchStrConfig.ts +12 -12
  4. package/src/lib/base-model/api-response.ts +23 -23
  5. package/src/lib/base-model/audit-log-entry.ts +7 -7
  6. package/src/lib/base-model/button-action-settings.ts +29 -25
  7. package/src/lib/base-model/column-def.model.ts +34 -34
  8. package/src/lib/base-model/do-action-request.ts +11 -11
  9. package/src/lib/base-model/feature-item.ts +9 -0
  10. package/src/lib/base-model/field-action.ts +7 -7
  11. package/src/lib/base-model/field-filter.model.ts +7 -14
  12. package/src/lib/base-model/field-info.ts +102 -98
  13. package/src/lib/base-model/field-predicate.model.ts +7 -7
  14. package/src/lib/base-model/filter-request.ts +27 -27
  15. package/src/lib/base-model/filter.model.ts +49 -49
  16. package/src/lib/base-model/get-items-list.ts +24 -24
  17. package/src/lib/base-model/index.ts +11 -11
  18. package/src/lib/base-model/items-total.model.ts +12 -0
  19. package/src/lib/base-model/line-item.model.ts +18 -0
  20. package/src/lib/base-model/lookupItem.ts +21 -21
  21. package/src/lib/base-model/null-snackmessage.ts +9 -9
  22. package/src/lib/base-model/page-info.ts +54 -51
  23. package/src/lib/base-model/report-request.model.ts +33 -33
  24. package/src/lib/base-model/response-envelop.model.ts +15 -15
  25. package/src/lib/base-model/snack-message.model.ts +14 -14
  26. package/src/lib/base-model/snackmessage-interface.ts +7 -7
  27. package/src/lib/base-model/table-column.interface.ts +29 -29
  28. package/src/lib/base-model/table-page-user-action.interface.ts +33 -33
  29. package/src/lib/base-model/workflow/workflow-steps.model.ts +9 -9
  30. package/src/lib/base-model/workflow/workflow.model.ts +52 -52
  31. package/src/lib/components/action-comment/action-comment.component.css +52 -0
  32. package/src/lib/components/action-comment/action-comment.component.html +47 -0
  33. package/src/lib/components/{rejection-comment → action-comment}/action-comment.component.spec.ts +23 -23
  34. package/src/lib/components/{rejection-comment → action-comment}/action-comment.component.ts +102 -86
  35. package/src/lib/components/action-confirmation/action-confirmation.component.css +46 -34
  36. package/src/lib/components/action-confirmation/action-confirmation.component.html +32 -18
  37. package/src/lib/components/action-confirmation/action-confirmation.component.spec.ts +23 -23
  38. package/src/lib/components/action-confirmation/action-confirmation.component.ts +58 -58
  39. package/src/lib/components/activity-report-form/activity-report-form.component.html +110 -109
  40. package/src/lib/components/activity-report-form/activity-report-form.component.scss +69 -0
  41. package/src/lib/components/activity-report-form/activity-report-form.component.spec.ts +25 -25
  42. package/src/lib/components/activity-report-form/activity-report-form.component.ts +616 -605
  43. package/src/lib/components/advanced-filter/field-filter/field-filter.component.html +8 -0
  44. package/src/lib/components/advanced-filter/field-filter/field-filter.component.scss +0 -0
  45. package/src/lib/components/advanced-filter/field-filter/field-filter.component.spec.ts +25 -0
  46. package/src/lib/components/advanced-filter/field-filter/field-filter.component.ts +55 -0
  47. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.html +36 -0
  48. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.scss +130 -0
  49. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.spec.ts +25 -0
  50. package/src/lib/components/advanced-filter/filter-builder/filter-builder.component.ts +186 -0
  51. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.css +51 -51
  52. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.html +23 -23
  53. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.spec.ts +23 -23
  54. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.ts +69 -69
  55. package/src/lib/components/audit-log-list/audit-log.component.html +26 -23
  56. package/src/lib/components/audit-log-list/audit-log.component.scss +50 -0
  57. package/src/lib/components/audit-log-list/audit-log.component.spec.ts +25 -25
  58. package/src/lib/components/audit-log-list/audit-log.component.ts +114 -116
  59. package/src/lib/components/auto-complete/auto-complete.component.css +55 -14
  60. package/src/lib/components/auto-complete/auto-complete.component.html +45 -29
  61. package/src/lib/components/auto-complete/auto-complete.component.spec.ts +23 -23
  62. package/src/lib/components/auto-complete/auto-complete.component.ts +331 -330
  63. package/src/lib/components/base-form/base-form.component.html +59 -58
  64. package/src/lib/components/base-form/base-form.component.scss +68 -0
  65. package/src/lib/components/base-form/base-form.component.spec.ts +25 -25
  66. package/src/lib/components/base-form/base-form.component.ts +323 -305
  67. package/src/lib/components/base-form-canvas/base-form-canvas.component.css +196 -22
  68. package/src/lib/components/base-form-canvas/base-form-canvas.component.html +1095 -1006
  69. package/src/lib/components/base-form-canvas/base-form-canvas.component.spec.ts +23 -23
  70. package/src/lib/components/base-form-canvas/base-form-canvas.component.ts +680 -573
  71. package/src/lib/components/base-input-dialog/base-input-dialog.component.css +67 -0
  72. package/src/lib/components/base-input-dialog/base-input-dialog.component.html +47 -42
  73. package/src/lib/components/base-input-dialog/base-input-dialog.component.spec.ts +23 -23
  74. package/src/lib/components/base-input-dialog/base-input-dialog.component.ts +77 -78
  75. package/src/lib/components/base-table/base-table.component.html +268 -242
  76. package/src/lib/components/base-table/base-table.component.scss +140 -31
  77. package/src/lib/components/base-table/base-table.component.spec.ts +25 -25
  78. package/src/lib/components/base-table/base-table.component.ts +621 -568
  79. package/src/lib/components/button-actions/button-actions.component.html +27 -28
  80. package/src/lib/components/button-actions/button-actions.component.scss +101 -6
  81. package/src/lib/components/button-actions/button-actions.component.spec.ts +23 -23
  82. package/src/lib/components/button-actions/button-actions.component.ts +70 -72
  83. package/src/lib/components/editable-base-table/editable-base-table.component.html +337 -372
  84. package/src/lib/components/editable-base-table/editable-base-table.component.scss +126 -44
  85. package/src/lib/components/editable-base-table/editable-base-table.component.spec.ts +25 -25
  86. package/src/lib/components/editable-base-table/editable-base-table.component.ts +579 -570
  87. package/src/lib/components/equation-builder/equation-builder.component.css +39 -0
  88. package/src/lib/components/equation-builder/equation-builder.component.html +31 -31
  89. package/src/lib/components/equation-builder/equation-builder.component.spec.ts +23 -23
  90. package/src/lib/components/equation-builder/equation-builder.component.ts +119 -121
  91. package/src/lib/components/item-line-editor/item-line-editor.component.html +102 -0
  92. package/src/lib/components/item-line-editor/item-line-editor.component.scss +152 -0
  93. package/src/lib/components/item-line-editor/item-line-editor.component.spec.ts +23 -0
  94. package/src/lib/components/item-line-editor/item-line-editor.component.ts +306 -0
  95. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.css +19 -11
  96. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.html +38 -38
  97. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.spec.ts +23 -23
  98. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.ts +315 -317
  99. package/src/lib/components/paginator/paginator.component.css +65 -25
  100. package/src/lib/components/paginator/paginator.component.html +30 -34
  101. package/src/lib/components/paginator/paginator.component.ts +87 -94
  102. package/src/lib/components/report-details-dialog/report-details-dialog.component.css +17 -17
  103. package/src/lib/components/report-details-dialog/report-details-dialog.component.html +16 -16
  104. package/src/lib/components/report-details-dialog/report-details-dialog.component.spec.ts +23 -23
  105. package/src/lib/components/report-details-dialog/report-details-dialog.component.ts +111 -113
  106. package/src/lib/components/report-form/report-form.component.html +92 -94
  107. package/src/lib/components/report-form/report-form.component.scss +51 -0
  108. package/src/lib/components/report-form/report-form.component.spec.ts +25 -25
  109. package/src/lib/components/report-form/report-form.component.ts +599 -588
  110. package/src/lib/components/search-bar/search-bar.component.html +51 -62
  111. package/src/lib/components/search-bar/search-bar.component.scss +63 -8
  112. package/src/lib/components/search-bar/search-bar.component.spec.ts +25 -25
  113. package/src/lib/components/search-bar/search-bar.component.ts +68 -70
  114. package/src/lib/components/section-form-canvas/section-form-canvas.component.html +43 -0
  115. package/src/lib/components/section-form-canvas/section-form-canvas.component.scss +81 -0
  116. package/src/lib/components/section-form-canvas/section-form-canvas.component.spec.ts +23 -0
  117. package/src/lib/components/section-form-canvas/section-form-canvas.component.ts +67 -0
  118. package/src/lib/components/shared/action-button/action-button.component.html +12 -0
  119. package/src/lib/components/shared/action-button/action-button.component.scss +45 -0
  120. package/src/lib/components/shared/action-button/action-button.component.ts +51 -0
  121. package/src/lib/components/shared/action-card/action-card.component.html +78 -0
  122. package/src/lib/components/shared/action-card/action-card.component.scss +238 -0
  123. package/src/lib/components/shared/action-card/action-card.component.ts +56 -0
  124. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.css +135 -54
  125. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.html +36 -22
  126. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.spec.ts +23 -23
  127. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.ts +71 -45
  128. package/src/lib/components/shared-list/shared-list.component.html +17 -17
  129. package/src/lib/components/shared-list/shared-list.component.spec.ts +23 -23
  130. package/src/lib/components/shared-list/shared-list.component.ts +53 -53
  131. package/src/lib/components/snackbar-static/snackbar-static.component.html +20 -0
  132. package/src/lib/components/snackbar-static/snackbar-static.component.scss +135 -0
  133. package/src/lib/components/snackbar-static/snackbar-static.component.ts +26 -0
  134. package/src/lib/components/title-bar/title-bar.component.html +35 -31
  135. package/src/lib/components/title-bar/title-bar.component.scss +126 -23
  136. package/src/lib/components/title-bar/title-bar.component.spec.ts +23 -23
  137. package/src/lib/components/title-bar/title-bar.component.ts +126 -119
  138. package/src/lib/services/backend-service.ts +287 -286
  139. package/src/lib/services/index.ts +3 -3
  140. package/src/lib/services/top-panel.ts +17 -17
  141. package/src/lib/services/trigger-form.service.ts +11 -11
  142. package/src/lib/share-module/shared-module.ts +10 -10
  143. package/src/lib/utils/base-utils.ts +102 -102
  144. package/src/lib/validators/date-range-validator.ts +31 -31
  145. package/src/lib/validators/index.ts +3 -3
  146. package/src/lib/validators/match-list.validator.ts +10 -10
  147. package/src/lib/validators/multi-email-validator.ts +15 -15
  148. package/src/public-api.ts +29 -21
  149. package/tsconfig.lib.json +15 -15
  150. package/tsconfig.lib.prod.json +11 -11
  151. package/tsconfig.spec.json +15 -15
  152. package/src/lib/components/rejection-comment/action-comment.component.css +0 -33
  153. package/src/lib/components/rejection-comment/action-comment.component.html +0 -46
  154. package/src/lib/styles/invoiceq-theme.scss +0 -252
  155. package/src/lib/styles/styles.scss +0 -1723
@@ -1,570 +1,579 @@
1
- import {
2
- Component,
3
- ElementRef,
4
- EventEmitter,
5
- Input,
6
- OnChanges,
7
- OnInit,
8
- Output,
9
- SimpleChanges,
10
- ViewChild
11
- } from "@angular/core";
12
- import {
13
- MatCell,
14
- MatCellDef,
15
- MatColumnDef,
16
- MatHeaderCell,
17
- MatHeaderCellDef,
18
- MatHeaderRow,
19
- MatHeaderRowDef,
20
- MatRow,
21
- MatRowDef,
22
- MatTable
23
- } from "@angular/material/table";
24
- import {TranslateModule} from "@ngx-translate/core";
25
- import {MatSortModule} from "@angular/material/sort";
26
- import {NgClass, NgForOf, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault} from "@angular/common";
27
- import {MatIcon} from "@angular/material/icon";
28
- import {MatButton, MatButtonModule} from "@angular/material/button";
29
- import {NgxPaginationModule} from "ngx-pagination";
30
- import {FlexLayoutModule} from "@angular/flex-layout";
31
- import {Router} from "@angular/router";
32
- import {AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";
33
- import {MatError, MatFormField, MatInput, MatLabel, MatSuffix} from "@angular/material/input";
34
- import {BackendService} from "../../services";
35
- import {
36
- BaseUtils,
37
- buildFormFields,
38
- getNegativeWfActionKey,
39
- getPositiveWfActionKey,
40
- getWfActionId
41
- } from "../../utils/base-utils";
42
- import {
43
- EMPTY_PAGE_INFO,
44
- FieldInfo,
45
- Filter,
46
- FilterRequest,
47
- LookupItem,
48
- PageInfo,
49
- SELECT_RECORD_ACTION,
50
- SnackMessage,
51
- TableColumn
52
- } from "../../base-model";
53
- import {DoActionRequest, REJECT, SAVE} from "../../base-model/do-action-request";
54
- import {ActionCommentComponent} from "../rejection-comment/action-comment.component";
55
- import {MatDialog} from "@angular/material/dialog";
56
- import {MatDatepicker, MatDatepickerInput, MatDatepickerToggle} from "@angular/material/datepicker";
57
- import moment, {Moment} from 'moment';
58
- import {AutoCompleteComponent} from "../auto-complete/auto-complete.component";
59
- import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatOption} from "@angular/material/core";
60
- import {MatChipListbox, MatChipOption} from "@angular/material/chips";
61
- import {TitleBarComponent} from "../title-bar/title-bar.component";
62
- import {PaginatorComponent} from "../paginator/paginator.component";
63
- import {Directionality} from "@angular/cdk/bidi";
64
- import {AttachmentUploaderComponent} from "../shared/attachment-uploader/attachment-uploader.component";
65
- import {EquationBuilderComponent} from "../equation-builder/equation-builder.component";
66
- import {MatSelect} from "@angular/material/select";
67
-
68
- import {BaseFormCanvasComponent} from "../base-form-canvas/base-form-canvas.component";
69
- import {MatCheckbox} from "@angular/material/checkbox";
70
- @Component({
71
- selector: 'app-editable-base-table',
72
- standalone: true,
73
- templateUrl: './editable-base-table.component.html',
74
- styleUrls: ['./editable-base-table.component.scss'],
75
- animations: [],
76
- imports: [
77
- NgClass,
78
- TranslateModule,
79
- MatIcon,
80
- MatSortModule,
81
- MatColumnDef,
82
- MatHeaderCellDef,
83
- NgIf,
84
- MatTable,
85
- MatHeaderCell,
86
- NgSwitch,
87
- MatButtonModule,
88
- MatCell,
89
- MatCellDef,
90
- NgxPaginationModule,
91
- MatRow,
92
- MatRowDef,
93
- MatHeaderRow,
94
- NgSwitchCase,
95
- NgSwitchDefault,
96
- MatHeaderRowDef,
97
- NgForOf,
98
- FlexLayoutModule,
99
- MatButton,
100
- ReactiveFormsModule,
101
- MatInput,
102
- AutoCompleteComponent,
103
- MatFormField,
104
- MatDatepicker,
105
- MatDatepickerInput,
106
- MatDatepickerToggle,
107
- MatLabel,
108
- MatSuffix,
109
- MatChipListbox,
110
- MatChipOption,
111
- TitleBarComponent,
112
- PaginatorComponent,
113
- AttachmentUploaderComponent,
114
- EquationBuilderComponent,
115
- MatSelect,
116
- MatOption,
117
- BaseFormCanvasComponent,
118
- MatCheckbox,
119
- ],
120
- providers: [
121
- // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
122
- // application's root module. We provide it at the component level here, due to limitations of
123
- // our example generation script.
124
- // {
125
- // provide: DateAdapter,
126
- // useClass: MomentDateAdapter,
127
- // deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
128
- // },
129
-
130
- // { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
131
- ],
132
- })
133
-
134
- export class EditableBaseTableComponent extends BaseUtils implements OnInit, OnChanges {
135
-
136
- collection = {count: 60, data: []};
137
- config = {
138
- itemsPerPage: 10,
139
- currentPage: 1,
140
- totalItems: this.collection.count
141
- };
142
- public maxSize: number = 7;
143
- public directionLinks: boolean = true;
144
- public autoHide: boolean = false;
145
- public responsive: boolean = true;
146
- public labels: any = {
147
- previousLabel: '<',
148
- nextLabel: '>',
149
- screenReaderPaginationLabel: 'Pagination',
150
- screenReaderPageLabel: 'page',
151
- screenReaderCurrentLabel: `You're on page`
152
- };
153
-
154
- private timer: any;
155
- dataElements: any[] = [];
156
- noDataFound = false;
157
- isLoaded: boolean = false;
158
- totalElements = 0;
159
- pagesCount = 0;
160
- pageIndex = 0;
161
- formParam: FormGroup;
162
- searchForm: FormGroup;
163
-
164
- @Input()
165
- filterRequest: FilterRequest;
166
-
167
- @Input()
168
- superDataElements: any[];
169
-
170
- @Input()
171
- override pageInfo: PageInfo = EMPTY_PAGE_INFO;
172
-
173
- @Input() //@ts-ignore
174
- enforceRefresh: boolean = false;
175
-
176
- @Input()
177
- isPending: boolean = false;
178
-
179
- @Input()
180
- isBulkItemsSupported: boolean = false;
181
-
182
- @Input()// @ts-ignore
183
- public fields: FieldInfo[] = [];
184
-
185
- @Input()// @ts-ignore
186
- public searchFormFields: FieldInfo[] = [];
187
-
188
- @Input() translationKey: string = 'addNew';
189
-
190
- @Output()
191
- formUpdated: EventEmitter<FormGroup> = new EventEmitter<FormGroup>();
192
-
193
- @Output()
194
- saveActionEmitter: EventEmitter<any> = new EventEmitter<any>();
195
- @Output()
196
- saveAttachmentEmitter: EventEmitter<any> = new EventEmitter<any>();
197
-
198
- @Input() actionRequestCallback!: (actionRequest: DoActionRequest) => DoActionRequest;
199
-
200
- @ViewChild('uploader') uploaderComponent!: AttachmentUploaderComponent;
201
-
202
- currentDirection: 'ltr' | 'rtl';
203
- selectedFileFromUploader: File | null = null;
204
- private selectedItem: any;
205
-
206
-
207
- constructor(
208
- private backendService: BackendService,
209
- private router: Router,
210
- private fb: FormBuilder,
211
- public dialog: MatDialog,
212
- private directionality: Directionality
213
- ) {
214
- super();
215
- }
216
-
217
- get dataFormArray(): FormArray {
218
- return this.formParam.get('dataFormArray') as FormArray;
219
- }
220
-
221
- extractFormat(column: TableColumn<any>) {
222
- return column?.format || 'd/M/yyyy, h:mm a';
223
- }
224
-
225
- get dataSource() {
226
- return this.dataFormArray.value;
227
- }
228
-
229
- ngOnInit(): void {
230
-
231
- this.currentDirection = this.directionality.value;
232
- this.directionality.change.subscribe((value) => {
233
- this.currentDirection = value;
234
- })
235
-
236
- if(this.superDataElements?.length>0){
237
- this.dataElements=this.superDataElements;
238
- this.buildForm();
239
- this.isLoaded = true;
240
- }else {
241
- this.loadData();
242
- }
243
- }
244
-
245
- private loadData() {
246
- if (this.isPending) {
247
- this.fields.forEach(field => {
248
- field.readonly = true;
249
- });
250
- } else {
251
- this.fields.forEach(field => {
252
- field.readonly = false;
253
- });
254
- }
255
-
256
- this.filterRequest.pendingPage = this.isPending
257
- this.backendService.getItemsByFilter(this.filterRequest, this.pageInfo.apiUri).subscribe(resp => {
258
- if (resp?.valid) {
259
- this.dataElements = resp.body;
260
- this.totalElements = resp.totalSize || 0;
261
- this.noDataFound = resp.body.length < 1;
262
- this.pagesCount = resp.pagesCount || 1;
263
- this.pageIndex = this.filterRequest.pageIndex + 1;
264
- this.buildForm();
265
- this.isLoaded = true;
266
- }
267
- });
268
- }
269
-
270
- private buildForm() {
271
- this.formParam = this.fb.group({
272
- dataFormArray: this.fb.array(this.dataElements.map(item => this.fb.group(buildFormFields(this.fields, item)))),
273
- });
274
- }
275
-
276
- onPageChange(event: number) {
277
- this.getNext(event - 1);
278
- this.config.currentPage = event;
279
- }
280
- getNext($event: number) {
281
- this.filterRequest.pageIndex = $event;
282
- this.loadData()
283
- }
284
-
285
- extractFieldName(element: any, property: string) {
286
- if (property.includes('.')) {
287
- return property.split('.').reduce((acc, part) => acc && acc[part], element);
288
- } else {
289
- return element[property];
290
- }
291
- }
292
-
293
- get visibleColumns() {
294
- return this.fields.filter(column => column.visible).map(column => column.property);
295
- }
296
-
297
-
298
- ngOnChanges(changes: SimpleChanges): void {
299
- if (changes["enforceRefresh"] && !changes["enforceRefresh"].isFirstChange() && changes["enforceRefresh"].currentValue === true) {
300
- // this.loadData();
301
- }
302
- }
303
-
304
- onSelectItem(row: any) {
305
- if (this.pageInfo.selfRouting) {
306
- const mode = this.isPending ? 'pending' : 'view';
307
- const url = `${this.pageInfo.listRoutePath || this.router.url}/${mode}`;
308
- this.router.navigate([`${url}`, row?.id]);
309
- }
310
- const action = SELECT_RECORD_ACTION;
311
- action.id = row?.id;
312
- // this.userAction.emit(action)
313
- this.selectedItem = row;
314
- }
315
-
316
- openNewTab(row) {
317
- if (!this.pageInfo.embededTableOnly) {
318
- const mode = this.isPending ? 'pending' : 'view';
319
- window.open(`${this.pageInfo.listRoutePath}/${mode}` + '/' + row?.id);
320
- }
321
- }
322
-
323
-
324
- getField(element, column: FieldInfo) {
325
- return element.controls[column.property];
326
- }
327
-
328
- fieldButtonEvent(column, element, actionId: number) {
329
- this.doSaveApproveAction(element, actionId);
330
- }
331
-
332
- patchLookupValue($event: LookupItem, property: string) {
333
- this.formUpdated.emit(this.selectedItem)
334
- }
335
-
336
- addNewItem() {
337
- const currentValues = this.formParam?.get('dataFormArray')?.value;
338
- if (currentValues) {
339
- this.dataElements = [...currentValues];
340
- }
341
- this.dataElements.push({});
342
- this.buildForm();
343
- }
344
-
345
-
346
- doSaveApproveAction(element, userActionId) {
347
- let actionId = getWfActionId(element.value.stateType);
348
- if (userActionId === REJECT && this.isPending) {
349
- actionId =3
350
- }
351
- let request = new DoActionRequest();
352
- request.actionId = actionId;
353
- request.subject = element.value;
354
-
355
- if (this.actionRequestCallback) {
356
- request = this.actionRequestCallback(request);
357
- if (request.subject.id === "") {
358
- request.subject.id = null;
359
- request.subject.stateType = "NEW";
360
- }
361
- }
362
-
363
- if (request.subject.id === "") {
364
- request.subject.id = null;
365
- request.subject.stateType = "NEW";
366
- }
367
-
368
-
369
- const dialogRef = this.dialog.open(ActionCommentComponent, {
370
- data: {label: userActionId === 2 ? 'save' : 'reject', isTermination: false},
371
- width: '600px',
372
- height: 'auto',
373
- direction: this.currentDirection
374
- });
375
- console.log(actionId)
376
- dialogRef.afterClosed().subscribe(result => {
377
- if (result) {
378
- request.comment = result.comment;
379
- this.backendService.doActionWithAttachments(request, [], this.pageInfo!).subscribe(resp => {
380
- if (resp.valid) {
381
- this.loadData();
382
- console.log("actionId", actionId);
383
- let message = '';
384
- if (actionId === 1 ) {
385
- message = 'saved_successfully' ;
386
- } else if (actionId ===2 ) {
387
- message = 'updated_successfully';
388
- } else if (actionId ===3 ) {
389
- message = 'successful_reject_message';
390
- } else if (actionId ===4 ) {
391
- message = 'approve_successfully';
392
- }
393
- this.backendService.topPanelMessage$.next(new SnackMessage(message, true, 'success'));
394
- }else {
395
- const x = resp.message?.length >0 ? resp.message[0].errorMessage : 'FAILED_CONTACT_ADMIN';
396
- this.backendService.topPanelMessage$.next(new SnackMessage(x, true, 'error'));
397
- }
398
- this.saveActionEmitter.emit({item:request.subject, resp});
399
- });
400
- }
401
- });
402
- }
403
- protected readonly getPositiveWfActionKey = getPositiveWfActionKey;
404
- protected readonly getNegativeWfActionKey = getNegativeWfActionKey;
405
- protected readonly SAVE = SAVE;
406
- protected readonly REJECT = REJECT;
407
-
408
-
409
- setMonthAndYear(normalizedMonthAndYear: Moment, picker: MatDatepicker<Moment>, element, column) {
410
- const date = new FormControl(moment());
411
- const ctrlValue = date.value;
412
- ctrlValue.year(normalizedMonthAndYear.year());
413
- ctrlValue.month(1);
414
- ctrlValue.dayOfYear(1);
415
- element.controls[column.property].setValue(ctrlValue);
416
- picker.close();
417
- }
418
-
419
- switchViewMode(b: boolean) {
420
- this.isPending = b;
421
- this.loadData();
422
- }
423
-
424
- addBulkItems() {
425
- const merged: any[] = [];
426
-
427
- this.dataFormArray.controls.forEach((group: AbstractControl) => {
428
- merged.push(group.value);
429
- });
430
-
431
- let request = new DoActionRequest();
432
- request.actionId = 1;
433
-
434
- request.subject = { invoices: merged };
435
-
436
- if (this.actionRequestCallback) {
437
- request = this.actionRequestCallback(request);
438
-
439
- request.subject.invoices = request.subject.invoices.map((item: any) => {
440
- if (item.id === "") {
441
- item.id = null;
442
- item.stateType = "NEW";
443
- }
444
- return item;
445
- });
446
- }
447
-
448
- request.subject.invoices = request.subject.invoices.map((item: any) => {
449
- if (item.id === "") {
450
- item.id = null;
451
- item.stateType = "NEW";
452
- }
453
- return item;
454
- });
455
-
456
-
457
-
458
- const dialogRef = this.dialog.open(ActionCommentComponent, {
459
- data: {label: 'save' , isTermination: false},
460
- width: '600px',
461
- height: 'auto',
462
- direction: this.currentDirection
463
- });
464
- dialogRef.afterClosed().subscribe(result => {
465
- if (result) {
466
- request.comment = result.comment;
467
- this.backendService.doActionWithAttachment(request, this.selectedFileFromUploader, this.pageInfo!).subscribe(resp => {
468
- if (resp.valid) {
469
- this.clearBulkItems();
470
- this.backendService.topPanelMessage$.next(new SnackMessage('saved_successfully', true, 'success'));
471
- this.loadData();
472
- }else {
473
- this.backendService.topPanelMessage$.next(new SnackMessage(this.pageInfo.labelsSection + '.' + resp.message?.[0]?.errorCode, true, 'error'));
474
- }
475
- this.saveAttachmentEmitter.emit({item:request.subject, resp});
476
- });
477
- }
478
- }); }
479
-
480
- @ViewChild('fileUpload') fileUpload: ElementRef<HTMLInputElement>;
481
-
482
- handleFileUpload($event: File) {
483
- let actionId = getWfActionId('NEW');
484
- let request = new DoActionRequest();
485
- request.actionId = actionId;
486
-
487
- this.selectedFileFromUploader = $event;
488
-
489
- }
490
-
491
- shouldDisableBulkAdd() {
492
- const hasFile = !!this.selectedFileFromUploader;
493
- return (!this.formParam?.valid || this.dataFormArray.controls.length === 0) && !hasFile;
494
- }
495
- handleEquationChange(event: { value: any[], valid: boolean }, element: FormGroup, column: any): void {
496
- element.value[column.property] = event.value;
497
- const { value, valid } = event;
498
- element.get(column.property)?.setValue(value);
499
- if (!valid) {
500
- element.get(column.property)?.setErrors({ invalidEquation: true });
501
- } else {
502
- element.get(column.property)?.setErrors(null);
503
- }
504
- }
505
-
506
- clearBulkItems() {
507
- this.dataElements = [];
508
- this.selectedFileFromUploader = null;
509
- this.uploaderComponent.clearFile();
510
- this.buildForm();
511
- this.formUpdated.emit(this.formParam);
512
- }
513
-
514
- hasDataToClear(): boolean {
515
- return (this.dataElements && this.dataElements.length > 0) || !!this.selectedFileFromUploader;
516
- }
517
- getOptionValue(item: any) {
518
- const value = typeof item === 'object' ?
519
- item.englishName : item;
520
- return value;
521
- }
522
-
523
- disabledSaveButton(element) {
524
- return !element.valid || (!this.isPending && element.value.stateType == 'PENDING');
525
- }
526
-
527
- doSearch() {
528
- if (this.searchForm.valid) {
529
- const rawValues = this.searchForm.getRawValue();
530
- this.filterRequest.pageIndex=0;
531
- this.filterRequest.filters = [];
532
- this.searchFormFields.forEach(x => {
533
- const value = rawValues[x.property];
534
- if (value !== null && value !== undefined && value !== '') {
535
- const filter = new Filter({
536
- key: 0,
537
- label: x.property,
538
- fieldName: x.searchAttribute,
539
- valueObject : x.searchAttribute.includes('.') ? value[x.searchAttribute.split('.').pop()] : value,
540
- operator: x.searchOperator,
541
- filterType: 'FILED_FILTER'
542
- });
543
- this.filterRequest.filters.push(filter);
544
- }
545
- });
546
- this.loadData();
547
- } else {
548
- this.backendService.topPanelMessage$.next(new SnackMessage('INVALID_SEARCH_FORM', true, 'error'));
549
- }
550
- }
551
-
552
- showSearch() {
553
- return this.searchFormFields?.length > 0;
554
- }
555
-
556
- clearSearch() {
557
- this.searchForm.get('sectorType').setValue({id:-100, englishName:'aaa', code:'aaa', arabicName:'aaa'});
558
- this.searchForm.reset();
559
- this.doSearch();
560
- }
561
-
562
- updateSearchForm($event: FormGroup) {
563
- this.searchForm = $event
564
- }
565
-
566
- validSearchData() {
567
- return !this.searchForm.valid || true;
568
- }
569
-
570
- }
1
+ import {
2
+ Component,
3
+ ElementRef,
4
+ EventEmitter,
5
+ Input,
6
+ OnChanges,
7
+ OnInit,
8
+ Output,
9
+ SimpleChanges,
10
+ ViewChild
11
+ } from "@angular/core";
12
+ import {
13
+ MatCell,
14
+ MatCellDef,
15
+ MatColumnDef,
16
+ MatHeaderCell,
17
+ MatHeaderCellDef,
18
+ MatHeaderRow,
19
+ MatHeaderRowDef,
20
+ MatRow,
21
+ MatRowDef,
22
+ MatTable
23
+ } from "@angular/material/table";
24
+ import {TranslateModule} from "@ngx-translate/core";
25
+ import {MatSortModule} from "@angular/material/sort";
26
+ import {NgClass, NgForOf, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault} from "@angular/common";
27
+ import {MatIcon} from "@angular/material/icon";
28
+ import {MatButton, MatButtonModule} from "@angular/material/button";
29
+ import {NgxPaginationModule} from "ngx-pagination";
30
+ import {Router} from "@angular/router";
31
+ import {AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";
32
+ import {MatError, MatFormField, MatInput, MatLabel, MatSuffix} from "@angular/material/input";
33
+ import {BackendService} from "../../services";
34
+ import {
35
+ BaseUtils,
36
+ buildFormFields,
37
+ getNegativeWfActionKey,
38
+ getPositiveWfActionKey,
39
+ getWfActionId
40
+ } from "../../utils/base-utils";
41
+ import {
42
+ EMPTY_PAGE_INFO,
43
+ FieldInfo,
44
+ Filter,
45
+ FilterRequest,
46
+ LookupItem,
47
+ PageInfo,
48
+ SELECT_RECORD_ACTION,
49
+ SnackMessage,
50
+ TableColumn
51
+ } from "../../base-model";
52
+ import {DoActionRequest, REJECT, SAVE} from "../../base-model/do-action-request";
53
+ import {ActionCommentComponent} from "../action-comment/action-comment.component";
54
+ import {MatDialog} from "@angular/material/dialog";
55
+ import {MatDatepicker, MatDatepickerInput, MatDatepickerToggle} from "@angular/material/datepicker";
56
+ import moment, {Moment} from 'moment';
57
+ import {AutoCompleteComponent} from "../auto-complete/auto-complete.component";
58
+ import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatOption} from "@angular/material/core";
59
+ import {MatChipListbox, MatChipOption} from "@angular/material/chips";
60
+ import {TitleBarComponent} from "../title-bar/title-bar.component";
61
+ import {PaginatorComponent} from "../paginator/paginator.component";
62
+ import {Directionality} from "@angular/cdk/bidi";
63
+ import {AttachmentUploaderComponent} from "../shared/attachment-uploader/attachment-uploader.component";
64
+ import {EquationBuilderComponent} from "../equation-builder/equation-builder.component";
65
+ import {MatSelect} from "@angular/material/select";
66
+
67
+ import {BaseFormCanvasComponent} from "../base-form-canvas/base-form-canvas.component";
68
+ import {MatCheckbox} from "@angular/material/checkbox";
69
+ @Component({
70
+ selector: 'app-editable-base-table',
71
+ standalone: true,
72
+ templateUrl: './editable-base-table.component.html',
73
+ styleUrls: ['./editable-base-table.component.scss'],
74
+ animations: [],
75
+ imports: [
76
+ NgClass,
77
+ TranslateModule,
78
+ MatIcon,
79
+ MatSortModule,
80
+ MatColumnDef,
81
+ MatHeaderCellDef,
82
+ NgIf,
83
+ MatTable,
84
+ MatHeaderCell,
85
+ NgSwitch,
86
+ MatButtonModule,
87
+ MatCell,
88
+ MatCellDef,
89
+ NgxPaginationModule,
90
+ MatRow,
91
+ MatRowDef,
92
+ MatHeaderRow,
93
+ NgSwitchCase,
94
+ NgSwitchDefault,
95
+ MatHeaderRowDef,
96
+ NgForOf,
97
+ MatButton,
98
+ ReactiveFormsModule,
99
+ MatInput,
100
+ AutoCompleteComponent,
101
+ MatFormField,
102
+ MatDatepicker,
103
+ MatDatepickerInput,
104
+ MatDatepickerToggle,
105
+ MatLabel,
106
+ MatSuffix,
107
+ MatChipListbox,
108
+ MatChipOption,
109
+ TitleBarComponent,
110
+ PaginatorComponent,
111
+ AttachmentUploaderComponent,
112
+ EquationBuilderComponent,
113
+ MatSelect,
114
+ MatOption,
115
+ BaseFormCanvasComponent,
116
+ MatCheckbox,
117
+ ],
118
+ providers: [
119
+ // `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
120
+ // application's root module. We provide it at the component level here, due to limitations of
121
+ // our example generation script.
122
+ // {
123
+ // provide: DateAdapter,
124
+ // useClass: MomentDateAdapter,
125
+ // deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
126
+ // },
127
+
128
+ // { provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
129
+ ],
130
+ })
131
+
132
+ export class EditableBaseTableComponent extends BaseUtils implements OnInit, OnChanges {
133
+
134
+ collection = {count: 60, data: []};
135
+ config = {
136
+ itemsPerPage: 10,
137
+ currentPage: 1,
138
+ totalItems: this.collection.count
139
+ };
140
+ public maxSize: number = 7;
141
+ public directionLinks: boolean = true;
142
+ public autoHide: boolean = false;
143
+ public responsive: boolean = true;
144
+ public labels: any = {
145
+ previousLabel: '<',
146
+ nextLabel: '>',
147
+ screenReaderPaginationLabel: 'Pagination',
148
+ screenReaderPageLabel: 'page',
149
+ screenReaderCurrentLabel: `You're on page`
150
+ };
151
+
152
+ private timer: any;
153
+ dataElements: any[] = [];
154
+ noDataFound = false;
155
+ isLoaded: boolean = false;
156
+ totalElements = 0;
157
+ pagesCount = 0;
158
+ pageIndex = 1;
159
+ pageSize = 10;
160
+ formParam: FormGroup;
161
+ searchForm: FormGroup;
162
+
163
+ @Input()
164
+ filterRequest: FilterRequest;
165
+
166
+ @Input()
167
+ superDataElements: any[];
168
+
169
+ @Input()
170
+ override pageInfo: PageInfo = EMPTY_PAGE_INFO;
171
+
172
+ @Input() //@ts-ignore
173
+ enforceRefresh: boolean = false;
174
+
175
+ @Input()
176
+ isPending: boolean = false;
177
+
178
+ @Input()
179
+ isBulkItemsSupported: boolean = false;
180
+
181
+ @Input()// @ts-ignore
182
+ public fields: FieldInfo[] = [];
183
+
184
+ @Input()// @ts-ignore
185
+ public searchFormFields: FieldInfo[] = [];
186
+
187
+ @Input() translationKey: string = 'addNew';
188
+
189
+ @Output()
190
+ formUpdated: EventEmitter<FormGroup> = new EventEmitter<FormGroup>();
191
+
192
+ @Output()
193
+ saveActionEmitter: EventEmitter<any> = new EventEmitter<any>();
194
+ @Output()
195
+ saveAttachmentEmitter: EventEmitter<any> = new EventEmitter<any>();
196
+
197
+ @Input() actionRequestCallback!: (actionRequest: DoActionRequest) => DoActionRequest;
198
+
199
+ @ViewChild('uploader') uploaderComponent!: AttachmentUploaderComponent;
200
+
201
+ currentDirection: 'ltr' | 'rtl';
202
+ selectedFileFromUploader: File | null = null;
203
+ private selectedItem: any;
204
+
205
+
206
+ constructor(
207
+ private backendService: BackendService,
208
+ private router: Router,
209
+ private fb: FormBuilder,
210
+ public dialog: MatDialog,
211
+ private directionality: Directionality
212
+ ) {
213
+ super();
214
+ }
215
+
216
+ get dataFormArray(): FormArray {
217
+ return this.formParam.get('dataFormArray') as FormArray;
218
+ }
219
+
220
+ extractFormat(column: TableColumn<any>) {
221
+ return column?.format || 'd/M/yyyy, h:mm a';
222
+ }
223
+
224
+ get dataSource() {
225
+ return this.dataFormArray.value;
226
+ }
227
+
228
+ ngOnInit(): void {
229
+
230
+ this.currentDirection = this.directionality.value;
231
+ this.directionality.change.subscribe((value) => {
232
+ this.currentDirection = value;
233
+ })
234
+
235
+ if(this.superDataElements?.length>0){
236
+ this.dataElements=this.superDataElements;
237
+ this.buildForm();
238
+ this.isLoaded = true;
239
+ }else {
240
+ this.loadData();
241
+ }
242
+ }
243
+
244
+ private loadData() {
245
+ this.fields.forEach(field => field.readonly = this.isPending);
246
+
247
+ this.dataElements = [];
248
+ this.totalElements = 0;
249
+ this.pagesCount = 1;
250
+ this.pageIndex = 1;
251
+ this.noDataFound = true;
252
+ this.isLoaded = true;
253
+
254
+ this.filterRequest.pendingPage = this.isPending;
255
+
256
+ if (!this.pageInfo.lazyLoadData) {
257
+ this.backendService.getItemsByFilter(this.filterRequest, this.pageInfo.apiUri)
258
+ .subscribe(resp => {
259
+ this.dataElements = resp.body || [];
260
+ this.totalElements = resp.totalSize || 0;
261
+ this.pagesCount = Math.max(Math.ceil(this.totalElements / this.pageSize), 1);
262
+ this.pageIndex = (this.filterRequest.pageIndex || 0) + 1;
263
+ this.noDataFound = this.dataElements.length === 0;
264
+ this.isLoaded = true;
265
+ });
266
+ }
267
+
268
+ this.buildForm();
269
+ }
270
+
271
+ private buildForm() {
272
+ this.formParam = this.fb.group({
273
+ dataFormArray: this.fb.array(this.dataElements.map(item => this.fb.group(buildFormFields(this.fields, item)))),
274
+ });
275
+ this.formUpdated.next(this.formParam);
276
+ }
277
+
278
+ onPageChange(event: number) {
279
+ this.pageIndex = event;
280
+ this.getNext(this.pageIndex - 1);
281
+ }
282
+ getNext(pageIndex: number) {
283
+ this.filterRequest.pageIndex = pageIndex;
284
+ this.filterRequest.pageSize = this.pageSize;
285
+ this.loadData();
286
+ }
287
+
288
+ onPageSizeChange(event: number) {
289
+ this.pageSize = event;
290
+ this.pageIndex = 1;
291
+ this.filterRequest.pageSize = this.pageSize;
292
+ this.getNext(0);
293
+ }
294
+
295
+
296
+ extractFieldName(element: any, property: string) {
297
+ if (property.includes('.')) {
298
+ return property.split('.').reduce((acc, part) => acc && acc[part], element);
299
+ } else {
300
+ return element[property];
301
+ }
302
+ }
303
+
304
+ get visibleColumns() {
305
+ return this.fields.filter(column => column.visible).map(column => column.property);
306
+ }
307
+
308
+
309
+ ngOnChanges(changes: SimpleChanges): void {
310
+ if (changes["enforceRefresh"] && !changes["enforceRefresh"].isFirstChange() && changes["enforceRefresh"].currentValue === true) {
311
+ // this.loadData();
312
+ }
313
+ }
314
+
315
+ onSelectItem(row: any) {
316
+ if (this.pageInfo.selfRouting) {
317
+ const mode = this.isPending ? 'pending' : 'view';
318
+ const url = `${this.pageInfo.listRoutePath || this.router.url}/${mode}`;
319
+ this.router.navigate([`${url}`, row?.id]);
320
+ }
321
+ const action = SELECT_RECORD_ACTION;
322
+ action.id = row?.id;
323
+ // this.userAction.emit(action)
324
+ this.selectedItem = row;
325
+ }
326
+
327
+ openNewTab(row) {
328
+ if (!this.pageInfo.embededTableOnly) {
329
+ const mode = this.isPending ? 'pending' : 'view';
330
+ window.open(`${this.pageInfo.listRoutePath}/${mode}` + '/' + row?.id);
331
+ }
332
+ }
333
+
334
+
335
+ getField(element, column: FieldInfo) {
336
+ return element.controls[column.property];
337
+ }
338
+
339
+ fieldButtonEvent(column, element, actionId: number) {
340
+ this.doSaveApproveAction(element, actionId);
341
+ }
342
+
343
+ patchLookupValue($event: LookupItem, property: string) {
344
+ this.formUpdated.emit(this.selectedItem)
345
+ }
346
+
347
+ addNewItem() {
348
+ const currentValues = this.formParam?.get('dataFormArray')?.value;
349
+ if (currentValues) {
350
+ this.dataElements = [...currentValues];
351
+ }
352
+ this.dataElements.push({});
353
+ this.buildForm();
354
+ }
355
+
356
+
357
+ doSaveApproveAction(element, userActionId) {
358
+ let actionId = getWfActionId(element.value.stateType);
359
+ if (userActionId === REJECT && this.isPending) {
360
+ actionId =3
361
+ }
362
+ let request = new DoActionRequest();
363
+ request.actionId = actionId;
364
+ request.subject = element.value;
365
+
366
+ if (this.actionRequestCallback) {
367
+ request = this.actionRequestCallback(request);
368
+ if (request.subject.id === "") {
369
+ request.subject.id = null;
370
+ request.subject.stateType = "NEW";
371
+ }
372
+ }
373
+
374
+ if (request.subject.id === "") {
375
+ request.subject.id = null;
376
+ request.subject.stateType = "NEW";
377
+ }
378
+
379
+
380
+ const dialogRef = this.dialog.open(ActionCommentComponent, {
381
+ data: {label: userActionId === 2 ? 'save' : 'reject', isTermination: false},
382
+ width: '600px',
383
+ height: 'auto',
384
+ direction: this.currentDirection
385
+ });
386
+ dialogRef.afterClosed().subscribe(result => {
387
+ if (result) {
388
+ request.comment = result.comment;
389
+ this.backendService.doActionWithAttachments(request, [], this.pageInfo!).subscribe(resp => {
390
+ if (resp.valid) {
391
+ this.loadData();
392
+ let message = '';
393
+ if (actionId === 1 ) {
394
+ message = 'saved_successfully' ;
395
+ } else if (actionId ===2 ) {
396
+ message = 'updated_successfully';
397
+ } else if (actionId ===3 ) {
398
+ message = 'successful_reject_message';
399
+ } else if (actionId ===4 ) {
400
+ message = 'approve_successfully';
401
+ }
402
+ this.backendService.topPanelMessage$.next(new SnackMessage(message, true, 'success'));
403
+ }else {
404
+ const x = resp.message?.length >0 ? resp.message[0].errorMessage : 'FAILED_CONTACT_ADMIN';
405
+ this.backendService.topPanelMessage$.next(new SnackMessage(x, true, 'error'));
406
+ }
407
+ this.saveActionEmitter.emit({item:request.subject, resp});
408
+ });
409
+ }
410
+ });
411
+ }
412
+ protected readonly getPositiveWfActionKey = getPositiveWfActionKey;
413
+ protected readonly getNegativeWfActionKey = getNegativeWfActionKey;
414
+ protected readonly SAVE = SAVE;
415
+ protected readonly REJECT = REJECT;
416
+
417
+
418
+ setMonthAndYear(normalizedMonthAndYear: Moment, picker: MatDatepicker<Moment>, element, column) {
419
+ const date = new FormControl(moment());
420
+ const ctrlValue = date.value;
421
+ ctrlValue.year(normalizedMonthAndYear.year());
422
+ ctrlValue.month(1);
423
+ ctrlValue.dayOfYear(1);
424
+ element.controls[column.property].setValue(ctrlValue);
425
+ picker.close();
426
+ }
427
+
428
+ switchViewMode(b: boolean) {
429
+ this.isPending = b;
430
+ this.loadData();
431
+ }
432
+
433
+ addBulkItems() {
434
+ const merged: any[] = [];
435
+
436
+ this.dataFormArray.controls.forEach((group: AbstractControl) => {
437
+ merged.push(group.value);
438
+ });
439
+
440
+ let request = new DoActionRequest();
441
+ request.actionId = 1;
442
+
443
+ request.subject = { invoices: merged };
444
+
445
+ if (this.actionRequestCallback) {
446
+ request = this.actionRequestCallback(request);
447
+
448
+ request.subject.invoices = request.subject.invoices.map((item: any) => {
449
+ if (item.id === "") {
450
+ item.id = null;
451
+ item.stateType = "NEW";
452
+ }
453
+ return item;
454
+ });
455
+ }
456
+
457
+ request.subject.invoices = request.subject.invoices.map((item: any) => {
458
+ if (item.id === "") {
459
+ item.id = null;
460
+ item.stateType = "NEW";
461
+ }
462
+ return item;
463
+ });
464
+
465
+
466
+
467
+ const dialogRef = this.dialog.open(ActionCommentComponent, {
468
+ data: {label: 'save' , isTermination: false},
469
+ width: '600px',
470
+ height: 'auto',
471
+ direction: this.currentDirection
472
+ });
473
+ dialogRef.afterClosed().subscribe(result => {
474
+ if (result) {
475
+ request.comment = result.comment;
476
+ this.backendService.doActionWithAttachment(request, this.selectedFileFromUploader, this.pageInfo!).subscribe(resp => {
477
+ if (resp.valid) {
478
+ this.clearBulkItems();
479
+ this.backendService.topPanelMessage$.next(new SnackMessage('saved_successfully', true, 'success'));
480
+ this.loadData();
481
+ }else {
482
+ this.backendService.topPanelMessage$.next(new SnackMessage(this.pageInfo.labelsSection + '.' + resp.message?.[0]?.errorCode, true, 'error'));
483
+ }
484
+ this.saveAttachmentEmitter.emit({item:request.subject, resp});
485
+ });
486
+ }
487
+ }); }
488
+
489
+ @ViewChild('fileUpload') fileUpload: ElementRef<HTMLInputElement>;
490
+
491
+ handleFileUpload($event: File) {
492
+ let actionId = getWfActionId('NEW');
493
+ let request = new DoActionRequest();
494
+ request.actionId = actionId;
495
+
496
+ this.selectedFileFromUploader = $event;
497
+
498
+ }
499
+
500
+ shouldDisableBulkAdd() {
501
+ const hasFile = !!this.selectedFileFromUploader;
502
+ return (!this.formParam?.valid || this.dataFormArray.controls.length === 0) && !hasFile;
503
+ }
504
+ handleEquationChange(event: { value: any[], valid: boolean }, element: FormGroup, column: any): void {
505
+ element.value[column.property] = event.value;
506
+ const { value, valid } = event;
507
+ element.get(column.property)?.setValue(value);
508
+ if (!valid) {
509
+ element.get(column.property)?.setErrors({ invalidEquation: true });
510
+ } else {
511
+ element.get(column.property)?.setErrors(null);
512
+ }
513
+ }
514
+
515
+ clearBulkItems() {
516
+ this.dataElements = [];
517
+ this.selectedFileFromUploader = null;
518
+ this.uploaderComponent.clearFile();
519
+ this.buildForm();
520
+ this.formUpdated.emit(this.formParam);
521
+ }
522
+
523
+ hasDataToClear(): boolean {
524
+ return (this.dataElements && this.dataElements.length > 0) || !!this.selectedFileFromUploader;
525
+ }
526
+ getOptionValue(item: any) {
527
+ const value = typeof item === 'object' ?
528
+ item.englishName : item;
529
+ return value;
530
+ }
531
+
532
+ disabledSaveButton(element) {
533
+ return !element.valid || (!this.isPending && element.value.stateType == 'PENDING');
534
+ }
535
+
536
+ doSearch() {
537
+ if (this.searchForm.valid) {
538
+ const rawValues = this.searchForm.getRawValue();
539
+ this.filterRequest.pageIndex=0;
540
+ this.filterRequest.filters = [];
541
+ this.searchFormFields.forEach(x => {
542
+ const value = rawValues[x.property];
543
+ if (value !== null && value !== undefined && value !== '') {
544
+ const filter = new Filter({
545
+ key: 0,
546
+ label: x.property,
547
+ fieldName: x.searchAttribute,
548
+ valueObject : x.searchAttribute.includes('.') ? value[x.searchAttribute.split('.').pop()] : value,
549
+ operator: x.searchOperator,
550
+ filterType: 'FILED_FILTER'
551
+ });
552
+ this.filterRequest.filters.push(filter);
553
+ }
554
+ });
555
+ this.loadData();
556
+ } else {
557
+ this.backendService.topPanelMessage$.next(new SnackMessage('INVALID_SEARCH_FORM', true, 'error'));
558
+ }
559
+ }
560
+
561
+ showSearch() {
562
+ return this.searchFormFields?.length > 0;
563
+ }
564
+
565
+ clearSearch() {
566
+ this.searchForm.get('sectorType').setValue({id:-100, englishName:'aaa', code:'aaa', arabicName:'aaa'});
567
+ this.searchForm.reset();
568
+ this.doSearch();
569
+ }
570
+
571
+ updateSearchForm($event: FormGroup) {
572
+ this.searchForm = $event
573
+ }
574
+
575
+ validSearchData() {
576
+ return !this.searchForm.valid || true;
577
+ }
578
+
579
+ }