commons-shared-web-ui 0.0.50 → 0.0.52

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 (187) hide show
  1. package/fesm2022/commons-shared-web-ui.mjs +14557 -0
  2. package/fesm2022/commons-shared-web-ui.mjs.map +1 -0
  3. package/index.d.ts +4534 -0
  4. package/package.json +34 -53
  5. package/src/lib/styles/utilities.scss +1 -0
  6. package/.claude/settings.local.json +0 -10
  7. package/documentation/alert.md +0 -123
  8. package/documentation/button-dropdown.md +0 -126
  9. package/documentation/button.md +0 -184
  10. package/documentation/cards-usage-guidelines.md +0 -131
  11. package/documentation/configurable-form.md +0 -605
  12. package/documentation/confirmation-modal.md +0 -250
  13. package/documentation/filter-sidebar.md +0 -178
  14. package/documentation/filter-table-selector.md +0 -228
  15. package/documentation/form-builder.md +0 -597
  16. package/documentation/form-components.md +0 -384
  17. package/documentation/nav.md +0 -427
  18. package/documentation/pagination.md +0 -181
  19. package/documentation/side-nav-documentation.md +0 -169
  20. package/documentation/smart-form.md +0 -2405
  21. package/documentation/smart-table.md +0 -1221
  22. package/documentation/snackbar.md +0 -118
  23. package/documentation/style-externalization.md +0 -88
  24. package/documentation/summary-card.md +0 -279
  25. package/ng-package.json +0 -28
  26. package/src/lib/modules/alert/alert.models.ts +0 -6
  27. package/src/lib/modules/alert/alert.module.ts +0 -16
  28. package/src/lib/modules/alert/components/alert/alert.component.html +0 -27
  29. package/src/lib/modules/alert/components/alert/alert.component.scss +0 -92
  30. package/src/lib/modules/alert/components/alert/alert.component.ts +0 -81
  31. package/src/lib/modules/button/button.models.ts +0 -13
  32. package/src/lib/modules/button/button.module.ts +0 -16
  33. package/src/lib/modules/button/components/button/button.component.html +0 -22
  34. package/src/lib/modules/button/components/button/button.component.scss +0 -88
  35. package/src/lib/modules/button/components/button/button.component.ts +0 -67
  36. package/src/lib/modules/button-dropdown/button-dropdown.models.ts +0 -26
  37. package/src/lib/modules/button-dropdown/button-dropdown.module.ts +0 -22
  38. package/src/lib/modules/button-dropdown/button-dropdown.theme.scss +0 -87
  39. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.html +0 -41
  40. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.scss +0 -135
  41. package/src/lib/modules/button-dropdown/components/button-dropdown/button-dropdown.component.ts +0 -160
  42. package/src/lib/modules/configurable-form/component/configurable-form.component.html +0 -294
  43. package/src/lib/modules/configurable-form/component/configurable-form.component.scss +0 -503
  44. package/src/lib/modules/configurable-form/component/configurable-form.component.ts +0 -628
  45. package/src/lib/modules/configurable-form/configurable-form.examples.ts +0 -154
  46. package/src/lib/modules/configurable-form/configurable-form.model.ts +0 -131
  47. package/src/lib/modules/configurable-form/configurable-form.module.ts +0 -19
  48. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.html +0 -77
  49. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.scss +0 -395
  50. package/src/lib/modules/confirmation-modal/components/confirmation-modal/confirmation-modal.component.ts +0 -266
  51. package/src/lib/modules/confirmation-modal/confirmation-modal.models.ts +0 -71
  52. package/src/lib/modules/confirmation-modal/confirmation-modal.module.ts +0 -20
  53. package/src/lib/modules/filter/components/filter/filter.component.html +0 -131
  54. package/src/lib/modules/filter/components/filter/filter.component.scss +0 -245
  55. package/src/lib/modules/filter/components/filter/filter.component.ts +0 -216
  56. package/src/lib/modules/filter/filter.models.ts +0 -88
  57. package/src/lib/modules/filter/filter.module.ts +0 -24
  58. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.html +0 -112
  59. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.scss +0 -186
  60. package/src/lib/modules/filter-sidebar/components/filter-sidebar/filter-sidebar.component.ts +0 -163
  61. package/src/lib/modules/filter-sidebar/filter-sidebar.models.ts +0 -95
  62. package/src/lib/modules/filter-sidebar/filter-sidebar.module.ts +0 -24
  63. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.html +0 -73
  64. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.scss +0 -321
  65. package/src/lib/modules/filter-table-selector/components/filter-table-selector/filter-table-selector.component.ts +0 -361
  66. package/src/lib/modules/filter-table-selector/filter-table-selector.models.ts +0 -91
  67. package/src/lib/modules/filter-table-selector/filter-table-selector.module.ts +0 -22
  68. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.html +0 -63
  69. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.scss +0 -496
  70. package/src/lib/modules/form-builder/components/field-configurator/configurator-config-panel/configurator-config-panel.component.ts +0 -445
  71. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.html +0 -75
  72. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.scss +0 -210
  73. package/src/lib/modules/form-builder/components/field-configurator/configurator-tree/configurator-tree.component.ts +0 -55
  74. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.html +0 -25
  75. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.scss +0 -82
  76. package/src/lib/modules/form-builder/components/field-configurator/field-configurator.component.ts +0 -95
  77. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.html +0 -20
  78. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.scss +0 -37
  79. package/src/lib/modules/form-builder/components/field-selection/field-selection.component.ts +0 -94
  80. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.html +0 -46
  81. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.scss +0 -102
  82. package/src/lib/modules/form-builder/components/field-selection/group-node/group-node.component.ts +0 -50
  83. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.html +0 -35
  84. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.scss +0 -67
  85. package/src/lib/modules/form-builder/components/field-selection/selection-field-node/selection-field-node.component.ts +0 -34
  86. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.html +0 -68
  87. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.scss +0 -113
  88. package/src/lib/modules/form-builder/components/field-selection/selection-section-node/selection-section-node.component.ts +0 -74
  89. package/src/lib/modules/form-builder/configs/field-type-schema.map.ts +0 -533
  90. package/src/lib/modules/form-builder/form-builder.module.ts +0 -36
  91. package/src/lib/modules/form-builder/index.ts +0 -9
  92. package/src/lib/modules/form-builder/models/builder.models.ts +0 -7
  93. package/src/lib/modules/form-builder/models/field-configurator.models.ts +0 -38
  94. package/src/lib/modules/form-builder/models/field-selection.models.ts +0 -51
  95. package/src/lib/modules/form-builder/services/field-configurator.service.ts +0 -258
  96. package/src/lib/modules/form-builder/services/field-selection.service.ts +0 -299
  97. package/src/lib/modules/form-builder/services/form-schema-tree.service.ts +0 -670
  98. package/src/lib/modules/form-builder/tokens/builder.tokens.ts +0 -10
  99. package/src/lib/modules/form-builder/utils/constants.ts +0 -43
  100. package/src/lib/modules/form-components/components/checkbox/checkbox.component.html +0 -29
  101. package/src/lib/modules/form-components/components/checkbox/checkbox.component.scss +0 -111
  102. package/src/lib/modules/form-components/components/checkbox/checkbox.component.ts +0 -207
  103. package/src/lib/modules/form-components/components/checkbox/checkbox.models.ts +0 -35
  104. package/src/lib/modules/form-components/components/datepicker/datepicker.component.html +0 -42
  105. package/src/lib/modules/form-components/components/datepicker/datepicker.component.scss +0 -115
  106. package/src/lib/modules/form-components/components/datepicker/datepicker.component.ts +0 -267
  107. package/src/lib/modules/form-components/components/datepicker/datepicker.models.ts +0 -45
  108. package/src/lib/modules/form-components/components/dropdown/dropdown.component.html +0 -74
  109. package/src/lib/modules/form-components/components/dropdown/dropdown.component.scss +0 -252
  110. package/src/lib/modules/form-components/components/dropdown/dropdown.component.ts +0 -377
  111. package/src/lib/modules/form-components/components/dropdown/dropdown.models.ts +0 -53
  112. package/src/lib/modules/form-components/components/input/input.component.html +0 -51
  113. package/src/lib/modules/form-components/components/input/input.component.scss +0 -128
  114. package/src/lib/modules/form-components/components/input/input.component.ts +0 -250
  115. package/src/lib/modules/form-components/components/input/input.models.ts +0 -55
  116. package/src/lib/modules/form-components/components/radio/radio.component.html +0 -22
  117. package/src/lib/modules/form-components/components/radio/radio.component.scss +0 -107
  118. package/src/lib/modules/form-components/components/radio/radio.component.ts +0 -181
  119. package/src/lib/modules/form-components/components/radio/radio.models.ts +0 -39
  120. package/src/lib/modules/form-components/components/search/search.component.html +0 -15
  121. package/src/lib/modules/form-components/components/search/search.component.scss +0 -87
  122. package/src/lib/modules/form-components/components/search/search.component.ts +0 -213
  123. package/src/lib/modules/form-components/components/search/search.models.ts +0 -40
  124. package/src/lib/modules/form-components/components/toggle/toggle.component.html +0 -15
  125. package/src/lib/modules/form-components/components/toggle/toggle.component.scss +0 -81
  126. package/src/lib/modules/form-components/components/toggle/toggle.component.ts +0 -166
  127. package/src/lib/modules/form-components/components/toggle/toggle.models.ts +0 -27
  128. package/src/lib/modules/form-components/directives/click-outside.directive.ts +0 -22
  129. package/src/lib/modules/form-components/form-components.module.ts +0 -41
  130. package/src/lib/modules/material/material.module.ts +0 -94
  131. package/src/lib/modules/nav/components/nav/nav.component.html +0 -34
  132. package/src/lib/modules/nav/components/nav/nav.component.scss +0 -171
  133. package/src/lib/modules/nav/components/nav/nav.component.ts +0 -82
  134. package/src/lib/modules/nav/nav.models.ts +0 -31
  135. package/src/lib/modules/nav/nav.module.ts +0 -17
  136. package/src/lib/modules/pagination/components/pagination/pagination.component.html +0 -52
  137. package/src/lib/modules/pagination/components/pagination/pagination.component.scss +0 -155
  138. package/src/lib/modules/pagination/components/pagination/pagination.component.ts +0 -109
  139. package/src/lib/modules/pagination/pagination.module.ts +0 -17
  140. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.html +0 -56
  141. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.scss +0 -342
  142. package/src/lib/modules/side-nav/components/side-nav/side-nav.component.ts +0 -135
  143. package/src/lib/modules/side-nav/side-nav.models.ts +0 -38
  144. package/src/lib/modules/side-nav/side-nav.module.ts +0 -16
  145. package/src/lib/modules/smart-form/components/form-field/form-field.component.html +0 -1196
  146. package/src/lib/modules/smart-form/components/form-field/form-field.component.scss +0 -2014
  147. package/src/lib/modules/smart-form/components/form-field/form-field.component.ts +0 -2525
  148. package/src/lib/modules/smart-form/components/form-section/form-section.component.html +0 -65
  149. package/src/lib/modules/smart-form/components/form-section/form-section.component.scss +0 -209
  150. package/src/lib/modules/smart-form/components/form-section/form-section.component.ts +0 -131
  151. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.html +0 -253
  152. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.scss +0 -689
  153. package/src/lib/modules/smart-form/components/smart-form/smart-form.component.ts +0 -1124
  154. package/src/lib/modules/smart-form/index.ts +0 -10
  155. package/src/lib/modules/smart-form/models/form-schema.model.ts +0 -733
  156. package/src/lib/modules/smart-form/models/hierarchy-config.model.ts +0 -21
  157. package/src/lib/modules/smart-form/services/expression.service.ts +0 -75
  158. package/src/lib/modules/smart-form/services/smart-form-controller.service.ts +0 -65
  159. package/src/lib/modules/smart-form/smart-form.examples.ts +0 -1324
  160. package/src/lib/modules/smart-form/smart-form.module.ts +0 -36
  161. package/src/lib/modules/smart-form/utils/translation.utils.ts +0 -82
  162. package/src/lib/modules/smart-form/utils/trusted-url.pipe.ts +0 -25
  163. package/src/lib/modules/smart-form/utils/validation.utils.ts +0 -98
  164. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.html +0 -283
  165. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.scss +0 -685
  166. package/src/lib/modules/smart-table/components/smart-table/smart-table.component.ts +0 -1128
  167. package/src/lib/modules/smart-table/models/table-config.model.ts +0 -207
  168. package/src/lib/modules/smart-table/smart-table.module.ts +0 -30
  169. package/src/lib/modules/smart-table/utils/safe-html.pipe.ts +0 -28
  170. package/src/lib/modules/smart-table/utils/smart-table.utils.ts +0 -18
  171. package/src/lib/modules/snackbar/components/snackbar.component.html +0 -41
  172. package/src/lib/modules/snackbar/components/snackbar.component.scss +0 -99
  173. package/src/lib/modules/snackbar/components/snackbar.component.ts +0 -18
  174. package/src/lib/modules/snackbar/models/snackbar.models.ts +0 -10
  175. package/src/lib/modules/snackbar/services/snackbar.service.ts +0 -40
  176. package/src/lib/modules/snackbar/snackbar.module.ts +0 -11
  177. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.html +0 -47
  178. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.scss +0 -199
  179. package/src/lib/modules/summary-card/components/summary-card/summary-card.component.ts +0 -126
  180. package/src/lib/modules/summary-card/summary-card.module.ts +0 -18
  181. package/src/lib/shared-ui.module.ts +0 -44
  182. package/src/lib/utils/constants.ts +0 -11
  183. package/src/lib/utils/storage.utils.ts +0 -37
  184. package/src/lib/utils/string.utils.ts +0 -23
  185. package/src/lib/utils/translation.utils.ts +0 -87
  186. package/src/public-api.ts +0 -104
  187. package/tsconfig.lib.json +0 -15
