@masterteam/form-builder 0.0.10 → 0.0.12
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.
|
@@ -27,7 +27,7 @@ import { CrudStateBase, handleApiRequest, RadioCardsFieldConfig } from '@mastert
|
|
|
27
27
|
import { DynamicForm } from '@masterteam/forms/dynamic-form';
|
|
28
28
|
import { ToggleField } from '@masterteam/components/toggle-field';
|
|
29
29
|
import { ModalRef } from '@masterteam/components/dialog';
|
|
30
|
-
import { FormulaToolbar, FormulaEditor, serializeTokens } from '@masterteam/components/formula';
|
|
30
|
+
import { CONDITION_FUNCTION_CATEGORIES, CONDITION_OPERATORS, FormulaToolbar, FormulaEditor, VALIDATION_FUNCTION_CATEGORIES, VALIDATION_OPERATORS, serializeTokens } from '@masterteam/components/formula';
|
|
31
31
|
import { Tooltip } from '@masterteam/components/tooltip';
|
|
32
32
|
import { ClientForm } from '@masterteam/forms/client-form';
|
|
33
33
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
@@ -79,6 +79,13 @@ class GetFormConfiguration {
|
|
|
79
79
|
class ResetFormConfiguration {
|
|
80
80
|
static type = '[FormBuilder] Reset Form Configuration';
|
|
81
81
|
}
|
|
82
|
+
class UpdateFormSettings {
|
|
83
|
+
payload;
|
|
84
|
+
static type = '[FormBuilder] Update Form Settings';
|
|
85
|
+
constructor(payload) {
|
|
86
|
+
this.payload = payload;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
82
89
|
// ============================================================================
|
|
83
90
|
// Section Actions
|
|
84
91
|
// ============================================================================
|
|
@@ -201,6 +208,7 @@ var FormBuilderActionKey;
|
|
|
201
208
|
// Form Configuration
|
|
202
209
|
FormBuilderActionKey["GetFormConfiguration"] = "getFormConfiguration";
|
|
203
210
|
FormBuilderActionKey["ResetFormConfiguration"] = "resetFormConfiguration";
|
|
211
|
+
FormBuilderActionKey["UpdateFormSettings"] = "updateFormSettings";
|
|
204
212
|
// Section CRUD
|
|
205
213
|
FormBuilderActionKey["AddSection"] = "addSection";
|
|
206
214
|
FormBuilderActionKey["UpdateSection"] = "updateSection";
|
|
@@ -252,6 +260,15 @@ let FormBuilderState = class FormBuilderState extends CrudStateBase {
|
|
|
252
260
|
const { parentPath, moduleType, moduleId } = state;
|
|
253
261
|
return `${this.baseUrl}${parentPath}/${moduleType}/${moduleId}`;
|
|
254
262
|
}
|
|
263
|
+
normalizeFormConfiguration(config) {
|
|
264
|
+
if (!config)
|
|
265
|
+
return null;
|
|
266
|
+
return {
|
|
267
|
+
...config,
|
|
268
|
+
renderMode: config.renderMode ?? 'sections',
|
|
269
|
+
validations: config.validations ?? [],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
255
272
|
// ============================================================================
|
|
256
273
|
// Selectors
|
|
257
274
|
// ============================================================================
|
|
@@ -331,9 +348,7 @@ let FormBuilderState = class FormBuilderState extends CrudStateBase {
|
|
|
331
348
|
key: FormBuilderActionKey.GetFormConfiguration,
|
|
332
349
|
request$: req$,
|
|
333
350
|
updateState: (_state, data) => ({
|
|
334
|
-
formConfiguration: data
|
|
335
|
-
? { ...data, validations: data.validations ?? [] }
|
|
336
|
-
: null,
|
|
351
|
+
formConfiguration: this.normalizeFormConfiguration(data),
|
|
337
352
|
}),
|
|
338
353
|
});
|
|
339
354
|
}
|
|
@@ -346,9 +361,33 @@ let FormBuilderState = class FormBuilderState extends CrudStateBase {
|
|
|
346
361
|
key: FormBuilderActionKey.ResetFormConfiguration,
|
|
347
362
|
request$: req$,
|
|
348
363
|
onSuccess: (res, _currentState) => ({
|
|
349
|
-
formConfiguration: res.data
|
|
350
|
-
|
|
351
|
-
|
|
364
|
+
formConfiguration: this.normalizeFormConfiguration(res.data),
|
|
365
|
+
}),
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
updateFormSettings(ctx, action) {
|
|
369
|
+
const state = ctx.getState();
|
|
370
|
+
const currentConfig = state.formConfiguration;
|
|
371
|
+
if (!currentConfig)
|
|
372
|
+
return;
|
|
373
|
+
const optimisticConfig = this.normalizeFormConfiguration({
|
|
374
|
+
...currentConfig,
|
|
375
|
+
...action.payload,
|
|
376
|
+
});
|
|
377
|
+
const apiPath = `${this.getApiPath(state)}/settings`;
|
|
378
|
+
const req$ = this.http.patch(apiPath, action.payload);
|
|
379
|
+
ctx.patchState({
|
|
380
|
+
formConfiguration: optimisticConfig,
|
|
381
|
+
});
|
|
382
|
+
return handleApiRequest({
|
|
383
|
+
ctx,
|
|
384
|
+
key: FormBuilderActionKey.UpdateFormSettings,
|
|
385
|
+
request$: req$,
|
|
386
|
+
onSuccess: (res) => ({
|
|
387
|
+
formConfiguration: this.normalizeFormConfiguration(res.data) ?? optimisticConfig,
|
|
388
|
+
}),
|
|
389
|
+
onError: () => ({
|
|
390
|
+
formConfiguration: currentConfig,
|
|
352
391
|
}),
|
|
353
392
|
});
|
|
354
393
|
}
|
|
@@ -844,6 +883,9 @@ __decorate([
|
|
|
844
883
|
__decorate([
|
|
845
884
|
Action(ResetFormConfiguration)
|
|
846
885
|
], FormBuilderState.prototype, "resetFormConfiguration", null);
|
|
886
|
+
__decorate([
|
|
887
|
+
Action(UpdateFormSettings)
|
|
888
|
+
], FormBuilderState.prototype, "updateFormSettings", null);
|
|
847
889
|
__decorate([
|
|
848
890
|
Action(AddSection)
|
|
849
891
|
], FormBuilderState.prototype, "addSection", null);
|
|
@@ -921,7 +963,7 @@ FormBuilderState = __decorate([
|
|
|
921
963
|
], FormBuilderState);
|
|
922
964
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormBuilderState, decorators: [{
|
|
923
965
|
type: Injectable
|
|
924
|
-
}], propDecorators: { setModuleInfo: [], resetState: [], setProperties: [], setPreviewInfo: [], getFormConfiguration: [], resetFormConfiguration: [], addSection: [], updateSection: [], deleteSection: [], addField: [], updateField: [], deleteField: [], reorderFields: [], moveField: [], addValidation: [], updateValidation: [], deleteValidation: [], toggleValidationActive: [] } });
|
|
966
|
+
}], propDecorators: { setModuleInfo: [], resetState: [], setProperties: [], setPreviewInfo: [], getFormConfiguration: [], resetFormConfiguration: [], updateFormSettings: [], addSection: [], updateSection: [], deleteSection: [], addField: [], updateField: [], deleteField: [], reorderFields: [], moveField: [], addValidation: [], updateValidation: [], deleteValidation: [], toggleValidationActive: [] } });
|
|
925
967
|
|
|
926
968
|
class FormBuilderFacade {
|
|
927
969
|
store = inject(Store);
|
|
@@ -944,6 +986,7 @@ class FormBuilderFacade {
|
|
|
944
986
|
// ============================================================================
|
|
945
987
|
isLoadingFormConfiguration = computed(() => this.stateSignal().loadingActive.includes(FormBuilderActionKey.GetFormConfiguration), ...(ngDevMode ? [{ debugName: "isLoadingFormConfiguration" }] : []));
|
|
946
988
|
isResettingFormConfiguration = computed(() => this.stateSignal().loadingActive.includes(FormBuilderActionKey.ResetFormConfiguration), ...(ngDevMode ? [{ debugName: "isResettingFormConfiguration" }] : []));
|
|
989
|
+
isUpdatingFormSettings = computed(() => this.stateSignal().loadingActive.includes(FormBuilderActionKey.UpdateFormSettings), ...(ngDevMode ? [{ debugName: "isUpdatingFormSettings" }] : []));
|
|
947
990
|
isAddingSection = computed(() => this.stateSignal().loadingActive.includes(FormBuilderActionKey.AddSection), ...(ngDevMode ? [{ debugName: "isAddingSection" }] : []));
|
|
948
991
|
isUpdatingSection = computed(() => this.stateSignal().loadingActive.includes(FormBuilderActionKey.UpdateSection), ...(ngDevMode ? [{ debugName: "isUpdatingSection" }] : []));
|
|
949
992
|
isDeletingSection = computed(() => this.stateSignal().loadingActive.includes(FormBuilderActionKey.DeleteSection), ...(ngDevMode ? [{ debugName: "isDeletingSection" }] : []));
|
|
@@ -1007,6 +1050,9 @@ class FormBuilderFacade {
|
|
|
1007
1050
|
resetFormConfiguration() {
|
|
1008
1051
|
return this.store.dispatch(new ResetFormConfiguration());
|
|
1009
1052
|
}
|
|
1053
|
+
updateFormSettings(payload) {
|
|
1054
|
+
return this.store.dispatch(new UpdateFormSettings(payload));
|
|
1055
|
+
}
|
|
1010
1056
|
// ============================================================================
|
|
1011
1057
|
// Section Dispatchers
|
|
1012
1058
|
// ============================================================================
|
|
@@ -1060,262 +1106,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
1060
1106
|
args: [{ providedIn: 'root' }]
|
|
1061
1107
|
}] });
|
|
1062
1108
|
|
|
1063
|
-
/**
|
|
1064
|
-
* Condition Formula Constants
|
|
1065
|
-
* Static functions and operators for condition formulas (Show/Hide/Enable/Disable)
|
|
1066
|
-
*/
|
|
1067
|
-
/**
|
|
1068
|
-
* Functions for field conditions
|
|
1069
|
-
*/
|
|
1070
|
-
const CONDITION_FUNCTION_CATEGORIES = [
|
|
1071
|
-
{
|
|
1072
|
-
name: 'Logic',
|
|
1073
|
-
displayName: 'Field Visibility',
|
|
1074
|
-
functions: [
|
|
1075
|
-
{
|
|
1076
|
-
name: 'SHOW_IF',
|
|
1077
|
-
category: 'Logic',
|
|
1078
|
-
description: 'Show this field when condition is true',
|
|
1079
|
-
signature: 'SHOW_IF(condition)',
|
|
1080
|
-
parameters: [
|
|
1081
|
-
{
|
|
1082
|
-
name: 'condition',
|
|
1083
|
-
type: 'boolean',
|
|
1084
|
-
description: 'When true, field is visible',
|
|
1085
|
-
required: true,
|
|
1086
|
-
},
|
|
1087
|
-
],
|
|
1088
|
-
returnType: 'boolean',
|
|
1089
|
-
examples: [
|
|
1090
|
-
'SHOW_IF(@Status == "Active")',
|
|
1091
|
-
'SHOW_IF(@Type == "Custom")',
|
|
1092
|
-
],
|
|
1093
|
-
},
|
|
1094
|
-
{
|
|
1095
|
-
name: 'HIDE_IF',
|
|
1096
|
-
category: 'Logic',
|
|
1097
|
-
description: 'Hide this field when condition is true',
|
|
1098
|
-
signature: 'HIDE_IF(condition)',
|
|
1099
|
-
parameters: [
|
|
1100
|
-
{
|
|
1101
|
-
name: 'condition',
|
|
1102
|
-
type: 'boolean',
|
|
1103
|
-
description: 'When true, field is hidden',
|
|
1104
|
-
required: true,
|
|
1105
|
-
},
|
|
1106
|
-
],
|
|
1107
|
-
returnType: 'boolean',
|
|
1108
|
-
examples: ['HIDE_IF(@Status == "Closed")', 'HIDE_IF(ISNULL(@Parent))'],
|
|
1109
|
-
},
|
|
1110
|
-
{
|
|
1111
|
-
name: 'DISABLE_IF',
|
|
1112
|
-
category: 'Logic',
|
|
1113
|
-
description: 'Disable this field when condition is true',
|
|
1114
|
-
signature: 'DISABLE_IF(condition)',
|
|
1115
|
-
parameters: [
|
|
1116
|
-
{
|
|
1117
|
-
name: 'condition',
|
|
1118
|
-
type: 'boolean',
|
|
1119
|
-
description: 'When true, field is disabled',
|
|
1120
|
-
required: true,
|
|
1121
|
-
},
|
|
1122
|
-
],
|
|
1123
|
-
returnType: 'boolean',
|
|
1124
|
-
examples: [
|
|
1125
|
-
'DISABLE_IF(@IsLocked == true)',
|
|
1126
|
-
'DISABLE_IF(@Status == "Approved")',
|
|
1127
|
-
],
|
|
1128
|
-
},
|
|
1129
|
-
{
|
|
1130
|
-
name: 'ENABLE_IF',
|
|
1131
|
-
category: 'Logic',
|
|
1132
|
-
description: 'Enable this field when condition is true',
|
|
1133
|
-
signature: 'ENABLE_IF(condition)',
|
|
1134
|
-
parameters: [
|
|
1135
|
-
{
|
|
1136
|
-
name: 'condition',
|
|
1137
|
-
type: 'boolean',
|
|
1138
|
-
description: 'When true, field is enabled',
|
|
1139
|
-
required: true,
|
|
1140
|
-
},
|
|
1141
|
-
],
|
|
1142
|
-
returnType: 'boolean',
|
|
1143
|
-
examples: [
|
|
1144
|
-
'ENABLE_IF(@Status == "Draft")',
|
|
1145
|
-
'ENABLE_IF(@CanEdit == true)',
|
|
1146
|
-
],
|
|
1147
|
-
},
|
|
1148
|
-
],
|
|
1149
|
-
},
|
|
1150
|
-
{
|
|
1151
|
-
name: 'Aggregation',
|
|
1152
|
-
displayName: 'Logic Helpers',
|
|
1153
|
-
functions: [
|
|
1154
|
-
{
|
|
1155
|
-
name: 'AND',
|
|
1156
|
-
category: 'Aggregation',
|
|
1157
|
-
description: 'Returns true if all conditions are true',
|
|
1158
|
-
signature: 'AND(condition1, condition2)',
|
|
1159
|
-
parameters: [
|
|
1160
|
-
{
|
|
1161
|
-
name: 'condition1',
|
|
1162
|
-
type: 'boolean',
|
|
1163
|
-
description: 'First condition',
|
|
1164
|
-
required: true,
|
|
1165
|
-
},
|
|
1166
|
-
{
|
|
1167
|
-
name: 'condition2',
|
|
1168
|
-
type: 'boolean',
|
|
1169
|
-
description: 'Second condition',
|
|
1170
|
-
required: true,
|
|
1171
|
-
},
|
|
1172
|
-
],
|
|
1173
|
-
returnType: 'boolean',
|
|
1174
|
-
examples: ['AND(@Status == "Active", @Priority > 0)'],
|
|
1175
|
-
},
|
|
1176
|
-
{
|
|
1177
|
-
name: 'OR',
|
|
1178
|
-
category: 'Aggregation',
|
|
1179
|
-
description: 'Returns true if any condition is true',
|
|
1180
|
-
signature: 'OR(condition1, condition2)',
|
|
1181
|
-
parameters: [
|
|
1182
|
-
{
|
|
1183
|
-
name: 'condition1',
|
|
1184
|
-
type: 'boolean',
|
|
1185
|
-
description: 'First condition',
|
|
1186
|
-
required: true,
|
|
1187
|
-
},
|
|
1188
|
-
{
|
|
1189
|
-
name: 'condition2',
|
|
1190
|
-
type: 'boolean',
|
|
1191
|
-
description: 'Second condition',
|
|
1192
|
-
required: true,
|
|
1193
|
-
},
|
|
1194
|
-
],
|
|
1195
|
-
returnType: 'boolean',
|
|
1196
|
-
examples: ['OR(@Status == "Active", @Status == "Pending")'],
|
|
1197
|
-
},
|
|
1198
|
-
{
|
|
1199
|
-
name: 'NOT',
|
|
1200
|
-
category: 'Aggregation',
|
|
1201
|
-
description: 'Returns the opposite of the condition',
|
|
1202
|
-
signature: 'NOT(condition)',
|
|
1203
|
-
parameters: [
|
|
1204
|
-
{
|
|
1205
|
-
name: 'condition',
|
|
1206
|
-
type: 'boolean',
|
|
1207
|
-
description: 'The condition to negate',
|
|
1208
|
-
required: true,
|
|
1209
|
-
},
|
|
1210
|
-
],
|
|
1211
|
-
returnType: 'boolean',
|
|
1212
|
-
examples: ['NOT(@IsCompleted)'],
|
|
1213
|
-
},
|
|
1214
|
-
{
|
|
1215
|
-
name: 'ISNULL',
|
|
1216
|
-
category: 'Aggregation',
|
|
1217
|
-
description: 'Returns true if value is null or empty',
|
|
1218
|
-
signature: 'ISNULL(value)',
|
|
1219
|
-
parameters: [
|
|
1220
|
-
{
|
|
1221
|
-
name: 'value',
|
|
1222
|
-
type: 'any',
|
|
1223
|
-
description: 'The value to check',
|
|
1224
|
-
required: true,
|
|
1225
|
-
},
|
|
1226
|
-
],
|
|
1227
|
-
returnType: 'boolean',
|
|
1228
|
-
examples: ['ISNULL(@Description)'],
|
|
1229
|
-
},
|
|
1230
|
-
{
|
|
1231
|
-
name: 'CONTAINS',
|
|
1232
|
-
category: 'Aggregation',
|
|
1233
|
-
description: 'Returns true if text contains the search string',
|
|
1234
|
-
signature: 'CONTAINS(text, search)',
|
|
1235
|
-
parameters: [
|
|
1236
|
-
{
|
|
1237
|
-
name: 'text',
|
|
1238
|
-
type: 'string',
|
|
1239
|
-
description: 'The text to search in',
|
|
1240
|
-
required: true,
|
|
1241
|
-
},
|
|
1242
|
-
{
|
|
1243
|
-
name: 'search',
|
|
1244
|
-
type: 'string',
|
|
1245
|
-
description: 'The string to search for',
|
|
1246
|
-
required: true,
|
|
1247
|
-
},
|
|
1248
|
-
],
|
|
1249
|
-
returnType: 'boolean',
|
|
1250
|
-
examples: ['CONTAINS(@Name, "Project")'],
|
|
1251
|
-
},
|
|
1252
|
-
],
|
|
1253
|
-
},
|
|
1254
|
-
];
|
|
1255
|
-
/**
|
|
1256
|
-
* Operators for conditions
|
|
1257
|
-
*/
|
|
1258
|
-
const CONDITION_OPERATORS = [
|
|
1259
|
-
// Comparison
|
|
1260
|
-
{
|
|
1261
|
-
symbol: '==',
|
|
1262
|
-
name: 'Equal',
|
|
1263
|
-
type: 'comparison',
|
|
1264
|
-
description: 'Equal to',
|
|
1265
|
-
precedence: 3,
|
|
1266
|
-
},
|
|
1267
|
-
{
|
|
1268
|
-
symbol: '!=',
|
|
1269
|
-
name: 'Not Equal',
|
|
1270
|
-
type: 'comparison',
|
|
1271
|
-
description: 'Not equal to',
|
|
1272
|
-
precedence: 3,
|
|
1273
|
-
},
|
|
1274
|
-
{
|
|
1275
|
-
symbol: '>',
|
|
1276
|
-
name: 'Greater Than',
|
|
1277
|
-
type: 'comparison',
|
|
1278
|
-
description: 'Greater than',
|
|
1279
|
-
precedence: 4,
|
|
1280
|
-
},
|
|
1281
|
-
{
|
|
1282
|
-
symbol: '<',
|
|
1283
|
-
name: 'Less Than',
|
|
1284
|
-
type: 'comparison',
|
|
1285
|
-
description: 'Less than',
|
|
1286
|
-
precedence: 4,
|
|
1287
|
-
},
|
|
1288
|
-
{
|
|
1289
|
-
symbol: '>=',
|
|
1290
|
-
name: 'Greater or Equal',
|
|
1291
|
-
type: 'comparison',
|
|
1292
|
-
description: 'Greater than or equal',
|
|
1293
|
-
precedence: 4,
|
|
1294
|
-
},
|
|
1295
|
-
{
|
|
1296
|
-
symbol: '<=',
|
|
1297
|
-
name: 'Less or Equal',
|
|
1298
|
-
type: 'comparison',
|
|
1299
|
-
description: 'Less than or equal',
|
|
1300
|
-
precedence: 4,
|
|
1301
|
-
},
|
|
1302
|
-
// Logical
|
|
1303
|
-
{
|
|
1304
|
-
symbol: '&&',
|
|
1305
|
-
name: 'And',
|
|
1306
|
-
type: 'logical',
|
|
1307
|
-
description: 'Logical AND',
|
|
1308
|
-
precedence: 2,
|
|
1309
|
-
},
|
|
1310
|
-
{
|
|
1311
|
-
symbol: '||',
|
|
1312
|
-
name: 'Or',
|
|
1313
|
-
type: 'logical',
|
|
1314
|
-
description: 'Logical OR',
|
|
1315
|
-
precedence: 1,
|
|
1316
|
-
},
|
|
1317
|
-
];
|
|
1318
|
-
|
|
1319
1109
|
/**
|
|
1320
1110
|
* Field Conditions Dialog
|
|
1321
1111
|
*
|
|
@@ -1623,7 +1413,7 @@ class FBFieldForm {
|
|
|
1623
1413
|
});
|
|
1624
1414
|
}
|
|
1625
1415
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBFieldForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1626
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FBFieldForm, isStandalone: true, selector: "mt-fb-field-form", inputs: { sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, allSections: { classPropertyName: "allSections", publicName: "allSections", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-hidden!']\">\r\n <div class=\"mt-2 h-full overflow-y-auto pb-10 flex flex-col gap-4\">\r\n <mt-dynamic-form\r\n [formConfig]=\"activeFormConfig()\"\r\n [formControl]=\"formControl\"\r\n >\r\n </mt-dynamic-form>\r\n\r\n @if (isManageProperties()) {\r\n <!-- isRead Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-read')\"\r\n [descriptionCard]=\"t('is-read-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"isReadControl\"\r\n ></mt-toggle-field>\r\n\r\n <!-- isWrite Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-write')\"\r\n [descriptionCard]=\"t('is-write-description')\"\r\n icon=\"general.edit-02\"\r\n [formControl]=\"isWriteControl\"\r\n ></mt-toggle-field>\r\n } @else {\r\n <!-- Show/Hide Toggle with Set Conditions -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('show-hide')\"\r\n [descriptionCard]=\"t('show-hide-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"showHideControl\"\r\n class=\"mt-3\"\r\n >\r\n <ng-template #toggleCardBottom>\r\n @if (showHideControl.value) {\r\n <div class=\"mt-3\">\r\n <mt-button\r\n [label]=\"t('set-conditions')\"\r\n size=\"small\"\r\n (onClick)=\"onSetConditions()\"\r\n ></mt-button>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-toggle-field>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div [class]=\"modalService.footerClass\">\r\n @if (initialData() && !isManageProperties()) {\r\n <mt-button\r\n [tooltip]=\"t('delete')\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n icon=\"general.trash-01\"\r\n [loading]=\"deleting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"onDelete($event)\"\r\n class=\"me-auto\"\r\n ></mt-button>\r\n }\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [disabled]=\"submitting() || deleting()\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!formControl.valid || deleting()\"\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }] });
|
|
1416
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FBFieldForm, isStandalone: true, selector: "mt-fb-field-form", inputs: { sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, allSections: { classPropertyName: "allSections", publicName: "allSections", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-hidden!']\">\r\n <div class=\"mt-2 h-full overflow-y-auto pb-10 flex flex-col gap-4\">\r\n <mt-dynamic-form\r\n [formConfig]=\"activeFormConfig()\"\r\n [formControl]=\"formControl\"\r\n >\r\n </mt-dynamic-form>\r\n\r\n @if (isManageProperties()) {\r\n <!-- isRead Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-read')\"\r\n [descriptionCard]=\"t('is-read-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"isReadControl\"\r\n ></mt-toggle-field>\r\n\r\n <!-- isWrite Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-write')\"\r\n [descriptionCard]=\"t('is-write-description')\"\r\n icon=\"general.edit-02\"\r\n [formControl]=\"isWriteControl\"\r\n ></mt-toggle-field>\r\n } @else {\r\n <!-- Show/Hide Toggle with Set Conditions -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('show-hide')\"\r\n [descriptionCard]=\"t('show-hide-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"showHideControl\"\r\n class=\"mt-3\"\r\n >\r\n <ng-template #toggleCardBottom>\r\n @if (showHideControl.value) {\r\n <div class=\"mt-3\">\r\n <mt-button\r\n [label]=\"t('set-conditions')\"\r\n size=\"small\"\r\n (onClick)=\"onSetConditions()\"\r\n ></mt-button>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-toggle-field>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div [class]=\"modalService.footerClass\">\r\n @if (initialData() && !isManageProperties()) {\r\n <mt-button\r\n [tooltip]=\"t('delete')\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n icon=\"general.trash-01\"\r\n [loading]=\"deleting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"onDelete($event)\"\r\n class=\"me-auto\"\r\n ></mt-button>\r\n }\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [disabled]=\"submitting() || deleting()\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!formControl.valid || deleting()\"\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }] });
|
|
1627
1417
|
}
|
|
1628
1418
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBFieldForm, decorators: [{
|
|
1629
1419
|
type: Component,
|
|
@@ -1739,7 +1529,7 @@ class FBSectionForm {
|
|
|
1739
1529
|
});
|
|
1740
1530
|
}
|
|
1741
1531
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBSectionForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1742
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FBSectionForm, isStandalone: true, selector: "mt-fb-section-form", inputs: { sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, sectionsCount: { classPropertyName: "sectionsCount", publicName: "sectionsCount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-hidden!']\">\r\n <div class=\"mt-4 h-full overflow-y-auto pb-10\">\r\n <mt-dynamic-form [formConfig]=\"formConfig\" [formControl]=\"formControl\">\r\n </mt-dynamic-form>\r\n </div>\r\n </div>\r\n\r\n <div [class]=\"modalService.footerClass\">\r\n @if (sectionId()) {\r\n <mt-button\r\n [tooltip]=\"t('delete')\"\r\n severity=\"danger\"\r\n outlined\r\n icon=\"general.trash-01\"\r\n [loading]=\"deleting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"onDelete($event)\"\r\n class=\"me-auto\"\r\n ></mt-button>\r\n }\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [disabled]=\"submitting() || deleting()\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!formControl.valid || deleting()\"\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
1532
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FBSectionForm, isStandalone: true, selector: "mt-fb-section-form", inputs: { sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, sectionsCount: { classPropertyName: "sectionsCount", publicName: "sectionsCount", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-hidden!']\">\r\n <div class=\"mt-4 h-full overflow-y-auto pb-10\">\r\n <mt-dynamic-form [formConfig]=\"formConfig\" [formControl]=\"formControl\">\r\n </mt-dynamic-form>\r\n </div>\r\n </div>\r\n\r\n <div [class]=\"modalService.footerClass\">\r\n @if (sectionId()) {\r\n <mt-button\r\n [tooltip]=\"t('delete')\"\r\n severity=\"danger\"\r\n outlined\r\n icon=\"general.trash-01\"\r\n [loading]=\"deleting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"onDelete($event)\"\r\n class=\"me-auto\"\r\n ></mt-button>\r\n }\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n severity=\"secondary\"\r\n [disabled]=\"submitting() || deleting()\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!formControl.valid || deleting()\"\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
1743
1533
|
}
|
|
1744
1534
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBSectionForm, decorators: [{
|
|
1745
1535
|
type: Component,
|
|
@@ -1933,332 +1723,29 @@ class FBPreviewForm {
|
|
|
1933
1723
|
modalService = inject(ModalService);
|
|
1934
1724
|
ref = inject(ModalRef);
|
|
1935
1725
|
facade = inject(FormBuilderFacade);
|
|
1936
|
-
// Preview info from store
|
|
1937
1726
|
previewInfo = this.facade.previewInfo;
|
|
1938
|
-
|
|
1727
|
+
formConfiguration = this.facade.formConfiguration;
|
|
1939
1728
|
moduleKey = computed(() => this.previewInfo()?.moduleKey ?? '', ...(ngDevMode ? [{ debugName: "moduleKey" }] : []));
|
|
1940
1729
|
operationKey = computed(() => this.previewInfo()?.operationKey ?? '', ...(ngDevMode ? [{ debugName: "operationKey" }] : []));
|
|
1730
|
+
renderMode = computed(() => {
|
|
1731
|
+
const renderMode = this.formConfiguration()?.renderMode;
|
|
1732
|
+
if (renderMode === 'steps' || renderMode === 'tabs')
|
|
1733
|
+
return renderMode;
|
|
1734
|
+
if (renderMode === 'sections')
|
|
1735
|
+
return 'form';
|
|
1736
|
+
return undefined;
|
|
1737
|
+
}, ...(ngDevMode ? [{ debugName: "renderMode" }] : []));
|
|
1941
1738
|
onClose() {
|
|
1942
1739
|
this.ref.close();
|
|
1943
1740
|
}
|
|
1944
1741
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBPreviewForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1945
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FBPreviewForm, isStandalone: true, selector: "mt-fb-preview-form", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\
|
|
1742
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FBPreviewForm, isStandalone: true, selector: "mt-fb-preview-form", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-hidden!']\">\n <div class=\"h-full overflow-y-auto px-3 pb-10\">\n @if (moduleKey() && operationKey()) {\n <mt-client-form\n [moduleKey]=\"moduleKey()\"\n [operationKey]=\"operationKey()\"\n [moduleId]=\"previewInfo()?.moduleId\"\n [levelId]=\"previewInfo()?.levelId\"\n [levelDataId]=\"previewInfo()?.levelDataId\"\n [moduleDataId]=\"previewInfo()?.moduleDataId\"\n [requestSchemaId]=\"previewInfo()?.requestSchemaId\"\n [autoLoad]=\"true\"\n [renderMode]=\"renderMode()\"\n />\n } @else {\n <div\n class=\"flex justify-center items-center h-64 text-muted-color text-lg\"\n >\n {{ t(\"no-fields-visible\") }}\n </div>\n }\n </div>\n </div>\n</ng-container>\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: ClientForm, selector: "mt-client-form", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "returnUrl", "readonly", "autoLoad", "formMode", "renderMode", "showInternalStepActions", "lang", "lookups"], outputs: ["loaded", "submitted", "errored", "modeDetected", "formSourceDetected"] }] });
|
|
1946
1743
|
}
|
|
1947
1744
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBPreviewForm, decorators: [{
|
|
1948
1745
|
type: Component,
|
|
1949
|
-
args: [{ selector: 'mt-fb-preview-form', standalone: true, imports: [TranslocoDirective, ClientForm], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\
|
|
1746
|
+
args: [{ selector: 'mt-fb-preview-form', standalone: true, imports: [TranslocoDirective, ClientForm], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-hidden!']\">\n <div class=\"h-full overflow-y-auto px-3 pb-10\">\n @if (moduleKey() && operationKey()) {\n <mt-client-form\n [moduleKey]=\"moduleKey()\"\n [operationKey]=\"operationKey()\"\n [moduleId]=\"previewInfo()?.moduleId\"\n [levelId]=\"previewInfo()?.levelId\"\n [levelDataId]=\"previewInfo()?.levelDataId\"\n [moduleDataId]=\"previewInfo()?.moduleDataId\"\n [requestSchemaId]=\"previewInfo()?.requestSchemaId\"\n [autoLoad]=\"true\"\n [renderMode]=\"renderMode()\"\n />\n } @else {\n <div\n class=\"flex justify-center items-center h-64 text-muted-color text-lg\"\n >\n {{ t(\"no-fields-visible\") }}\n </div>\n }\n </div>\n </div>\n</ng-container>\n" }]
|
|
1950
1747
|
}] });
|
|
1951
1748
|
|
|
1952
|
-
/**
|
|
1953
|
-
* Validation Formula Constants
|
|
1954
|
-
* Functions and operators for validation formulas
|
|
1955
|
-
*/
|
|
1956
|
-
const VALIDATION_FUNCTION_CATEGORIES = [
|
|
1957
|
-
{
|
|
1958
|
-
name: 'Validation',
|
|
1959
|
-
displayName: 'Validation',
|
|
1960
|
-
functions: [
|
|
1961
|
-
{
|
|
1962
|
-
name: 'REQUIRED',
|
|
1963
|
-
category: 'Validation',
|
|
1964
|
-
description: 'Returns true when value is not empty',
|
|
1965
|
-
signature: 'REQUIRED(value)',
|
|
1966
|
-
parameters: [
|
|
1967
|
-
{
|
|
1968
|
-
name: 'value',
|
|
1969
|
-
type: 'any',
|
|
1970
|
-
description: 'Value to check',
|
|
1971
|
-
required: true,
|
|
1972
|
-
},
|
|
1973
|
-
],
|
|
1974
|
-
returnType: 'boolean',
|
|
1975
|
-
examples: ['REQUIRED(@Email)'],
|
|
1976
|
-
},
|
|
1977
|
-
{
|
|
1978
|
-
name: 'ISNULL',
|
|
1979
|
-
category: 'Validation',
|
|
1980
|
-
description: 'Returns true if value is null or empty',
|
|
1981
|
-
signature: 'ISNULL(value)',
|
|
1982
|
-
parameters: [
|
|
1983
|
-
{
|
|
1984
|
-
name: 'value',
|
|
1985
|
-
type: 'any',
|
|
1986
|
-
description: 'Value to check',
|
|
1987
|
-
required: true,
|
|
1988
|
-
},
|
|
1989
|
-
],
|
|
1990
|
-
returnType: 'boolean',
|
|
1991
|
-
examples: ['ISNULL(@Phone)'],
|
|
1992
|
-
},
|
|
1993
|
-
{
|
|
1994
|
-
name: 'MIN_LENGTH',
|
|
1995
|
-
category: 'Validation',
|
|
1996
|
-
description: 'Returns true if value length is at least min',
|
|
1997
|
-
signature: 'MIN_LENGTH(value, min)',
|
|
1998
|
-
parameters: [
|
|
1999
|
-
{
|
|
2000
|
-
name: 'value',
|
|
2001
|
-
type: 'string',
|
|
2002
|
-
description: 'Value to check',
|
|
2003
|
-
required: true,
|
|
2004
|
-
},
|
|
2005
|
-
{
|
|
2006
|
-
name: 'min',
|
|
2007
|
-
type: 'number',
|
|
2008
|
-
description: 'Minimum length',
|
|
2009
|
-
required: true,
|
|
2010
|
-
},
|
|
2011
|
-
],
|
|
2012
|
-
returnType: 'boolean',
|
|
2013
|
-
examples: ['MIN_LENGTH(@Password, 8)'],
|
|
2014
|
-
},
|
|
2015
|
-
{
|
|
2016
|
-
name: 'MAX_LENGTH',
|
|
2017
|
-
category: 'Validation',
|
|
2018
|
-
description: 'Returns true if value length is at most max',
|
|
2019
|
-
signature: 'MAX_LENGTH(value, max)',
|
|
2020
|
-
parameters: [
|
|
2021
|
-
{
|
|
2022
|
-
name: 'value',
|
|
2023
|
-
type: 'string',
|
|
2024
|
-
description: 'Value to check',
|
|
2025
|
-
required: true,
|
|
2026
|
-
},
|
|
2027
|
-
{
|
|
2028
|
-
name: 'max',
|
|
2029
|
-
type: 'number',
|
|
2030
|
-
description: 'Maximum length',
|
|
2031
|
-
required: true,
|
|
2032
|
-
},
|
|
2033
|
-
],
|
|
2034
|
-
returnType: 'boolean',
|
|
2035
|
-
examples: ['MAX_LENGTH(@Title, 120)'],
|
|
2036
|
-
},
|
|
2037
|
-
{
|
|
2038
|
-
name: 'REGEX',
|
|
2039
|
-
category: 'Validation',
|
|
2040
|
-
description: 'Returns true if value matches regex pattern',
|
|
2041
|
-
signature: 'REGEX(value, pattern)',
|
|
2042
|
-
parameters: [
|
|
2043
|
-
{
|
|
2044
|
-
name: 'value',
|
|
2045
|
-
type: 'string',
|
|
2046
|
-
description: 'Value to check',
|
|
2047
|
-
required: true,
|
|
2048
|
-
},
|
|
2049
|
-
{
|
|
2050
|
-
name: 'pattern',
|
|
2051
|
-
type: 'string',
|
|
2052
|
-
description: 'Regex pattern',
|
|
2053
|
-
required: true,
|
|
2054
|
-
},
|
|
2055
|
-
],
|
|
2056
|
-
returnType: 'boolean',
|
|
2057
|
-
examples: ['REGEX(@Email, "^[^@]+@[^@]+\\.[^@]+$")'],
|
|
2058
|
-
},
|
|
2059
|
-
{
|
|
2060
|
-
name: 'BEFORE',
|
|
2061
|
-
category: 'Validation',
|
|
2062
|
-
description: 'Returns true if date is before reference date',
|
|
2063
|
-
signature: 'BEFORE(date, reference)',
|
|
2064
|
-
parameters: [
|
|
2065
|
-
{
|
|
2066
|
-
name: 'date',
|
|
2067
|
-
type: 'date',
|
|
2068
|
-
description: 'Date to check',
|
|
2069
|
-
required: true,
|
|
2070
|
-
},
|
|
2071
|
-
{
|
|
2072
|
-
name: 'reference',
|
|
2073
|
-
type: 'date',
|
|
2074
|
-
description: 'Reference date',
|
|
2075
|
-
required: true,
|
|
2076
|
-
},
|
|
2077
|
-
],
|
|
2078
|
-
returnType: 'boolean',
|
|
2079
|
-
examples: ['BEFORE(@EndDate, @StartDate)'],
|
|
2080
|
-
},
|
|
2081
|
-
{
|
|
2082
|
-
name: 'AFTER',
|
|
2083
|
-
category: 'Validation',
|
|
2084
|
-
description: 'Returns true if date is after reference date',
|
|
2085
|
-
signature: 'AFTER(date, reference)',
|
|
2086
|
-
parameters: [
|
|
2087
|
-
{
|
|
2088
|
-
name: 'date',
|
|
2089
|
-
type: 'date',
|
|
2090
|
-
description: 'Date to check',
|
|
2091
|
-
required: true,
|
|
2092
|
-
},
|
|
2093
|
-
{
|
|
2094
|
-
name: 'reference',
|
|
2095
|
-
type: 'date',
|
|
2096
|
-
description: 'Reference date',
|
|
2097
|
-
required: true,
|
|
2098
|
-
},
|
|
2099
|
-
],
|
|
2100
|
-
returnType: 'boolean',
|
|
2101
|
-
examples: ['AFTER(@StartDate, @EndDate)'],
|
|
2102
|
-
},
|
|
2103
|
-
],
|
|
2104
|
-
},
|
|
2105
|
-
{
|
|
2106
|
-
name: 'Logic',
|
|
2107
|
-
displayName: 'Logic Helpers',
|
|
2108
|
-
functions: [
|
|
2109
|
-
{
|
|
2110
|
-
name: 'AND',
|
|
2111
|
-
category: 'Logic',
|
|
2112
|
-
description: 'Returns true if all conditions are true',
|
|
2113
|
-
signature: 'AND(condition1, condition2)',
|
|
2114
|
-
parameters: [
|
|
2115
|
-
{
|
|
2116
|
-
name: 'condition1',
|
|
2117
|
-
type: 'boolean',
|
|
2118
|
-
description: 'First condition',
|
|
2119
|
-
required: true,
|
|
2120
|
-
},
|
|
2121
|
-
{
|
|
2122
|
-
name: 'condition2',
|
|
2123
|
-
type: 'boolean',
|
|
2124
|
-
description: 'Second condition',
|
|
2125
|
-
required: true,
|
|
2126
|
-
},
|
|
2127
|
-
],
|
|
2128
|
-
returnType: 'boolean',
|
|
2129
|
-
examples: ['AND(REQUIRED(@Email), REGEX(@Email, "^.+@.+$"))'],
|
|
2130
|
-
},
|
|
2131
|
-
{
|
|
2132
|
-
name: 'OR',
|
|
2133
|
-
category: 'Logic',
|
|
2134
|
-
description: 'Returns true if any condition is true',
|
|
2135
|
-
signature: 'OR(condition1, condition2)',
|
|
2136
|
-
parameters: [
|
|
2137
|
-
{
|
|
2138
|
-
name: 'condition1',
|
|
2139
|
-
type: 'boolean',
|
|
2140
|
-
description: 'First condition',
|
|
2141
|
-
required: true,
|
|
2142
|
-
},
|
|
2143
|
-
{
|
|
2144
|
-
name: 'condition2',
|
|
2145
|
-
type: 'boolean',
|
|
2146
|
-
description: 'Second condition',
|
|
2147
|
-
required: true,
|
|
2148
|
-
},
|
|
2149
|
-
],
|
|
2150
|
-
returnType: 'boolean',
|
|
2151
|
-
examples: ['OR(ISNULL(@Phone), REGEX(@Phone, "^\\+?[0-9]+$"))'],
|
|
2152
|
-
},
|
|
2153
|
-
{
|
|
2154
|
-
name: 'NOT',
|
|
2155
|
-
category: 'Logic',
|
|
2156
|
-
description: 'Returns the opposite of a condition',
|
|
2157
|
-
signature: 'NOT(condition)',
|
|
2158
|
-
parameters: [
|
|
2159
|
-
{
|
|
2160
|
-
name: 'condition',
|
|
2161
|
-
type: 'boolean',
|
|
2162
|
-
description: 'Condition to negate',
|
|
2163
|
-
required: true,
|
|
2164
|
-
},
|
|
2165
|
-
],
|
|
2166
|
-
returnType: 'boolean',
|
|
2167
|
-
examples: ['NOT(ISNULL(@Password))'],
|
|
2168
|
-
},
|
|
2169
|
-
],
|
|
2170
|
-
},
|
|
2171
|
-
];
|
|
2172
|
-
const VALIDATION_OPERATORS = [
|
|
2173
|
-
// Arithmetic
|
|
2174
|
-
{
|
|
2175
|
-
symbol: '+',
|
|
2176
|
-
name: 'Add',
|
|
2177
|
-
type: 'arithmetic',
|
|
2178
|
-
description: 'Addition',
|
|
2179
|
-
precedence: 4,
|
|
2180
|
-
},
|
|
2181
|
-
{
|
|
2182
|
-
symbol: '-',
|
|
2183
|
-
name: 'Subtract',
|
|
2184
|
-
type: 'arithmetic',
|
|
2185
|
-
description: 'Subtraction',
|
|
2186
|
-
precedence: 4,
|
|
2187
|
-
},
|
|
2188
|
-
{
|
|
2189
|
-
symbol: '*',
|
|
2190
|
-
name: 'Multiply',
|
|
2191
|
-
type: 'arithmetic',
|
|
2192
|
-
description: 'Multiplication',
|
|
2193
|
-
precedence: 5,
|
|
2194
|
-
},
|
|
2195
|
-
{
|
|
2196
|
-
symbol: '/',
|
|
2197
|
-
name: 'Divide',
|
|
2198
|
-
type: 'arithmetic',
|
|
2199
|
-
description: 'Division',
|
|
2200
|
-
precedence: 5,
|
|
2201
|
-
},
|
|
2202
|
-
// Comparison
|
|
2203
|
-
{
|
|
2204
|
-
symbol: '==',
|
|
2205
|
-
name: 'Equal',
|
|
2206
|
-
type: 'comparison',
|
|
2207
|
-
description: 'Equal to',
|
|
2208
|
-
precedence: 3,
|
|
2209
|
-
},
|
|
2210
|
-
{
|
|
2211
|
-
symbol: '!=',
|
|
2212
|
-
name: 'Not Equal',
|
|
2213
|
-
type: 'comparison',
|
|
2214
|
-
description: 'Not equal to',
|
|
2215
|
-
precedence: 3,
|
|
2216
|
-
},
|
|
2217
|
-
{
|
|
2218
|
-
symbol: '>',
|
|
2219
|
-
name: 'Greater Than',
|
|
2220
|
-
type: 'comparison',
|
|
2221
|
-
description: 'Greater than',
|
|
2222
|
-
precedence: 3,
|
|
2223
|
-
},
|
|
2224
|
-
{
|
|
2225
|
-
symbol: '<',
|
|
2226
|
-
name: 'Less Than',
|
|
2227
|
-
type: 'comparison',
|
|
2228
|
-
description: 'Less than',
|
|
2229
|
-
precedence: 3,
|
|
2230
|
-
},
|
|
2231
|
-
{
|
|
2232
|
-
symbol: '>=',
|
|
2233
|
-
name: 'Greater or Equal',
|
|
2234
|
-
type: 'comparison',
|
|
2235
|
-
description: 'Greater than or equal',
|
|
2236
|
-
precedence: 3,
|
|
2237
|
-
},
|
|
2238
|
-
{
|
|
2239
|
-
symbol: '<=',
|
|
2240
|
-
name: 'Less or Equal',
|
|
2241
|
-
type: 'comparison',
|
|
2242
|
-
description: 'Less than or equal',
|
|
2243
|
-
precedence: 3,
|
|
2244
|
-
},
|
|
2245
|
-
// Logical
|
|
2246
|
-
{
|
|
2247
|
-
symbol: '&&',
|
|
2248
|
-
name: 'And',
|
|
2249
|
-
type: 'logical',
|
|
2250
|
-
description: 'Logical AND',
|
|
2251
|
-
precedence: 2,
|
|
2252
|
-
},
|
|
2253
|
-
{
|
|
2254
|
-
symbol: '||',
|
|
2255
|
-
name: 'Or',
|
|
2256
|
-
type: 'logical',
|
|
2257
|
-
description: 'Logical OR',
|
|
2258
|
-
precedence: 1,
|
|
2259
|
-
},
|
|
2260
|
-
];
|
|
2261
|
-
|
|
2262
1749
|
class FBValidationRuleForm {
|
|
2263
1750
|
modalService = inject(ModalService);
|
|
2264
1751
|
ref = inject(ModalRef);
|
|
@@ -2522,7 +2009,7 @@ class FBValidationRules {
|
|
|
2522
2009
|
.subscribe();
|
|
2523
2010
|
}
|
|
2524
2011
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBValidationRules, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2525
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.3", type: FBValidationRules, isStandalone: true, selector: "mt-fb-validation-rules", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-auto']\">\r\n <div class=\"flex justify-end pb-4\">\r\n <mt-button\r\n [label]=\"t('add-validation-rule')\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n (onClick)=\"openCreate()\"\r\n ></mt-button>\r\n </div>\r\n <mt-table\r\n [data]=\"tableRows()\"\r\n [columns]=\"tableColumns()\"\r\n [rowActions]=\"rowActions()\"\r\n (cellChange)=\"onCellChange($event)\"\r\n ></mt-table>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "generalSearch", "showFilters", "loading", "updating", "lazy", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
2012
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.3", type: FBValidationRules, isStandalone: true, selector: "mt-fb-validation-rules", ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div [class]=\"[modalService.contentClass, 'p-4', 'overflow-y-auto']\">\r\n <div class=\"flex justify-end pb-4\">\r\n <mt-button\r\n [label]=\"t('add-validation-rule')\"\r\n severity=\"primary\"\r\n variant=\"outlined\"\r\n (onClick)=\"openCreate()\"\r\n ></mt-button>\r\n </div>\r\n <mt-table\r\n [data]=\"tableRows()\"\r\n [columns]=\"tableColumns()\"\r\n [rowActions]=\"rowActions()\"\r\n (cellChange)=\"onCellChange($event)\"\r\n ></mt-table>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "showFilters", "loading", "updating", "lazy", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }] });
|
|
2526
2013
|
}
|
|
2527
2014
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FBValidationRules, decorators: [{
|
|
2528
2015
|
type: Component,
|
|
@@ -2646,8 +2133,10 @@ class FormBuilder {
|
|
|
2646
2133
|
// Facade State
|
|
2647
2134
|
// ============================================================================
|
|
2648
2135
|
sections = this.facade.sections;
|
|
2136
|
+
formConfiguration = this.facade.formConfiguration;
|
|
2649
2137
|
properties = this.facade.properties;
|
|
2650
2138
|
isLoading = this.facade.isLoadingFormConfiguration;
|
|
2139
|
+
isUpdatingFormSettings = this.facade.isUpdatingFormSettings;
|
|
2651
2140
|
error = this.facade.formConfigurationError;
|
|
2652
2141
|
moduleType = this.facade.moduleType;
|
|
2653
2142
|
moduleId = this.facade.moduleId;
|
|
@@ -2743,6 +2232,29 @@ class FormBuilder {
|
|
|
2743
2232
|
}),
|
|
2744
2233
|
}));
|
|
2745
2234
|
}, ...(ngDevMode ? [{ debugName: "enrichedSections" }] : []));
|
|
2235
|
+
selectedRenderMode = computed(() => {
|
|
2236
|
+
return this.formConfiguration()?.renderMode ?? 'sections';
|
|
2237
|
+
}, ...(ngDevMode ? [{ debugName: "selectedRenderMode" }] : []));
|
|
2238
|
+
renderModeOptions = computed(() => [
|
|
2239
|
+
{
|
|
2240
|
+
label: 'Sections',
|
|
2241
|
+
value: 'sections',
|
|
2242
|
+
icon: 'layout.table',
|
|
2243
|
+
color: 'primary',
|
|
2244
|
+
},
|
|
2245
|
+
{
|
|
2246
|
+
label: 'Steps',
|
|
2247
|
+
value: 'steps',
|
|
2248
|
+
icon: 'layout.layout-top',
|
|
2249
|
+
color: 'success',
|
|
2250
|
+
},
|
|
2251
|
+
{
|
|
2252
|
+
label: 'Tabs',
|
|
2253
|
+
value: 'tabs',
|
|
2254
|
+
icon: 'layout.layout-grid-01',
|
|
2255
|
+
color: 'info',
|
|
2256
|
+
},
|
|
2257
|
+
], ...(ngDevMode ? [{ debugName: "renderModeOptions" }] : []));
|
|
2746
2258
|
// ============================================================================
|
|
2747
2259
|
// Lifecycle
|
|
2748
2260
|
// ============================================================================
|
|
@@ -3164,6 +2676,11 @@ class FormBuilder {
|
|
|
3164
2676
|
dismissible: true,
|
|
3165
2677
|
});
|
|
3166
2678
|
}
|
|
2679
|
+
onRenderModeChange(renderMode) {
|
|
2680
|
+
if (renderMode === this.selectedRenderMode())
|
|
2681
|
+
return;
|
|
2682
|
+
this.facade.updateFormSettings({ renderMode });
|
|
2683
|
+
}
|
|
3167
2684
|
openValidationRules() {
|
|
3168
2685
|
this.dialogRef = this.modalService.openModal(FBValidationRules, 'drawer', {
|
|
3169
2686
|
header: this.translocoService.translate('formBuilder.validation-rules'),
|
|
@@ -3182,7 +2699,7 @@ class FormBuilder {
|
|
|
3182
2699
|
}
|
|
3183
2700
|
noReturnPredicate = () => false;
|
|
3184
2701
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3185
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FormBuilder, isStandalone: true, selector: "mt-form-builder", inputs: { canvasStyleClass: { classPropertyName: "canvasStyleClass", publicName: "canvasStyleClass", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popovers", predicate: Popover, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex gap-7 h-full w-full overflow-hidden\" cdkDropListGroup>\r\n <!-- Properties Sidebar (hidden in manageProperties mode) -->\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card class=\"w-1/5 h-full flex flex-col overflow-hidden\">\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex flex-1 flex-col min-h-0\"\r\n >\r\n <p-tablist class=\"shrink-0\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n Path\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n No context available\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Select {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n No options\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <span class=\"text-xs text-slate-400\">\r\n Add segment\r\n </span>\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Add Segment\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden flex-1 overflow-y-auto\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n @if (scope.key === \"Current\") {\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"sticky top-0 bg-surface-0 py-3\">\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <p-skeleton\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-lg\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"w-full\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n placeholder=\"Select...\"\r\n [ngModel]=\"getScopeSelectedPropertyKey(scope.key)\"\r\n (ngModelChange)=\"\r\n setScopeSelectedProperty(scope.key, $event)\r\n \"\r\n [options]=\"getScopePropertyOptions(scope.key)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-2xl bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (scope.key === \"Current\" && searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (scope.key !== \"Current\") {\r\n Select a property\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n No properties available\r\n } @else {\r\n All items are in use\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div class=\"flex flex-1 gap-4 h-full overflow-y-auto\">\r\n <div\r\n class=\"flex flex-col w-2/3 gap-4 h-full\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 flex items-center gap-3\">\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div class=\"flex items-center justify-between\">\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n @for (section of enrichedSections(); track section.id) {\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i3.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i3.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabList, selector: "p-tablist" }, { kind: "component", type: i3.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: FBSection, selector: "mt-fb-section", inputs: ["section", "sectionsCount", "allSections", "mode"], outputs: ["onFieldDrop"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i6.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i6.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i6.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i6.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }] });
|
|
2702
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FormBuilder, isStandalone: true, selector: "mt-form-builder", inputs: { canvasStyleClass: { classPropertyName: "canvasStyleClass", publicName: "canvasStyleClass", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popovers", predicate: Popover, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex gap-7 h-full w-full overflow-hidden\" cdkDropListGroup>\r\n <!-- Properties Sidebar (hidden in manageProperties mode) -->\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card class=\"w-1/5 h-full flex flex-col overflow-hidden\">\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex flex-1 flex-col min-h-0\"\r\n >\r\n <p-tablist class=\"shrink-0\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n Path\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n No context available\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Select {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n No options\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <span class=\"text-xs text-slate-400\">\r\n Add segment\r\n </span>\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Add Segment\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden flex-1 overflow-y-auto\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n @if (scope.key === \"Current\") {\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"sticky top-0 bg-surface-0 py-3\">\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <p-skeleton\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-lg\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"w-full\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n placeholder=\"Select...\"\r\n [ngModel]=\"getScopeSelectedPropertyKey(scope.key)\"\r\n (ngModelChange)=\"\r\n setScopeSelectedProperty(scope.key, $event)\r\n \"\r\n [options]=\"getScopePropertyOptions(scope.key)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-2xl bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (scope.key === \"Current\" && searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (scope.key !== \"Current\") {\r\n Select a property\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n No properties available\r\n } @else {\r\n All items are in use\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div class=\"flex flex-1 gap-4 h-full overflow-y-auto\">\r\n <div\r\n class=\"flex flex-col w-2/3 gap-4 h-full\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 flex items-center gap-3\">\r\n <div class=\"w-44\">\r\n <mt-select-field\r\n [label]=\"''\"\r\n [placeholder]=\"''\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [ngModel]=\"selectedRenderMode()\"\r\n (ngModelChange)=\"onRenderModeChange($event)\"\r\n [options]=\"renderModeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n optionIcon=\"icon\"\r\n optionIconColor=\"color\"\r\n [optionAvatarShape]=\"'square'\"\r\n [size]=\"'small'\"\r\n [loading]=\"isUpdatingFormSettings()\"\r\n [disabled]=\"\r\n isLoading() ||\r\n isUpdatingFormSettings() ||\r\n !formConfiguration()\r\n \"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading() || isUpdatingFormSettings()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div class=\"flex items-center justify-between\">\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n @for (section of enrichedSections(); track section.id) {\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i3.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i3.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabList, selector: "p-tablist" }, { kind: "component", type: i3.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: FBSection, selector: "mt-fb-section", inputs: ["section", "sectionsCount", "allSections", "mode"], outputs: ["onFieldDrop"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i6.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i6.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i6.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i6.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }] });
|
|
3186
2703
|
}
|
|
3187
2704
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormBuilder, decorators: [{
|
|
3188
2705
|
type: Component,
|
|
@@ -3200,7 +2717,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
3200
2717
|
FBSection,
|
|
3201
2718
|
DragDropModule,
|
|
3202
2719
|
Icon,
|
|
3203
|
-
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex gap-7 h-full w-full overflow-hidden\" cdkDropListGroup>\r\n <!-- Properties Sidebar (hidden in manageProperties mode) -->\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card class=\"w-1/5 h-full flex flex-col overflow-hidden\">\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex flex-1 flex-col min-h-0\"\r\n >\r\n <p-tablist class=\"shrink-0\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n Path\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n No context available\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Select {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n No options\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <span class=\"text-xs text-slate-400\">\r\n Add segment\r\n </span>\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Add Segment\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden flex-1 overflow-y-auto\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n @if (scope.key === \"Current\") {\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"sticky top-0 bg-surface-0 py-3\">\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <p-skeleton\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-lg\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"w-full\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n placeholder=\"Select...\"\r\n [ngModel]=\"getScopeSelectedPropertyKey(scope.key)\"\r\n (ngModelChange)=\"\r\n setScopeSelectedProperty(scope.key, $event)\r\n \"\r\n [options]=\"getScopePropertyOptions(scope.key)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-2xl bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (scope.key === \"Current\" && searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (scope.key !== \"Current\") {\r\n Select a property\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n No properties available\r\n } @else {\r\n All items are in use\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div class=\"flex flex-1 gap-4 h-full overflow-y-auto\">\r\n <div\r\n class=\"flex flex-col w-2/3 gap-4 h-full\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 flex items-center gap-3\">\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div class=\"flex items-center justify-between\">\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n @for (section of enrichedSections(); track section.id) {\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"] }]
|
|
2720
|
+
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex gap-7 h-full w-full overflow-hidden\" cdkDropListGroup>\r\n <!-- Properties Sidebar (hidden in manageProperties mode) -->\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card class=\"w-1/5 h-full flex flex-col overflow-hidden\">\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex flex-1 flex-col min-h-0\"\r\n >\r\n <p-tablist class=\"shrink-0\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n Path\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n No context available\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Select {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n No options\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <span class=\"text-xs text-slate-400\">\r\n Add segment\r\n </span>\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n Add Segment\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden flex-1 overflow-y-auto\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n @if (scope.key === \"Current\") {\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n } @else {\r\n <div class=\"sticky top-0 bg-surface-0 py-3\">\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <p-skeleton\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-lg\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"w-full\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n placeholder=\"Select...\"\r\n [ngModel]=\"getScopeSelectedPropertyKey(scope.key)\"\r\n (ngModelChange)=\"\r\n setScopeSelectedProperty(scope.key, $event)\r\n \"\r\n [options]=\"getScopePropertyOptions(scope.key)\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n }\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-2xl bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (scope.key === \"Current\" && searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (scope.key !== \"Current\") {\r\n Select a property\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n No properties available\r\n } @else {\r\n All items are in use\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div class=\"flex flex-1 gap-4 h-full overflow-y-auto\">\r\n <div\r\n class=\"flex flex-col w-2/3 gap-4 h-full\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 flex items-center gap-3\">\r\n <div class=\"w-44\">\r\n <mt-select-field\r\n [label]=\"''\"\r\n [placeholder]=\"''\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [ngModel]=\"selectedRenderMode()\"\r\n (ngModelChange)=\"onRenderModeChange($event)\"\r\n [options]=\"renderModeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n optionIcon=\"icon\"\r\n optionIconColor=\"color\"\r\n [optionAvatarShape]=\"'square'\"\r\n [size]=\"'small'\"\r\n [loading]=\"isUpdatingFormSettings()\"\r\n [disabled]=\"\r\n isLoading() ||\r\n isUpdatingFormSettings() ||\r\n !formConfiguration()\r\n \"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading() || isUpdatingFormSettings()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div class=\"flex items-center justify-between\">\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n @for (section of enrichedSections(); track section.id) {\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"] }]
|
|
3204
2721
|
}], ctorParameters: () => [], propDecorators: { popovers: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => Popover), { isSignal: true }] }], canvasStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasStyleClass", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }] } });
|
|
3205
2722
|
|
|
3206
2723
|
/*
|
|
@@ -3211,5 +2728,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
3211
2728
|
* Generated bundle index. Do not edit.
|
|
3212
2729
|
*/
|
|
3213
2730
|
|
|
3214
|
-
export { AddField, AddSection, AddValidation, DeleteField, DeleteSection, DeleteValidation, FormBuilder, FormBuilderActionKey, FormBuilderFacade, FormBuilderState, GetFormConfiguration, MoveField, ReorderFields, ResetFormBuilderState, ResetFormConfiguration, SetModuleInfo, SetPreviewInfo, SetProperties, ToggleValidationActive, UpdateField, UpdateSection, UpdateValidation };
|
|
2731
|
+
export { AddField, AddSection, AddValidation, DeleteField, DeleteSection, DeleteValidation, FormBuilder, FormBuilderActionKey, FormBuilderFacade, FormBuilderState, GetFormConfiguration, MoveField, ReorderFields, ResetFormBuilderState, ResetFormConfiguration, SetModuleInfo, SetPreviewInfo, SetProperties, ToggleValidationActive, UpdateField, UpdateFormSettings, UpdateSection, UpdateValidation };
|
|
3215
2732
|
//# sourceMappingURL=masterteam-form-builder.mjs.map
|