@cyprnet/node-red-contrib-uibuilder-formgen 0.5.12 → 0.5.13
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.
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@ All notable changes to this package will be documented in this file.
|
|
|
6
6
|
|
|
7
7
|
- Schema Builder: added a **Convert multiline → arrays** helper in the Lookups editor to migrate older lookup lists (newline strings) into arrays-of-strings.
|
|
8
8
|
|
|
9
|
+
## 0.5.13
|
|
10
|
+
|
|
11
|
+
- Schema Builder: Field editor now **stays open on validation errors** so dynamic Lookup/Auto-fill settings (e.g. Node-RED source requiring Lookup ID) don’t appear to “revert” after clicking OK.
|
|
12
|
+
|
|
9
13
|
## 0.5.11
|
|
10
14
|
|
|
11
15
|
- Lookup / Auto-fill: lookup items can now store lists as **arrays** (e.g. <code>["a","b"]</code>) and the portal will format arrays for textarea/keyvalue targets. Builder Lookups editor now includes a **Simple list** mode (one item per line → JSON array).
|
|
@@ -942,16 +942,25 @@
|
|
|
942
942
|
this.$bvModal.show('field-modal');
|
|
943
943
|
},
|
|
944
944
|
|
|
945
|
-
saveField() {
|
|
945
|
+
saveField(bvModalEvt) {
|
|
946
|
+
const preventClose = () => {
|
|
947
|
+
if (bvModalEvt && typeof bvModalEvt.preventDefault === 'function') {
|
|
948
|
+
bvModalEvt.preventDefault();
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
const fail = (msg) => {
|
|
952
|
+
preventClose();
|
|
953
|
+
this.showAlertMessage(msg, 'warning');
|
|
954
|
+
return false;
|
|
955
|
+
};
|
|
956
|
+
|
|
946
957
|
if (!this.currentField.id || !this.currentField.label) {
|
|
947
|
-
|
|
948
|
-
return;
|
|
958
|
+
return fail('Field ID and Label are required');
|
|
949
959
|
}
|
|
950
960
|
|
|
951
961
|
// Validate field ID
|
|
952
962
|
if (!/^[a-zA-Z0-9._-]+$/.test(this.currentField.id)) {
|
|
953
|
-
|
|
954
|
-
return;
|
|
963
|
+
return fail('Field ID must be alphanumeric with underscores or hyphens');
|
|
955
964
|
}
|
|
956
965
|
|
|
957
966
|
const { sectionIdx, fieldIdx } = this.editingFieldLocation;
|
|
@@ -961,8 +970,7 @@
|
|
|
961
970
|
if (fieldIdx === null) {
|
|
962
971
|
const exists = section.fields.some(f => f.id === this.currentField.id);
|
|
963
972
|
if (exists) {
|
|
964
|
-
|
|
965
|
-
return;
|
|
973
|
+
return fail('Field ID already exists in this section');
|
|
966
974
|
}
|
|
967
975
|
} else {
|
|
968
976
|
// Check if ID changed and conflicts
|
|
@@ -970,8 +978,7 @@
|
|
|
970
978
|
if (oldField.id !== this.currentField.id) {
|
|
971
979
|
const exists = section.fields.some((f, idx) => idx !== fieldIdx && f.id === this.currentField.id);
|
|
972
980
|
if (exists) {
|
|
973
|
-
|
|
974
|
-
return;
|
|
981
|
+
return fail('Field ID already exists in this section');
|
|
975
982
|
}
|
|
976
983
|
}
|
|
977
984
|
}
|
|
@@ -1022,8 +1029,7 @@
|
|
|
1022
1029
|
delete field.options;
|
|
1023
1030
|
} else if (this.currentField.type === 'select' || this.currentField.type === 'radio') {
|
|
1024
1031
|
if (!this.currentField.options || this.currentField.options.length === 0) {
|
|
1025
|
-
|
|
1026
|
-
return;
|
|
1032
|
+
return fail(`${this.currentField.type} fields require at least one option`);
|
|
1027
1033
|
}
|
|
1028
1034
|
// Filter out empty options and ensure both value and text exist
|
|
1029
1035
|
const validOptions = this.currentField.options
|
|
@@ -1034,8 +1040,7 @@
|
|
|
1034
1040
|
}));
|
|
1035
1041
|
|
|
1036
1042
|
if (validOptions.length === 0) {
|
|
1037
|
-
|
|
1038
|
-
return;
|
|
1043
|
+
return fail(`${this.currentField.type} fields require at least one valid option`);
|
|
1039
1044
|
}
|
|
1040
1045
|
|
|
1041
1046
|
field.options = validOptions;
|
|
@@ -1053,8 +1058,7 @@
|
|
|
1053
1058
|
|
|
1054
1059
|
if (field.keyvalueMode === 'pairs') {
|
|
1055
1060
|
if (!this.currentField.pairs || this.currentField.pairs.length === 0) {
|
|
1056
|
-
|
|
1057
|
-
return;
|
|
1061
|
+
return fail('Key-Value fields require at least one pair');
|
|
1058
1062
|
}
|
|
1059
1063
|
// Filter out empty pairs and ensure both key and value exist
|
|
1060
1064
|
const validPairs = this.currentField.pairs
|
|
@@ -1065,16 +1069,14 @@
|
|
|
1065
1069
|
}));
|
|
1066
1070
|
|
|
1067
1071
|
if (validPairs.length === 0) {
|
|
1068
|
-
|
|
1069
|
-
return;
|
|
1072
|
+
return fail('Key-Value fields require at least one valid pair with a key');
|
|
1070
1073
|
}
|
|
1071
1074
|
|
|
1072
1075
|
field.pairs = validPairs;
|
|
1073
1076
|
} else {
|
|
1074
1077
|
// Delimiter mode - no pairs needed, but validate delimiter
|
|
1075
1078
|
if (!field.keyvalueDelimiter || field.keyvalueDelimiter.trim() === '') {
|
|
1076
|
-
|
|
1077
|
-
return;
|
|
1079
|
+
return fail('Delimiter is required for delimiter mode');
|
|
1078
1080
|
}
|
|
1079
1081
|
}
|
|
1080
1082
|
|
|
@@ -1120,31 +1122,26 @@
|
|
|
1120
1122
|
.filter(m => m.targetField && m.valueKey);
|
|
1121
1123
|
|
|
1122
1124
|
if (!fromField) {
|
|
1123
|
-
|
|
1124
|
-
return;
|
|
1125
|
+
return fail('Lookup/Auto-fill: "From field" is required when enabled');
|
|
1125
1126
|
}
|
|
1126
1127
|
if (!matchKey) {
|
|
1127
|
-
|
|
1128
|
-
return;
|
|
1128
|
+
return fail('Lookup/Auto-fill: "Match key" is required when enabled');
|
|
1129
1129
|
}
|
|
1130
1130
|
if (cleanedMappings.length === 0) {
|
|
1131
|
-
|
|
1132
|
-
return;
|
|
1131
|
+
return fail('Lookup/Auto-fill: add at least one mapping (target field + value key)');
|
|
1133
1132
|
}
|
|
1134
1133
|
|
|
1135
1134
|
let source = null;
|
|
1136
1135
|
if (sourceType === 'uibuilder') {
|
|
1137
1136
|
const lookupId = String(af.lookupId || '').trim();
|
|
1138
1137
|
if (!lookupId) {
|
|
1139
|
-
|
|
1140
|
-
return;
|
|
1138
|
+
return fail('Lookup/Auto-fill: "Lookup ID" is required for Node-RED (dynamic) source');
|
|
1141
1139
|
}
|
|
1142
1140
|
source = { type: 'uibuilder', lookupId };
|
|
1143
1141
|
} else {
|
|
1144
1142
|
const listName = String(af.schemaListName || '').trim();
|
|
1145
1143
|
if (!listName) {
|
|
1146
|
-
|
|
1147
|
-
return;
|
|
1144
|
+
return fail('Lookup/Auto-fill: "List name" is required for Schema (static) source');
|
|
1148
1145
|
}
|
|
1149
1146
|
source = { type: 'schema', path: `lookups.${listName}` };
|
|
1150
1147
|
|
|
@@ -1156,8 +1153,7 @@
|
|
|
1156
1153
|
if (!this.schema.lookups) this.$set(this.schema, 'lookups', {});
|
|
1157
1154
|
this.$set(this.schema.lookups, listName, parsed);
|
|
1158
1155
|
} catch (e) {
|
|
1159
|
-
|
|
1160
|
-
return;
|
|
1156
|
+
return fail('Lookup/Auto-fill: schema list JSON is invalid');
|
|
1161
1157
|
}
|
|
1162
1158
|
}
|
|
1163
1159
|
}
|
|
@@ -455,7 +455,7 @@ module.exports = function(RED) {
|
|
|
455
455
|
await fs.writeJson(targetSchema, schema, { spaces: 2 });
|
|
456
456
|
|
|
457
457
|
const runtimeData = {
|
|
458
|
-
generatorVersion: "0.5.
|
|
458
|
+
generatorVersion: "0.5.13",
|
|
459
459
|
generatorNode: "uibuilder-formgen-v3",
|
|
460
460
|
timestamp: new Date().toISOString(),
|
|
461
461
|
instanceName: instanceName,
|
|
@@ -484,7 +484,7 @@ module.exports = function(RED) {
|
|
|
484
484
|
|
|
485
485
|
// Write runtime metadata
|
|
486
486
|
const runtimeData = {
|
|
487
|
-
generatorVersion: "0.5.
|
|
487
|
+
generatorVersion: "0.5.13",
|
|
488
488
|
timestamp: new Date().toISOString(),
|
|
489
489
|
instanceName: instanceName,
|
|
490
490
|
storageMode: storageMode,
|