@@ -1,628 +0,0 @@
1
- import { Component, EventEmitter, Input, OnInit, Output, OnChanges, SimpleChanges } from '@angular/core';
2
- import { FormBuilder, FormGroup, FormControl, FormArray, Validators, AbstractControl, ReactiveFormsModule } from '@angular/forms';
3
- import { MatSnackBar } from '@angular/material/snack-bar';
4
- import { HttpClient } from '@angular/common/http';
5
- import {
6
- FormConfig,
7
- FormField,
8
- FormSection,
9
- FormOption,
10
- JsonFormConfig,
11
- JsonFieldConfig,
12
- FieldType,
13
- UISubType
14
- } from '../configurable-form.model';
15
- import { CommonModule } from '@angular/common';
16
- import { MaterialModule } from '../../material/material.module';
17
- import { translateConfig } from '../../../utils/translation.utils';
18
-
19
- @Component({
20
- selector: 'lib-configurable-form',
21
- templateUrl: './configurable-form.component.html',
22
- styleUrls: ['./configurable-form.component.scss'],
23
- standalone: true,
24
- imports: [CommonModule, ReactiveFormsModule, MaterialModule],
25
- })
26
- export class ConfigurableFormComponent implements OnInit, OnChanges {
27
- @Input() config!: FormConfig;
28
- @Input() jsonConfig!: JsonFormConfig;
29
- @Input() data: any = {};
30
- @Input() baseApiUrl: string = '';
31
- @Input() labels: any;
32
- @Output() optionsLoad = new EventEmitter<any>();
33
-
34
- form!: FormGroup;
35
- processedConfig!: FormConfig;
36
- fieldVisibilityMap: Map<string, boolean> = new Map();
37
- passwordFieldState: Map<string, boolean> = new Map();
38
-
39
- constructor(
40
- private fb: FormBuilder,
41
- private snackBar: MatSnackBar,
42
- private http: HttpClient
43
- ) { }
44
-
45
- ngOnInit(): void {
46
- this.initializeForm();
47
- }
48
-
49
- ngOnChanges(changes: SimpleChanges): void {
50
- if (changes['config'] || changes['jsonConfig']) {
51
- this.initializeForm();
52
- }
53
- if (changes['data'] && this.form) {
54
- this.form.patchValue(this.data);
55
- }
56
- }
57
-
58
- initializeForm() {
59
- // Transform JSON config if provided, otherwise use config directly
60
- if (this.jsonConfig) {
61
- this.processedConfig = this.transformJsonConfig(this.jsonConfig);
62
- } else if (this.config) {
63
- this.processedConfig = JSON.parse(JSON.stringify(this.config));
64
- } else {
65
- return;
66
- }
67
-
68
- // Apply translations if labels and labelsObject are provided
69
- if (this.labels && this.labels.labelsObject) {
70
- translateConfig(this.processedConfig, this.labels.labelsObject);
71
- }
72
-
73
-
74
- this.normalizeFields();
75
- this.initializeFieldVisibility();
76
- this.buildForm();
77
- this.setupDependencies();
78
-
79
- // Patch initial data if provided
80
- if (this.data && Object.keys(this.data).length > 0) {
81
- this.form.patchValue(this.data);
82
- }
83
- }
84
-
85
- // Transform JSON config format to internal FormConfig format
86
- transformJsonConfig(jsonConfig: JsonFormConfig): FormConfig {
87
- const fields = jsonConfig.jsonConfig
88
- .sort((a, b) => a.sequence - b.sequence)
89
- .map(field => this.transformJsonField(field));
90
-
91
- return {
92
- sections: [{
93
- sectionTitle: jsonConfig.label,
94
- fields: fields
95
- }],
96
- entityType: jsonConfig.entityType
97
- };
98
- }
99
-
100
- // Transform individual JSON field to FormField
101
- transformJsonField(jsonField: JsonFieldConfig): FormField {
102
- const fieldType = this.mapUISubTypeToFieldType(jsonField.uiConfig.subType);
103
-
104
- return {
105
- name: jsonField.jsonKey,
106
- jsonKey: jsonField.jsonKey,
107
- label: jsonField.label,
108
- type: fieldType,
109
- sequence: jsonField.sequence,
110
- keyType: jsonField.keyType,
111
- uiConfig: jsonField.uiConfig,
112
- validationRules: jsonField.validationRules,
113
- required: jsonField.validationRules?.isMandatory || jsonField.validationRules?.isRequired,
114
- mandatory: jsonField.validationRules?.isMandatory,
115
- dependsOn: undefined, // Will be set based on dependent array
116
- dependent: jsonField.uiConfig.dependent,
117
- optionConfigs: jsonField.uiConfig.optionConfigs,
118
- class: 'col-12'
119
- };
120
- }
121
-
122
- // Map UI subtype to field type
123
- mapUISubTypeToFieldType(subType?: string): FieldType {
124
- switch (subType) {
125
- case 'UI_SUBTYPE.SHORT_TEXT':
126
- return 'text';
127
- case 'UI_SUBTYPE.LONG_TEXT':
128
- return 'textarea';
129
- case 'UI_SUBTYPE.NUMBER':
130
- return 'number';
131
- case 'UI_SUBTYPE.EMAIL':
132
- return 'email';
133
- case 'UI_SUBTYPE.PHONE':
134
- return 'tel';
135
- case 'UI_SUBTYPE.URL':
136
- return 'url';
137
- default:
138
- return 'text';
139
- }
140
- }
141
-
142
- // Normalize fields to ensure all required properties exist
143
- normalizeFields() {
144
- this.processedConfig.sections.forEach(section => {
145
- section.fields.forEach(field => {
146
- // Set default type if not specified
147
- if (!field.type) {
148
- field.type = 'text';
149
- }
150
-
151
- // Merge uiConfig with field-level properties
152
- if (field.uiConfig) {
153
- if (field.uiConfig.type === 'UI_TYPE.DROP_DOWN') {
154
- field.type = 'dropdown';
155
- }
156
- if (field.uiConfig.optionConfigs) {
157
- field.optionConfigs = field.uiConfig.optionConfigs;
158
- }
159
- if (field.uiConfig.dependent) {
160
- field.dependent = field.uiConfig.dependent;
161
- }
162
- }
163
-
164
- // Initialize visibility
165
- if (field.visible === undefined) {
166
- field.visible = true;
167
- }
168
-
169
- // Load options for dropdowns
170
- if ((field.type === 'dropdown' || field.type === 'select') && field.optionConfigs) {
171
- this.loadFieldOptions(field);
172
- }
173
- });
174
- });
175
- }
176
-
177
- // Initialize field visibility map
178
- initializeFieldVisibility() {
179
- this.processedConfig.sections.forEach(section => {
180
- section.fields.forEach(field => {
181
- this.fieldVisibilityMap.set(field.name, field.visible !== false);
182
- });
183
- });
184
- }
185
-
186
- buildForm() {
187
- const formGroupConfig: any = {};
188
-
189
- this.processedConfig.sections.forEach(section => {
190
- if (section.isRepeater) {
191
- // Create FormArray for repeater sections
192
- const arrayName = section.formArrayName || 'items';
193
- const minItems = section.minItems || 1;
194
- const initialItems = [];
195
-
196
- for (let i = 0; i < minItems; i++) {
197
- initialItems.push(this.createGroup(section.fields));
198
- }
199
-
200
- formGroupConfig[arrayName] = this.fb.array(initialItems);
201
- } else {
202
- // Add regular fields to form group
203
- section.fields.forEach(field => {
204
- if (field.subFields) {
205
- // Composite field - add all sub-fields
206
- field.subFields.forEach(subField => {
207
- if (field.required || field.mandatory) {
208
- subField.required = true;
209
- }
210
- formGroupConfig[subField.name] = this.createControl(subField);
211
- });
212
- } else {
213
- formGroupConfig[field.name] = this.createControl(field);
214
- }
215
- });
216
- }
217
- });
218
-
219
- this.form = this.fb.group(formGroupConfig);
220
-
221
- // Apply composite validators to the root form group
222
- this.processedConfig.sections.forEach(section => {
223
- if (!section.isRepeater) {
224
- section.fields.forEach(field => {
225
- if (field.type === 'composite' && field.compositeValidationRule && field.subFields) {
226
- this.form.addValidators(this.createCompositeValidator(field));
227
- }
228
- });
229
- }
230
- });
231
- this.form.updateValueAndValidity();
232
- }
233
-
234
- createCompositeValidator(field: FormField) {
235
- return (control: AbstractControl) => {
236
- const group = control as FormGroup;
237
- if (!field.subFields || field.subFields.length < 2) return null;
238
-
239
- if (field.compositeValidationRule === 'minMax') {
240
- const minControl = group.get(field.subFields[0].name);
241
- const maxControl = group.get(field.subFields[1].name);
242
-
243
- if (minControl && maxControl && minControl.value !== null && maxControl.value !== null) {
244
- if (Number(minControl.value) > Number(maxControl.value)) {
245
- return { [`invalid_minMax_${field.name}`]: true };
246
- }
247
- }
248
- }
249
-
250
- if (field.compositeValidationRule === 'percentageTotal') {
251
- let total = 0;
252
- let allPresent = true;
253
-
254
- field.subFields.forEach(sub => {
255
- const ctrl = group.get(sub.name);
256
- if (ctrl && ctrl.value !== null && ctrl.value !== '') {
257
- total += Number(ctrl.value);
258
- } else {
259
- allPresent = false;
260
- }
261
- });
262
-
263
- if (allPresent && total !== 100) {
264
- return { [`invalid_percentageTotal_${field.name}`]: true };
265
- }
266
- }
267
-
268
- return null;
269
- };
270
- }
271
-
272
- createControl(field: FormField): FormControl {
273
- const validators = [];
274
-
275
- // Add validators based on field configuration
276
- if (field.required || field.mandatory || field.validationRules?.isMandatory || field.validationRules?.isRequired) {
277
- validators.push(Validators.required);
278
- }
279
-
280
- if (field.validationRules?.minLength) {
281
- validators.push(Validators.minLength(field.validationRules.minLength));
282
- }
283
-
284
- if (field.validationRules?.maxLength) {
285
- validators.push(Validators.maxLength(field.validationRules.maxLength));
286
- }
287
-
288
- if (field.validationRules?.pattern) {
289
- validators.push(Validators.pattern(field.validationRules.pattern));
290
- }
291
-
292
- if (field.validationRules?.min !== undefined) {
293
- validators.push(Validators.min(field.validationRules.min));
294
- }
295
-
296
- if (field.validationRules?.max !== undefined) {
297
- validators.push(Validators.max(field.validationRules.max));
298
- }
299
-
300
- if (field.type === 'email') {
301
- validators.push(Validators.email);
302
- }
303
-
304
- const initialValue = field.value !== undefined ? field.value : '';
305
- return this.fb.control({ value: initialValue, disabled: field.disabled || false }, validators);
306
- }
307
-
308
- createGroup(fields: FormField[]): FormGroup {
309
- const groupConfig: any = {};
310
-
311
- fields.forEach(field => {
312
- if (field.subFields) {
313
- field.subFields.forEach(subField => {
314
- groupConfig[subField.name] = this.createControl(subField);
315
- });
316
- } else {
317
- groupConfig[field.name] = this.createControl(field);
318
- }
319
- });
320
-
321
- return this.fb.group(groupConfig);
322
- }
323
-
324
- getFormArray(name: string): FormArray {
325
- return this.form.get(name) as FormArray;
326
- }
327
-
328
- addRepeaterItem(section: FormSection) {
329
- const arrayName = section.formArrayName || 'items';
330
- const formArray = this.getFormArray(arrayName);
331
-
332
- // Check max items
333
- if (section.maxItems && formArray.length >= section.maxItems) {
334
- this.snackBar.open(this.labels.errorMaxItemsAllowed.replace('{0}', String(section.maxItems)), this.labels.closeSnackBar, { duration: 3000 });
335
- return;
336
- }
337
-
338
- formArray.push(this.createGroup(section.fields));
339
- }
340
-
341
- removeRepeaterItem(sectionName: string, index: number) {
342
- const formArray = this.getFormArray(sectionName);
343
- formArray.removeAt(index);
344
- }
345
-
346
- validate(): boolean {
347
- if (this.form.invalid) {
348
- this.form.markAllAsTouched();
349
- this.scrollToFirstInvalidControl();
350
- return false;
351
- }
352
- return true;
353
- }
354
-
355
- scrollToFirstInvalidControl() {
356
- const firstInvalidControl = document.querySelector('.is-invalid');
357
- if (firstInvalidControl) {
358
- firstInvalidControl.scrollIntoView({ behavior: 'smooth', block: 'center' });
359
- }
360
- }
361
-
362
- setupDependencies() {
363
- this.processedConfig.sections.forEach(section => {
364
- section.fields.forEach(field => {
365
-
366
-
367
- // Also setup for fields with dependent array
368
- if (field.dependent && field.dependent.length > 0) {
369
- const control = this.form.get(field.name);
370
- if (control) {
371
- control.valueChanges.subscribe(value => {
372
- this.onFieldValueChange(field, value);
373
- });
374
- }
375
- }
376
- });
377
- });
378
- }
379
-
380
- onFieldValueChange(field: FormField, value: any) {
381
- // Handle dependent fields
382
- if (field.dependent && field.dependent.length > 0) {
383
- field.dependent.forEach(dependentFieldName => {
384
- const dependentField = this.findFieldByName(dependentFieldName);
385
- if (dependentField) {
386
- // Clear the dependent field value
387
- const control = this.form.get(dependentFieldName);
388
- if (control) {
389
- control.setValue('');
390
- control.markAsUntouched();
391
- }
392
-
393
- // Load new options for the dependent field
394
- if (value) {
395
- this.loadFieldOptions(dependentField, { [field.name]: value });
396
- } else {
397
- // Clear options if parent value is cleared
398
- dependentField.loadedOptions = [];
399
- }
400
- }
401
- });
402
- }
403
- }
404
-
405
- // Load options for a dropdown field
406
- loadFieldOptions(field: FormField, parentValues?: any) {
407
- // Emit event for parent to notify about options load request
408
- // Allow parent to mark as handled to skip internal API call
409
- const event = { field, parentValue: parentValues, handled: false };
410
- this.optionsLoad.emit(event);
411
-
412
- if (event.handled) {
413
- return;
414
- }
415
-
416
- if (!field.optionConfigs) {
417
- return;
418
- }
419
-
420
- const config = field.optionConfigs;
421
-
422
- // Handle static options
423
- if (config.optionDTO === 'OPTION_DTO.STATIC' && config.staticOptions) {
424
- field.loadedOptions = config.staticOptions;
425
- return;
426
- }
427
-
428
- // Handle API-based options
429
- if (config.optionDTO === 'OPTION_DTO.REF_DATA' && config.url) {
430
- let url = config.url;
431
-
432
- // Replace placeholders in URL with parent values
433
- if (parentValues) {
434
- Object.keys(parentValues).forEach(key => {
435
- url = url.replace(`{${key}}`, parentValues[key]);
436
- });
437
- }
438
-
439
- // Prepend base API URL if provided
440
- if (this.baseApiUrl && !url.startsWith('http')) {
441
- url = `${this.baseApiUrl}/${url}`;
442
- }
443
-
444
- this.http.get<any>(url).subscribe({
445
- next: (response) => {
446
- // Extract data from response
447
- const data = response.data || response.content || response;
448
- field.loadedOptions = this.extractOptions(data, config);
449
- },
450
- error: (error) => {
451
- console.error('Error loading options:', error);
452
- field.loadedOptions = [];
453
- }
454
- });
455
- }
456
- }
457
-
458
- // Extract options from API response
459
- extractOptions(data: any[], config: any): FormOption[] {
460
- if (!Array.isArray(data)) {
461
- return [];
462
- }
463
-
464
- return data.map(item => ({
465
- label: item[config.labelKey || 'name'],
466
- value: item[config.requestKey || 'code'] || item[config.valueKey || 'id'],
467
- code: item.code,
468
- name: item.name
469
- }));
470
- }
471
-
472
- // Get options for a field (either static or loaded)
473
- getFieldOptions(field: FormField): FormOption[] {
474
- return field.loadedOptions || field.options || [];
475
- }
476
-
477
- // Check if field is visible
478
- isFieldVisible(field: FormField): boolean {
479
- return this.fieldVisibilityMap.get(field.name) !== false;
480
- }
481
-
482
- // Toggle field visibility
483
- toggleFieldVisibility(field: FormField, visible: boolean) {
484
- this.fieldVisibilityMap.set(field.name, visible);
485
-
486
- const control = this.form.get(field.name);
487
- if (control) {
488
- if (visible) {
489
- // Re-enable and restore validators
490
- control.enable();
491
- this.updateControlValidators(control, field);
492
- } else {
493
- // Disable and clear validators
494
- control.disable();
495
- control.clearValidators();
496
- control.updateValueAndValidity();
497
- }
498
- }
499
- }
500
-
501
- // Update control validators based on field config
502
- updateControlValidators(control: AbstractControl, field: FormField) {
503
- const validators = [];
504
-
505
- if (field.required || field.mandatory || field.validationRules?.isMandatory) {
506
- validators.push(Validators.required);
507
- }
508
-
509
- if (field.validationRules?.minLength) {
510
- validators.push(Validators.minLength(field.validationRules.minLength));
511
- }
512
-
513
- if (field.validationRules?.maxLength) {
514
- validators.push(Validators.maxLength(field.validationRules.maxLength));
515
- }
516
-
517
- if (field.validationRules?.pattern) {
518
- validators.push(Validators.pattern(field.validationRules.pattern));
519
- }
520
-
521
- control.setValidators(validators);
522
- control.updateValueAndValidity();
523
- }
524
-
525
- onFileChange(event: any, field: FormField) {
526
- const files: FileList = event.target.files;
527
-
528
- if (!files || files.length === 0) {
529
- return;
530
- }
531
-
532
- // Initialize uploadedFiles if not present
533
- // Initialize uploadedFiles if not present
534
- if (!field.uploadedFiles) {
535
- field.uploadedFiles = [];
536
- }
537
-
538
- const uploadedFiles: any[] = [];
539
- // Handle files
540
- for (let i = 0; i < files.length; i++) {
541
- const file = files[i];
542
-
543
- // Check file size (5MB limit)
544
- if (file.size > 5 * 1024 * 1024) {
545
- this.snackBar.open(this.labels.errorFileLimitExceeded.replace('{0}', file.name), this.labels.closeSnackBar, { duration: 3000 });
546
- continue;
547
- }
548
-
549
- uploadedFiles.push({
550
- name: file.name,
551
- size: file.size,
552
- type: file.type,
553
- file: file
554
- });
555
- }
556
-
557
- if (field.multiple) {
558
- field.uploadedFiles.push(...uploadedFiles);
559
- } else {
560
- field.uploadedFiles = uploadedFiles;
561
- }
562
-
563
- // Update form control value for validation
564
- this.updateFileControlValue(field);
565
-
566
- // Clear the input
567
- event.target.value = '';
568
- }
569
-
570
- // Remove uploaded file
571
- removeFile(field: FormField, index: number) {
572
- if (field.uploadedFiles) {
573
- field.uploadedFiles.splice(index, 1);
574
- this.updateFileControlValue(field);
575
- }
576
- }
577
-
578
- // Update file control value for validation
579
- updateFileControlValue(field: FormField) {
580
- const control = this.form.get(field.name);
581
- if (control) {
582
- const hasFiles = field.uploadedFiles && field.uploadedFiles.length > 0;
583
- control.setValue(hasFiles ? field.uploadedFiles : null);
584
- control.markAsTouched();
585
- }
586
- }
587
-
588
- // Get character count for text field
589
- getCharacterCount(fieldName: string): number {
590
- const control = this.form.get(fieldName);
591
- if (control && control.value) {
592
- return control.value.toString().length;
593
- }
594
- return 0;
595
- }
596
-
597
- // Toggle section collapse
598
- toggleSection(section: FormSection) {
599
- section.collapsed = !section.collapsed;
600
- }
601
-
602
-
603
-
604
- // Helper method to find field by name
605
- private findFieldByName(name: string): FormField | undefined {
606
- for (const section of this.processedConfig.sections) {
607
- const field = section.fields.find(f => f.name === name);
608
- if (field) {
609
- return field;
610
- }
611
- }
612
- return undefined;
613
- }
614
-
615
- // Get the processed config for template use
616
- get sections(): FormSection[] {
617
- return this.processedConfig?.sections || [];
618
- }
619
-
620
- togglePassword(fieldName: string) {
621
- this.passwordFieldState.set(fieldName, !this.passwordFieldState.get(fieldName));
622
- }
623
-
624
- isPasswordVisible(fieldName: string): boolean {
625
- return this.passwordFieldState.get(fieldName) || false;
626
- }
627
- }
628
-