@unifylib/ui-lib 1.0.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 (129) hide show
  1. package/README.md +0 -0
  2. package/ng-package.json +7 -0
  3. package/package.json +12 -0
  4. package/src/lib/base-model/SearchStrConfig.ts +12 -0
  5. package/src/lib/base-model/api-response.ts +23 -0
  6. package/src/lib/base-model/audit-log-entry.ts +7 -0
  7. package/src/lib/base-model/button-action-settings.ts +25 -0
  8. package/src/lib/base-model/column-def.model.ts +34 -0
  9. package/src/lib/base-model/do-action-request.ts +11 -0
  10. package/src/lib/base-model/field-action.ts +7 -0
  11. package/src/lib/base-model/field-filter.model.ts +14 -0
  12. package/src/lib/base-model/field-info.ts +98 -0
  13. package/src/lib/base-model/field-predicate.model.ts +7 -0
  14. package/src/lib/base-model/filter-request.ts +27 -0
  15. package/src/lib/base-model/filter.model.ts +49 -0
  16. package/src/lib/base-model/get-items-list.ts +24 -0
  17. package/src/lib/base-model/index.ts +11 -0
  18. package/src/lib/base-model/lookupItem.ts +21 -0
  19. package/src/lib/base-model/null-snackmessage.ts +9 -0
  20. package/src/lib/base-model/page-info.ts +51 -0
  21. package/src/lib/base-model/report-request.model.ts +33 -0
  22. package/src/lib/base-model/response-envelop.model.ts +15 -0
  23. package/src/lib/base-model/snack-message.model.ts +14 -0
  24. package/src/lib/base-model/snackmessage-interface.ts +7 -0
  25. package/src/lib/base-model/table-column.interface.ts +29 -0
  26. package/src/lib/base-model/table-page-user-action.interface.ts +33 -0
  27. package/src/lib/base-model/workflow/workflow-steps.model.ts +9 -0
  28. package/src/lib/base-model/workflow/workflow.model.ts +52 -0
  29. package/src/lib/components/action-confirmation/action-confirmation.component.css +34 -0
  30. package/src/lib/components/action-confirmation/action-confirmation.component.html +18 -0
  31. package/src/lib/components/action-confirmation/action-confirmation.component.spec.ts +23 -0
  32. package/src/lib/components/action-confirmation/action-confirmation.component.ts +58 -0
  33. package/src/lib/components/activity-report-form/activity-report-form.component.html +109 -0
  34. package/src/lib/components/activity-report-form/activity-report-form.component.scss +0 -0
  35. package/src/lib/components/activity-report-form/activity-report-form.component.spec.ts +25 -0
  36. package/src/lib/components/activity-report-form/activity-report-form.component.ts +605 -0
  37. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.css +51 -0
  38. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.html +23 -0
  39. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.spec.ts +23 -0
  40. package/src/lib/components/audit-log-details-dialog/audit-log-details-dialog.component.ts +69 -0
  41. package/src/lib/components/audit-log-list/audit-log.component.html +23 -0
  42. package/src/lib/components/audit-log-list/audit-log.component.scss +0 -0
  43. package/src/lib/components/audit-log-list/audit-log.component.spec.ts +25 -0
  44. package/src/lib/components/audit-log-list/audit-log.component.ts +116 -0
  45. package/src/lib/components/auto-complete/auto-complete.component.css +14 -0
  46. package/src/lib/components/auto-complete/auto-complete.component.html +29 -0
  47. package/src/lib/components/auto-complete/auto-complete.component.spec.ts +23 -0
  48. package/src/lib/components/auto-complete/auto-complete.component.ts +330 -0
  49. package/src/lib/components/base-form/base-form.component.html +58 -0
  50. package/src/lib/components/base-form/base-form.component.scss +0 -0
  51. package/src/lib/components/base-form/base-form.component.spec.ts +25 -0
  52. package/src/lib/components/base-form/base-form.component.ts +305 -0
  53. package/src/lib/components/base-form-canvas/base-form-canvas.component.css +22 -0
  54. package/src/lib/components/base-form-canvas/base-form-canvas.component.html +1006 -0
  55. package/src/lib/components/base-form-canvas/base-form-canvas.component.spec.ts +23 -0
  56. package/src/lib/components/base-form-canvas/base-form-canvas.component.ts +573 -0
  57. package/src/lib/components/base-input-dialog/base-input-dialog.component.css +0 -0
  58. package/src/lib/components/base-input-dialog/base-input-dialog.component.html +42 -0
  59. package/src/lib/components/base-input-dialog/base-input-dialog.component.spec.ts +23 -0
  60. package/src/lib/components/base-input-dialog/base-input-dialog.component.ts +78 -0
  61. package/src/lib/components/base-table/base-table.component.html +242 -0
  62. package/src/lib/components/base-table/base-table.component.scss +31 -0
  63. package/src/lib/components/base-table/base-table.component.spec.ts +25 -0
  64. package/src/lib/components/base-table/base-table.component.ts +568 -0
  65. package/src/lib/components/button-actions/button-actions.component.html +28 -0
  66. package/src/lib/components/button-actions/button-actions.component.scss +6 -0
  67. package/src/lib/components/button-actions/button-actions.component.spec.ts +23 -0
  68. package/src/lib/components/button-actions/button-actions.component.ts +72 -0
  69. package/src/lib/components/editable-base-table/editable-base-table.component.html +372 -0
  70. package/src/lib/components/editable-base-table/editable-base-table.component.scss +44 -0
  71. package/src/lib/components/editable-base-table/editable-base-table.component.spec.ts +25 -0
  72. package/src/lib/components/editable-base-table/editable-base-table.component.ts +570 -0
  73. package/src/lib/components/equation-builder/equation-builder.component.css +0 -0
  74. package/src/lib/components/equation-builder/equation-builder.component.html +31 -0
  75. package/src/lib/components/equation-builder/equation-builder.component.spec.ts +23 -0
  76. package/src/lib/components/equation-builder/equation-builder.component.ts +121 -0
  77. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.css +11 -0
  78. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.html +38 -0
  79. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.spec.ts +23 -0
  80. package/src/lib/components/multi-auto-complete/multi-auto-complete.component.ts +317 -0
  81. package/src/lib/components/paginator/paginator.component.css +25 -0
  82. package/src/lib/components/paginator/paginator.component.html +34 -0
  83. package/src/lib/components/paginator/paginator.component.ts +94 -0
  84. package/src/lib/components/rejection-comment/action-comment.component.css +33 -0
  85. package/src/lib/components/rejection-comment/action-comment.component.html +46 -0
  86. package/src/lib/components/rejection-comment/action-comment.component.spec.ts +23 -0
  87. package/src/lib/components/rejection-comment/action-comment.component.ts +86 -0
  88. package/src/lib/components/report-details-dialog/report-details-dialog.component.css +17 -0
  89. package/src/lib/components/report-details-dialog/report-details-dialog.component.html +16 -0
  90. package/src/lib/components/report-details-dialog/report-details-dialog.component.spec.ts +23 -0
  91. package/src/lib/components/report-details-dialog/report-details-dialog.component.ts +113 -0
  92. package/src/lib/components/report-form/report-form.component.html +94 -0
  93. package/src/lib/components/report-form/report-form.component.scss +0 -0
  94. package/src/lib/components/report-form/report-form.component.spec.ts +25 -0
  95. package/src/lib/components/report-form/report-form.component.ts +588 -0
  96. package/src/lib/components/search-bar/search-bar.component.html +62 -0
  97. package/src/lib/components/search-bar/search-bar.component.scss +8 -0
  98. package/src/lib/components/search-bar/search-bar.component.spec.ts +25 -0
  99. package/src/lib/components/search-bar/search-bar.component.ts +70 -0
  100. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.css +54 -0
  101. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.html +22 -0
  102. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.spec.ts +23 -0
  103. package/src/lib/components/shared/attachment-uploader/attachment-uploader.component.ts +45 -0
  104. package/src/lib/components/shared-list/shared-list.component.css +0 -0
  105. package/src/lib/components/shared-list/shared-list.component.html +17 -0
  106. package/src/lib/components/shared-list/shared-list.component.spec.ts +23 -0
  107. package/src/lib/components/shared-list/shared-list.component.ts +53 -0
  108. package/src/lib/components/title-bar/title-bar.component.css +0 -0
  109. package/src/lib/components/title-bar/title-bar.component.css.map +1 -0
  110. package/src/lib/components/title-bar/title-bar.component.html +31 -0
  111. package/src/lib/components/title-bar/title-bar.component.scss +23 -0
  112. package/src/lib/components/title-bar/title-bar.component.spec.ts +23 -0
  113. package/src/lib/components/title-bar/title-bar.component.ts +119 -0
  114. package/src/lib/services/backend-service.ts +286 -0
  115. package/src/lib/services/index.ts +3 -0
  116. package/src/lib/services/top-panel.ts +17 -0
  117. package/src/lib/services/trigger-form.service.ts +11 -0
  118. package/src/lib/share-module/shared-module.ts +10 -0
  119. package/src/lib/styles/invoiceq-theme.scss +252 -0
  120. package/src/lib/styles/styles.scss +1723 -0
  121. package/src/lib/utils/base-utils.ts +102 -0
  122. package/src/lib/validators/date-range-validator.ts +31 -0
  123. package/src/lib/validators/index.ts +3 -0
  124. package/src/lib/validators/match-list.validator.ts +10 -0
  125. package/src/lib/validators/multi-email-validator.ts +15 -0
  126. package/src/public-api.ts +21 -0
  127. package/tsconfig.lib.json +15 -0
  128. package/tsconfig.lib.prod.json +11 -0
  129. package/tsconfig.spec.json +15 -0
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { BaseFormCanvasComponent } from './base-form-canvas.component';
4
+
5
+ describe('BaseFormCanvasComponent', () => {
6
+ let component: BaseFormCanvasComponent;
7
+ let fixture: ComponentFixture<BaseFormCanvasComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [BaseFormCanvasComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(BaseFormCanvasComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,573 @@
1
+ import {
2
+ Component,
3
+ computed,
4
+ ElementRef,
5
+ EventEmitter,
6
+ Input,
7
+ model,
8
+ OnChanges,
9
+ OnDestroy,
10
+ OnInit,
11
+ Output,
12
+ signal,
13
+ SimpleChanges,
14
+ ViewChild
15
+ } from '@angular/core';
16
+ import {FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule} from "@angular/forms";
17
+ import {
18
+ MatChip,
19
+ MatChipGrid,
20
+ MatChipInput,
21
+ MatChipInputEvent,
22
+ MatChipListbox,
23
+ MatChipOption,
24
+ MatChipRemove,
25
+ MatChipRow
26
+ } from "@angular/material/chips";
27
+ import {FieldInfo} from "../../base-model/field-info";
28
+ import {ActivatedRoute} from "@angular/router";
29
+ import {BackendService} from "../../services/backend-service";
30
+ import {TranslateModule, TranslateService} from "@ngx-translate/core";
31
+ import {PageInfo} from "../../base-model/page-info";
32
+ import {COMMA, ENTER, SEMICOLON} from "@angular/cdk/keycodes";
33
+ import {LookupItem} from "../../base-model/lookupItem";
34
+ import {FieldMessage} from "../../base-model/api-response";
35
+ import {
36
+ CurrencyPipe,
37
+ DatePipe,
38
+ KeyValuePipe,
39
+ NgForOf,
40
+ NgIf,
41
+ NgSwitch,
42
+ NgSwitchCase,
43
+ NgTemplateOutlet
44
+ } from "@angular/common";
45
+ import {FlexLayoutModule} from "@angular/flex-layout";
46
+ import {MatError, MatFormFieldModule, MatLabel} from "@angular/material/form-field";
47
+ import {MatInputModule} from "@angular/material/input";
48
+ import {MatDatepicker, MatDatepickerInput, MatDatepickerToggle} from "@angular/material/datepicker";
49
+ import {MatIcon} from "@angular/material/icon";
50
+ import {CdkTextareaAutosize} from "@angular/cdk/text-field";
51
+ import {MatRadioButton, MatRadioGroup} from "@angular/material/radio";
52
+ import {MatCheckbox} from "@angular/material/checkbox";
53
+ import {MatOption, MatSelect} from "@angular/material/select";
54
+ import {MatDivider} from "@angular/material/divider";
55
+ import {NgxJsonViewerModule} from "ngx-json-viewer";
56
+ import {NgxMatIntlTelInputComponent} from "ngx-mat-intl-tel-input";
57
+ import {MultiAutoCompleteComponent} from "../multi-auto-complete/multi-auto-complete.component";
58
+ import {AutoCompleteComponent} from "../auto-complete/auto-complete.component";
59
+ import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
60
+ import {BehaviorSubject, map} from "rxjs";
61
+ import {LiveAnnouncer} from "@angular/cdk/a11y";
62
+ import {buildFormFields} from "../../utils/base-utils";
63
+ import moment, {Moment} from "moment/moment";
64
+
65
+ @Component({
66
+ selector: 'app-base-form-canvas',
67
+ standalone: true,
68
+ imports: [
69
+ ReactiveFormsModule,
70
+ NgSwitch,
71
+ FormsModule,
72
+ FlexLayoutModule,
73
+ NgForOf,
74
+ NgTemplateOutlet,
75
+ KeyValuePipe,
76
+ NgIf,
77
+ MatLabel,
78
+ MatFormFieldModule,
79
+ TranslateModule,
80
+ MatInputModule,
81
+ MatDatepickerInput,
82
+ MatDatepicker,
83
+ MatDatepickerToggle,
84
+ MatError,
85
+ NgSwitchCase,
86
+ MatIcon,
87
+ MatChip,
88
+ CdkTextareaAutosize,
89
+ MatRadioGroup,
90
+ MatCheckbox,
91
+ MatRadioButton,
92
+ MatSelect,
93
+ MatOption,
94
+ MatDivider,
95
+ DatePipe,
96
+ NgxJsonViewerModule,
97
+ CurrencyPipe,
98
+ NgxMatIntlTelInputComponent,
99
+ MatChipGrid,
100
+ MatChipInput,
101
+ MatChipRow,
102
+ MatChipListbox,
103
+ MatChipOption,
104
+ MultiAutoCompleteComponent,
105
+ AutoCompleteComponent,
106
+ MatChipRemove
107
+ ],
108
+ templateUrl: './base-form-canvas.component.html',
109
+ styleUrl: './base-form-canvas.component.css'
110
+ })
111
+ export class BaseFormCanvasComponent implements OnInit, OnChanges, OnDestroy {
112
+ public hide: boolean = true;
113
+ dateViewMode: 'month' | 'year' | 'multi-year' = 'month';
114
+ @Input()
115
+ pageInfo!: PageInfo;
116
+
117
+ @Input()// @ts-ignore
118
+ fields: FieldInfo[] = [];
119
+
120
+ @Input()// @ts-ignore
121
+ errors: FieldMessage[] = [];
122
+
123
+ @Input()
124
+ workflowEditableFields: string[]=[];
125
+ @Input()
126
+ isWorkflowEditableManaged: boolean = false;
127
+
128
+ @Input()
129
+ supportingAttributes: any;
130
+
131
+ @Input()
132
+ editable: boolean = false;
133
+
134
+ @Input()
135
+ item: any = {};
136
+
137
+ _defaults: any = {};
138
+
139
+ @Output() attachmentEmitter: EventEmitter<any> = new EventEmitter<any>();
140
+
141
+ @Output() actionEmitter: EventEmitter<any> = new EventEmitter<any>();
142
+
143
+
144
+ @Output()
145
+ formUpdated: EventEmitter<FormGroup> = new EventEmitter<FormGroup>();
146
+
147
+ @Output()
148
+ hyperTextEvent: EventEmitter<boolean> = new EventEmitter();
149
+
150
+
151
+ formParam!: FormGroup;
152
+ screenFields = new Map<number, FieldInfo[]>();
153
+ removable = true;
154
+ selectable = true;
155
+ addOnBlur = true;
156
+
157
+ readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON];
158
+
159
+
160
+ public isPending: boolean = false;
161
+ public isNew: boolean = false;
162
+ itemId: number | undefined;
163
+
164
+ equationOperators : string[] = ['+','-','(' ];
165
+ @Input() equationSuggestedFields: { name: string, id: string }[] = [];
166
+ allEquationFields: BehaviorSubject<string[]>;
167
+ readonly equationValues = signal<string[]>([]);
168
+ currentEquationValue = model<string>('');
169
+
170
+ readonly equationFilteredFields = computed(() => {
171
+ const currentEquationValue = this.currentEquationValue().toLowerCase();
172
+ return this.allEquationFields.pipe(
173
+ map(fields =>
174
+ currentEquationValue ? fields?.filter(field => field.toLowerCase().includes(currentEquationValue)) : fields?.slice()
175
+ )
176
+ );
177
+ });
178
+ @ViewChild('EquationValueInput') fieldsInput: ElementRef<HTMLInputElement>;
179
+
180
+ set defaults(value: any | undefined) {
181
+ // this.backendService._defaults = value;
182
+ this._defaults = value;
183
+ this.buildForm();
184
+ // this.myCallback = value;
185
+ }
186
+
187
+ get defaults(): any | undefined {
188
+ // this.myCallback;
189
+ return this._defaults;
190
+ // return this.backendService._defaults;
191
+ }
192
+
193
+ constructor(protected translateService: TranslateService,
194
+ protected activatedRoute: ActivatedRoute,
195
+ protected backendService: BackendService,
196
+ private fb: FormBuilder,
197
+ private announcer: LiveAnnouncer) {
198
+
199
+ }
200
+
201
+ ngOnInit(): void {
202
+ if(this.item && this.item.fieldValue){
203
+ this.equationValues.update(value => this.item.fieldValue)
204
+ }
205
+ this.defaults = this.item;
206
+ this.extractLables();
207
+ this.buildForm();
208
+ this.activatedRoute.data.subscribe(data => {
209
+ this.isPending = data['mode'] === 'pending';
210
+ this.isNew = data['mode'] === 'new';
211
+ });
212
+ // this.authService.summaryPanelState$.next(Constants.SUMMARY_PANEL_CLOSED);
213
+ // this.defaults = {};
214
+ // this.invoiceQInit();
215
+ this.allEquationFields = new BehaviorSubject<string[]>([]);
216
+
217
+ this.updateEquationOptions();
218
+ }
219
+
220
+ formatTimeToDate(v: any){
221
+ const fromTime: Date = new Date();
222
+ if (v) {
223
+ let split = v.split(":");
224
+ fromTime.setHours(split[0], split[1]);
225
+ }
226
+ return new Date(fromTime.getTime());
227
+ }
228
+
229
+ patchLookupValue($event: LookupItem, fieldName: string) {
230
+ if ($event?.id !== -1 && this.defaults) {
231
+ // @ts-ignore
232
+ this.defaults[fieldName] = this.formParam.get(fieldName).value;
233
+ }
234
+ }
235
+ getBankName(fieldName: string) {
236
+ //TODO Batool do we need this here ?
237
+ if (this.formParam.get(fieldName).value?.length > 10 && !isNaN(this.formParam.get(fieldName).value) ) {
238
+ return ' / ' + this.translateService.instant('BANK.' + this.formParam.get(fieldName).value?.substr(4, 4));
239
+ } else {
240
+ return '';
241
+ }
242
+ }
243
+
244
+ patchMultiSelectValue($event: LookupItem[], fieldName: string) {
245
+ if ($event?.length >= 0 && this.defaults) {
246
+ this.defaults[fieldName] = this.formParam.get(fieldName).value;
247
+ }
248
+ }
249
+
250
+ ngOnChanges({item, errors, fields}: SimpleChanges): void {
251
+ errors?.currentValue?.forEach((msg: FieldMessage) => {
252
+ this.formParam.get(msg.fieldName)?.setErrors({serverError: msg.message});
253
+ });
254
+
255
+ if (item?.currentValue && !item.isFirstChange()){
256
+ this.defaults = item.currentValue;
257
+ }
258
+
259
+ if (fields?.currentValue && !fields.isFirstChange()){
260
+ this.buildForm();
261
+ }
262
+ }
263
+
264
+ showField(item: any, field: any) {
265
+ return (item.id || (!item.id && !field.updateOnly)) && field.visible
266
+ }
267
+
268
+ workflowEditableField(field: { property: string; }) {
269
+ const x = this.isWorkflowEditableManaged ? this.workflowEditableFields?.findIndex(d => d === field.property) > -1 : true;
270
+ return x;
271
+ }
272
+
273
+ showMultiSelectValuesAsReadonly(field: FieldInfo) {
274
+ const viewProp = this.translateService.getDefaultLang() === 'en' ? 'englishName' : 'arabicName';
275
+ return this.extractFieldName(this.defaults,field.property)?.map((a: { [x: string]: any; }) => a[viewProp]);
276
+ }
277
+
278
+ splitReadonly(values: any) {
279
+ return !values || values === '' ? []: values.split(';');
280
+ }
281
+
282
+
283
+ referenceAttributeTrue(fieldName: string, attribute: any) {
284
+ // return this.authService.referenceAttributeTrue(fieldName, this.pageInfo.processId, attribute);
285
+ }
286
+
287
+ translateLable(itemElement: any) {
288
+ return this.translateService.instant(itemElement)
289
+ }
290
+
291
+ buildForm() {
292
+ if (this.fields && this.fields.length > 0 && this.defaults) {
293
+ this.formParam = this.fb.group(buildFormFields(this.fields, this.defaults));
294
+ this.formUpdated.next(this.formParam);
295
+ }}
296
+
297
+ labelKey(column: any) {
298
+ const configuredKey = column.label ? column.label : column.property
299
+ return configuredKey.startsWith(this.pageInfo.labelsSection) ? `${configuredKey}` : `${this.pageInfo.labelsSection}.${configuredKey}`;
300
+ }
301
+
302
+ getErrors(prop: string) {
303
+
304
+ if (this.formParam.get(prop).value && this.formParam.get(prop).status !== 'VALID' && !this.formParam.get(prop).disabled) {
305
+ return this.getFirstErrorKey(prop);
306
+ // if (this.formParam.get(prop).errors?.['invalidMathExpression']) {
307
+ // return 'invalidMathExpression'
308
+ // } else {
309
+ // return this.formParam.get(prop).errors?.['serverError'] || 'INVALID_FORMAT';
310
+ // }
311
+
312
+ // return this.formParam.get(prop).errors?.find(e => typeof e !== 'undefined')?.serverError || 'INVALID_FORMAT';
313
+ }
314
+ return '';
315
+ }
316
+
317
+ getFirstErrorKey(prop: string): string {
318
+ const errors = this.formParam.get(prop)?.errors;
319
+
320
+ if (!errors || Object.keys(errors).length === 0) {
321
+ return errors?.['serverError'] || 'INVALID_FORMAT';
322
+ }
323
+
324
+ return Object.keys(errors)[0];
325
+ }
326
+
327
+ getCountryCodeList() {
328
+ return ["jo"]
329
+ }
330
+
331
+
332
+ friendlyName(fullPath: string , subPath: string , item: string){
333
+ return fullPath.substring(0, fullPath.indexOf(subPath)) + item ;
334
+ }
335
+
336
+ showValue(defaults, field){
337
+ return this.friendlyName(field.label , field.property , defaults[field.property]);
338
+ }
339
+
340
+ showError(prop: string) {
341
+ return this.formParam?.get(prop)?.value && this.formParam.get(prop).status === 'INVALID';
342
+ }
343
+
344
+ ngOnDestroy(): void {
345
+ this.defaults = null;
346
+ }
347
+
348
+ private extractLables() {
349
+ this.fields.forEach(f => {
350
+ if (f.visible) {
351
+ f.label = this.labelKey(f);
352
+
353
+ if (!this.screenFields.has(f.row)) {
354
+ this.screenFields.set(f.row, []);
355
+ }
356
+ this.screenFields.get(f.row)!.push(f);
357
+
358
+ if (f.cascadedBy) {
359
+ this.formParam?.get(f.cascadedBy)?.valueChanges.subscribe(() => {
360
+ this.formParam?.get(f.property)?.patchValue(null);
361
+ })
362
+ }
363
+ }
364
+ });
365
+
366
+ for (let i = 1; i < this.screenFields.size; i++) {
367
+ this.calcFlexSize(i);
368
+ }
369
+ // console.log(this.screenFields)
370
+ }
371
+
372
+ private calcFlexSize(i: number){
373
+ if (this.screenFields.get(i)) {
374
+ const autoSizeFields = this.screenFields.get(i).filter(f => !f.fieldSize);
375
+ const configLength = this.screenFields.get(i).filter(f => f.fieldSize > 0)
376
+ .reduce((sum, obj) => {
377
+ return sum + obj.fieldSize;
378
+ }, 0);
379
+ if (autoSizeFields.length > 0) {
380
+ const x = (100 - configLength) / autoSizeFields.length;
381
+ autoSizeFields.forEach(f => f.fieldSize = x);
382
+ }
383
+ }
384
+ }
385
+
386
+ getCurrencyPattern(field: FieldInfo) {
387
+ // const decimalPlaces = this.authService?.myCurrencies?.find(c => c.key === this.formParam.get(field.currency)?.value)?.currencyNumOfDecimalPattern || 3;
388
+ const decimalPlaces = 3;
389
+ return '^\\d*(?:[.,]\\d{1,' + decimalPlaces + '})?$';
390
+ }
391
+
392
+ splittedChips(form: FormGroup, fieldName: string):string[] {
393
+ return form.get(fieldName).value === '' ? []: form.get(fieldName).value.trim().split(';');
394
+ }
395
+
396
+
397
+ fixArabicNumbers(str: any) {
398
+ // if(typeof str === 'string') {
399
+ // str = str.replace(/([٠١٢٣٤٥٦٧٨٩])|([۰۱۲۳۴۵۶۷۸۹])/g, (m, $1, $2) => m.charCodeAt(0) - ($1 ? 1632 : 1776));
400
+ // }
401
+ // console.log(str);
402
+ }
403
+
404
+ listShowValue(defaults: any, field: FieldInfo) {
405
+ return defaults[field.property] ? this.showValue(defaults, field) : '';
406
+ }
407
+
408
+ removeChipsItem(form: FormGroup, fieldName: string, idx: number) {
409
+ const emails = this.splittedChips(form, fieldName);
410
+ if (emails.length >= 1){
411
+ emails.splice(idx,1);
412
+ }
413
+ let cleanedEmails = emails.join(";");
414
+ form.get(fieldName).setValue(cleanedEmails);
415
+ }
416
+
417
+ extractFieldName(element: any, property: string) {
418
+ if (property?.includes('.')) {
419
+ return property.split('.').reduce((acc, part) => acc && acc[part], element);
420
+ } else {
421
+ return element[property];
422
+ }
423
+ }
424
+
425
+ getMultiValue(field: FieldInfo) {
426
+ return this.formParam.get(field.property)?.value;
427
+ }
428
+
429
+ private validateEmail(email) {
430
+ var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
431
+ return re.test(String(email).toLowerCase());
432
+ }
433
+
434
+ addEmailToChips(event: MatChipInputEvent, form: FormGroup, fieldName: string) {
435
+
436
+ const input = event.input;
437
+ const value = event.value;
438
+ const items = value.split(';');
439
+ // value.split(' ');
440
+ items.forEach(itm => {
441
+ if (this.validateEmail((itm || '').trim())) {
442
+ const x = this.splittedChips(form, fieldName);
443
+ x.push(itm);
444
+ form.get(fieldName).patchValue(x.join(';'));
445
+ if (input) {
446
+ input.value = '';
447
+ }
448
+ }
449
+ });
450
+
451
+ }
452
+
453
+ extractJsonFieldName(defaults: any, property: string) {
454
+ const x= this.extractFieldName(defaults, property);
455
+ if (x?.length > 0)
456
+ return JSON.parse(x);
457
+ else return '{}';
458
+ }
459
+
460
+ getOptionValue(item: any) {
461
+ const value = typeof item === 'object' ?
462
+ this.translateService.getDefaultLang() === 'en' ? item.englishName : item.arabicName
463
+ : item;
464
+ return value;
465
+ }
466
+
467
+ getHyperTextEvent() {
468
+ this.hyperTextEvent.emit(true);
469
+ }
470
+
471
+ add(event: MatChipInputEvent): void {
472
+ const value = (event.value || '').trim();
473
+ if (value) {
474
+ if (this.equationOperators.includes(value) || !this.equationValues().includes(value)) {
475
+ this.equationValues.update(equationValues => [...equationValues, value]);
476
+ }
477
+ }
478
+
479
+ this.fieldsInput.nativeElement.value = '';
480
+ this.currentEquationValue.set('');
481
+ this.updateEquationOptions();
482
+
483
+ }
484
+
485
+ remove(item: string, index: number): void {
486
+ this.equationValues.update(equationValues => {
487
+ if (index < 0) {
488
+ return equationValues;
489
+ }
490
+
491
+ equationValues.splice(index, 1);
492
+ this.announcer.announce(`Removed ${item}`);
493
+ return [...equationValues];
494
+ });
495
+ this.updateEquationOptions();
496
+ }
497
+
498
+ selected(event: MatAutocompleteSelectedEvent): void{
499
+ const selectedValue = event.option.viewValue.trim();
500
+
501
+ if (!this.equationOperators.includes(selectedValue) && !this.equationValues().includes(selectedValue)) {
502
+ this.equationValues.update(equationValues => [...equationValues, selectedValue]);
503
+ } else if (this.equationOperators.includes(selectedValue)) {
504
+ this.equationValues.update(equationValues => [...equationValues, selectedValue]);
505
+ }
506
+
507
+ this.currentEquationValue.set('');
508
+ event.option.deselect();
509
+ this.fieldsInput.nativeElement.value = '';
510
+ this.updateEquationOptions();
511
+ }
512
+
513
+ updateEquationOptions(){
514
+ this.reflectEquationValueOnForm();
515
+
516
+ let updatedFields: string[];
517
+ if (this.equationValues().length === 0) {
518
+ updatedFields = this.getNamesFromSuggestedEquationFields();
519
+ } else {
520
+ let lastElement = this.equationValues()[this.equationValues().length - 1];
521
+ if (this.equationOperators.includes(lastElement)) {
522
+ updatedFields = this.getNamesFromSuggestedEquationFields();
523
+ } else {
524
+ updatedFields = this.equationOperators;
525
+ }
526
+ }
527
+ // console.log('*****', updatedFields);
528
+ this.allEquationFields.next(updatedFields);
529
+ }
530
+
531
+ getNamesFromSuggestedEquationFields(): string[] {
532
+ return this.equationSuggestedFields?.map(field => field.name);
533
+ }
534
+
535
+ reflectEquationValueOnForm() {
536
+ if (this.formParam && this.formParam.get('fieldValue')) {
537
+ this.formParam.get('fieldValue').setValue(this.equationValues());
538
+ } else {
539
+ // console.log('Form or fieldValue is not available.');
540
+ }
541
+ }
542
+
543
+ checkEquation(field: FieldInfo, $event: Event) {
544
+ // console.log('$event', $event);
545
+ // try {
546
+ // evaluate(equation.replace(/[a-zA-Z0-9]+/g, '1')); // Replace variables with dummy values
547
+ // this.formGroups[index].get('xyz').setErrors(null);
548
+ // console.log('valid ', equation)
549
+ // } catch (e) {
550
+ // this.formGroups[index].get('xyz').setErrors({serverError: 'incomplete '});
551
+ // console.log('bad ', equation)
552
+ // }
553
+ }
554
+
555
+ getView(field): 'month' | 'year' | 'multi-year' {
556
+ return field.pattern || 'month';
557
+ }
558
+
559
+ setMonthAndYear(normalizedMonthAndYear: Moment, picker: MatDatepicker<Moment>, field) {
560
+ console.log('field.pattern', field.pattern)
561
+ if (field.pattern === 'multi-year') {
562
+ console.log('hi')
563
+ const date = new FormControl(moment());
564
+ const ctrlValue = date.value;
565
+ ctrlValue.year(normalizedMonthAndYear.year());
566
+ ctrlValue.month(1);
567
+ ctrlValue.dayOfYear(1);
568
+ this.formParam.get(field.property).setValue(ctrlValue)
569
+ picker.close();
570
+ }
571
+ }
572
+ }
573
+
@@ -0,0 +1,42 @@
1
+ <div fxLayout="column" fxFlex="98">
2
+ <div fxLayout="row" fxLayoutAlign="start start" style="margin-top: 2vh;margin-bottom: 2vh; width: 100%">
3
+ <div fxLayout="column" fxFlex="100">
4
+ <app-title-bar [pageTitle]="getTitle()"></app-title-bar>
5
+ </div>
6
+ </div>
7
+
8
+ <ng-container *ngIf="isLoaded">
9
+ <app-base-form-canvas
10
+ [pageInfo]="pageInfo"
11
+ [fields]="fieldsInfo"
12
+ [editable]="true"
13
+ [item]="default"
14
+ (formUpdated)="captureForm($event)"></app-base-form-canvas>
15
+
16
+ <div fxLayout="row" fxLayoutAlign="start start" style="width: 100%">
17
+ <div fxLayout="column" fxFlex="49">
18
+ </div>
19
+ <div fxLayout="column" fxFlex="49">
20
+ <div align="right" style="margin: 1% 2%;">
21
+ <ng-container>
22
+ <button
23
+ mat-stroked-button class="btn-none-background-primary"
24
+ type="button"
25
+ (click)="doCancel('cancel')"
26
+ style="margin: 20px 10px;">Cancel
27
+ </button>
28
+ </ng-container>
29
+ <ng-container>
30
+ <button
31
+ [ngClass]="saveDisabled() ? 'btn-none-background-primary' : 'btn-background-primary'"
32
+ [disabled]="saveDisabled()"
33
+ mat-stroked-button
34
+ type="button"
35
+ (click)="doSave('save')">Save
36
+ </button>
37
+ </ng-container>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </ng-container>
42
+ </div>
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { BaseInputDialogComponent } from './base-input-dialog.component';
4
+
5
+ describe('BaseInputDialogComponent', () => {
6
+ let component: BaseInputDialogComponent;
7
+ let fixture: ComponentFixture<BaseInputDialogComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [BaseInputDialogComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(BaseInputDialogComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });