@sapui5/sap.suite.ui.generic.template 1.148.1 → 1.148.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/sap/suite/ui/generic/template/.library +1 -1
- package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ListReport/controller/ControllerImplementation.js +6 -3
- package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
- package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +48 -8
- package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
- package/src/sap/suite/ui/generic/template/lib/CRUDManager.js +7 -8
- package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +8 -1
- package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +10 -2
- package/src/sap/suite/ui/generic/template/lib/MessageUtils.js +4 -3
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillAIOrchestrator.js +43 -12
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillApplyHandler.js +67 -218
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillDialogController.js +55 -8
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFieldCollector.js +214 -35
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFormRenderer.js +93 -18
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +426 -48
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillTableRenderer.js +512 -63
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +33 -23
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +90 -73
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +24 -0
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ar.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_bg.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ca.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cnr.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cs.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cy.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_da.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_de.properties +30 -12
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_el.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_GB.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saprigi.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es_MX.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_et.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fi.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr.properties +29 -11
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr_CA.properties +27 -9
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hi.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hr.properties +27 -9
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hu.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_id.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_it.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_iw.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_kk.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ko.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lt.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lv.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_mk.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ms.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_nl.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_no.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pl.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt_PT.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ro.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ru.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sh.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sk.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sr.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sv.properties +37 -19
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_th.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_tr.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_vi.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +26 -8
- package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
- package/src/sap/suite/ui/generic/template/library.js +1 -1
- package/src/sap/suite/ui/generic/template/themes/base/ObjectPage.less +22 -1
|
@@ -1,30 +1,12 @@
|
|
|
1
1
|
sap.ui.define([
|
|
2
2
|
"sap/suite/ui/generic/template/genericUtilities/FeLogger",
|
|
3
|
-
"sap/suite/ui/generic/template/genericUtilities/FeError"
|
|
4
|
-
|
|
5
|
-
"sap/ui/model/FilterOperator"
|
|
6
|
-
], function(FeLogger, FeError, Filter, FilterOperator) {
|
|
3
|
+
"sap/suite/ui/generic/template/genericUtilities/FeError"
|
|
4
|
+
], function(FeLogger, FeError) {
|
|
7
5
|
"use strict";
|
|
8
6
|
|
|
9
7
|
var sClassName = "lib.ai.EasyFill.EasyFillApplyHandler";
|
|
10
8
|
var oLogger = new FeLogger(sClassName).getLogger();
|
|
11
9
|
|
|
12
|
-
/**
|
|
13
|
-
* Returns the first ValueListParameterInOut parameter matching the given local property name.
|
|
14
|
-
* Extracted as a module-level helper to avoid no-loop-func ESLint violations.
|
|
15
|
-
*
|
|
16
|
-
* @param {Array} aParameters - value-list Parameters array from OData annotations
|
|
17
|
-
* @param {string} sProperty - local property name to match
|
|
18
|
-
* @returns {object|undefined}
|
|
19
|
-
*/
|
|
20
|
-
function fnFindValueListParameter(aParameters, sProperty) {
|
|
21
|
-
return aParameters.find(function(oParam) {
|
|
22
|
-
return oParam.RecordType === "com.sap.vocabularies.Common.v1.ValueListParameterInOut" &&
|
|
23
|
-
oParam.LocalDataProperty &&
|
|
24
|
-
oParam.LocalDataProperty.PropertyPath === sProperty;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
10
|
/**
|
|
29
11
|
* EasyFillApplyHandler
|
|
30
12
|
*
|
|
@@ -39,15 +21,17 @@ sap.ui.define([
|
|
|
39
21
|
* Applies all AI-suggested scalar field values from the transient context to the live ObjectPage context.
|
|
40
22
|
* Called when the user clicks "Confirm" in the EasyFill dialog.
|
|
41
23
|
*
|
|
42
|
-
*
|
|
24
|
+
*
|
|
43
25
|
* Only properties present in the updatable lookup map are written back.
|
|
44
26
|
* Collection (table) row values are copied from transient staging contexts to the
|
|
45
27
|
* live row contexts only here, so the ObjectPage table updates only after confirm.
|
|
28
|
+
* New row creation is NOT done here — the caller must call createPendingNewRows separately
|
|
29
|
+
* because it requires CRUDManager access (draft-aware) that ApplyHandler does not hold.
|
|
46
30
|
*
|
|
47
31
|
* @param {object} oTransientContextForEasyFill - the transient OData context holding AI-suggested values
|
|
48
32
|
* @param {object} oObjectPageContext - the live ObjectPage binding context to write values into
|
|
49
33
|
* @param {object} mUpdatableLookupMap - map of { fieldName: value } for fields that are updatable
|
|
50
|
-
* @param {object} oTableStagingState - table staging state { mStagedRows }
|
|
34
|
+
* @param {object} oTableStagingState - table staging state { mStagedRows, mPendingNewRowContexts }
|
|
51
35
|
* @param {object} mCollectionState - collection tracking state
|
|
52
36
|
*/
|
|
53
37
|
applyAndSave: function(oTransientContextForEasyFill, oObjectPageContext, mUpdatableLookupMap, oTableStagingState, mCollectionState) {
|
|
@@ -93,6 +77,41 @@ sap.ui.define([
|
|
|
93
77
|
oLogger.debug("applyAndSave: applied " + iCollectionApplied + " staged table value(s) to ObjectPage context");
|
|
94
78
|
},
|
|
95
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Extracts user-reviewed values from the pending new-row transient contexts.
|
|
82
|
+
* Returns a map of { navProperty: predefinedValues } ready to pass to CRUDManager.addEntry.
|
|
83
|
+
* The caller is responsible for discarding the transient contexts afterwards.
|
|
84
|
+
*
|
|
85
|
+
* @param {object} oTableStagingState - table staging state { mPendingNewRowContexts }
|
|
86
|
+
* @param {object} mCollectionState - collection tracking state (mCollectionProperties)
|
|
87
|
+
* @returns {object} map of { navProperty: plainValuesObject }
|
|
88
|
+
*/
|
|
89
|
+
extractPendingNewRowValues: function(oTableStagingState, mCollectionState) {
|
|
90
|
+
var mNewRowValues = Object.create(null);
|
|
91
|
+
Object.keys((oTableStagingState && oTableStagingState.mPendingNewRowContexts) || {}).forEach(function(sCollectionName) {
|
|
92
|
+
var aNewContexts = oTableStagingState.mPendingNewRowContexts[sCollectionName] || [];
|
|
93
|
+
if (!aNewContexts.length) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
var mCollectionPropertyMap = (mCollectionState && mCollectionState.mCollectionProperties &&
|
|
97
|
+
mCollectionState.mCollectionProperties[sCollectionName]) || Object.create(null);
|
|
98
|
+
|
|
99
|
+
// Extract scalar values set by the user during the preview (first new row only — cap is 1)
|
|
100
|
+
var oNewContext = aNewContexts[0];
|
|
101
|
+
var oValues = Object.create(null);
|
|
102
|
+
Object.keys(mCollectionPropertyMap).forEach(function(sPropName) {
|
|
103
|
+
var vValue = oNewContext.getProperty && oNewContext.getProperty(sPropName);
|
|
104
|
+
if (vValue !== undefined && vValue !== null && typeof vValue !== "object") {
|
|
105
|
+
oValues[sPropName] = vValue;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
mNewRowValues[sCollectionName] = oValues;
|
|
109
|
+
oLogger.debug("extractPendingNewRowValues: extracted " + Object.keys(oValues).length +
|
|
110
|
+
" value(s) for new row in '" + sCollectionName + "'");
|
|
111
|
+
});
|
|
112
|
+
return mNewRowValues;
|
|
113
|
+
},
|
|
114
|
+
|
|
96
115
|
/**
|
|
97
116
|
* Builds a collection updates map from the staged transient row contexts.
|
|
98
117
|
* Only editable scalar properties whose staged value differs from the live row value are included.
|
|
@@ -154,157 +173,25 @@ sap.ui.define([
|
|
|
154
173
|
},
|
|
155
174
|
|
|
156
175
|
/**
|
|
157
|
-
* Returns whether any staged collection row currently differs from the live ObjectPage rows
|
|
176
|
+
* Returns whether any staged collection row currently differs from the live ObjectPage rows,
|
|
177
|
+
* or whether any new rows are pending creation.
|
|
158
178
|
*
|
|
159
|
-
* @param {object} oTableStagingState - table staging state { mStagedRows }
|
|
179
|
+
* @param {object} oTableStagingState - table staging state { mStagedRows, mPendingNewRowContexts }
|
|
160
180
|
* @param {object} mCollectionState - collection tracking state
|
|
161
181
|
* @returns {boolean}
|
|
162
182
|
*/
|
|
163
183
|
hasStagedCollectionChanges: function(oTableStagingState, mCollectionState) {
|
|
164
184
|
var mCollectionUpdates = this.buildStagedCollectionUpdates(oTableStagingState, mCollectionState);
|
|
165
|
-
|
|
185
|
+
var bHasUpdates = Object.keys(mCollectionUpdates).some(function(sCollectionName) {
|
|
166
186
|
return (mCollectionUpdates[sCollectionName] || []).length > 0;
|
|
167
187
|
});
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Validates each collection (table) row update by checking that value-help constrained
|
|
172
|
-
* properties contain values that exist in the corresponding value-help collection.
|
|
173
|
-
*
|
|
174
|
-
* Returns an array of validation error objects for any values that fail the check.
|
|
175
|
-
* If validation cannot be performed (e.g. missing metadata), the property is skipped
|
|
176
|
-
* and save is not blocked.
|
|
177
|
-
*
|
|
178
|
-
* @param {object} mCollectionUpdates - map of { navProperty: [ rowUpdate ] }
|
|
179
|
-
* @param {object} mCollectionState - collection tracking state: { mCollectionProperties, mCollectionEntityTypes, mCollectionRowContextsByPath, mCollectionRowContexts }
|
|
180
|
-
* @param {object} oObjectPageModel - the OData model (used to read value-help collections)
|
|
181
|
-
* @param {object} oRb - i18n resource bundle
|
|
182
|
-
* @param {object} oFieldCollector - EasyFillFieldCollector (used for isEditableByContextObject)
|
|
183
|
-
* @param {object} oGenericAnnotationHelper - GenericAnnotationHelper (used for isValueHelpTableAvailable)
|
|
184
|
-
* @returns {Promise<Array>} array of { collectionName, collectionLabel, rowLabel, rowIndex, rowPath, propertyName, propertyLabel }
|
|
185
|
-
*/
|
|
186
|
-
validateCollectionUpdatesAgainstValueHelp: async function(mCollectionUpdates, mCollectionState, oObjectPageModel, oRb, oFieldCollector, oGenericAnnotationHelper) {
|
|
187
|
-
var oMetaModel = oObjectPageModel && oObjectPageModel.getMetaModel();
|
|
188
|
-
if (!oMetaModel) {
|
|
189
|
-
oLogger.warning("validateCollectionUpdatesAgainstValueHelp: no MetaModel available");
|
|
190
|
-
return [];
|
|
188
|
+
if (bHasUpdates) {
|
|
189
|
+
return true;
|
|
191
190
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
for (var i = 0; i < aCollectionNames.length; i++) {
|
|
197
|
-
var sCollectionName = aCollectionNames[i];
|
|
198
|
-
var aRowUpdates = mCollectionUpdates[sCollectionName] || [];
|
|
199
|
-
var mCollectionPropertyMap = mCollectionState.mCollectionProperties[sCollectionName] || Object.create(null);
|
|
200
|
-
var oCollectionEntityType = mCollectionState.mCollectionEntityTypes[sCollectionName];
|
|
201
|
-
|
|
202
|
-
if (!oCollectionEntityType) { continue; }
|
|
203
|
-
|
|
204
|
-
// Use the field mapping description as the collection label in error messages
|
|
205
|
-
var sCollectionLabel = sCollectionName;
|
|
206
|
-
|
|
207
|
-
for (var j = 0; j < aRowUpdates.length; j++) {
|
|
208
|
-
var oRowUpdate = aRowUpdates[j];
|
|
209
|
-
var oResolvedRow = this._resolveCollectionRowContext(sCollectionName, oRowUpdate, mCollectionState);
|
|
210
|
-
if (!oResolvedRow || !oResolvedRow.context) { continue; }
|
|
211
|
-
|
|
212
|
-
var oRowContext = oResolvedRow.context;
|
|
213
|
-
var oRowObject = oRowContext.getObject && oRowContext.getObject();
|
|
214
|
-
var sRowLabel = oRb.getText("EASY_FILL_TABLE_ROW_LABEL", [String((oResolvedRow.rowIndex || 0) + 1)]);
|
|
215
|
-
|
|
216
|
-
var aPropNames = Object.keys(oRowUpdate);
|
|
217
|
-
for (var k = 0; k < aPropNames.length; k++) {
|
|
218
|
-
var sPropertyName = aPropNames[k];
|
|
219
|
-
if (sPropertyName === "_rowIndex" || sPropertyName === "_contextPath") { continue; }
|
|
220
|
-
|
|
221
|
-
var oPropertyMeta = mCollectionPropertyMap[sPropertyName];
|
|
222
|
-
// Skip non-editable properties — they cannot be written back
|
|
223
|
-
if (!oPropertyMeta || !oFieldCollector.isEditableByContextObject(oPropertyMeta, oRowObject)) { continue; }
|
|
224
|
-
|
|
225
|
-
// Only validate properties that have an associated value-help table
|
|
226
|
-
if (!oGenericAnnotationHelper.isValueHelpTableAvailable(oPropertyMeta)) { continue; }
|
|
227
|
-
|
|
228
|
-
var vUpdatedValue = oRowUpdate[sPropertyName];
|
|
229
|
-
if (vUpdatedValue === null || vUpdatedValue === undefined || typeof vUpdatedValue === "object") { continue; }
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
var sPropertyPath = oMetaModel.getODataProperty(oCollectionEntityType, sPropertyName, true);
|
|
233
|
-
if (!sPropertyPath) { continue; }
|
|
234
|
-
|
|
235
|
-
var oPropertyContext = oMetaModel.createBindingContext(sPropertyPath);
|
|
236
|
-
var oValueLists = await oMetaModel.getODataValueLists(oPropertyContext);
|
|
237
|
-
var oDefaultValueList = oValueLists && oValueLists[""];
|
|
238
|
-
|
|
239
|
-
if (!oDefaultValueList || !oDefaultValueList.CollectionPath || !oDefaultValueList.CollectionPath.String) { continue; }
|
|
240
|
-
|
|
241
|
-
// Resolve which value-list property maps to this local property
|
|
242
|
-
var sValueListProperty = sPropertyName;
|
|
243
|
-
if (Array.isArray(oDefaultValueList.Parameters)) {
|
|
244
|
-
var oParameter = fnFindValueListParameter(oDefaultValueList.Parameters, sPropertyName);
|
|
245
|
-
if (oParameter && oParameter.ValueListProperty && oParameter.ValueListProperty.String) {
|
|
246
|
-
sValueListProperty = oParameter.ValueListProperty.String;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Check that the AI-provided value exists in the value-help collection
|
|
251
|
-
var bValueFound = await this._readValueListByEquality(
|
|
252
|
-
oDefaultValueList.CollectionPath.String,
|
|
253
|
-
sValueListProperty,
|
|
254
|
-
vUpdatedValue,
|
|
255
|
-
oObjectPageModel
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
if (!bValueFound) {
|
|
259
|
-
aValidationErrors.push({
|
|
260
|
-
collectionName: sCollectionName,
|
|
261
|
-
collectionLabel: sCollectionLabel,
|
|
262
|
-
rowLabel: sRowLabel,
|
|
263
|
-
rowIndex: oResolvedRow.rowIndex,
|
|
264
|
-
rowPath: oRowContext.getPath && oRowContext.getPath(),
|
|
265
|
-
propertyName: sPropertyName,
|
|
266
|
-
propertyLabel: this._getPropertyLabel(oPropertyMeta) || sPropertyName
|
|
267
|
-
});
|
|
268
|
-
oLogger.warning("validateCollectionUpdatesAgainstValueHelp: invalid value for '" + sPropertyName + "' in row " + oResolvedRow.rowIndex);
|
|
269
|
-
}
|
|
270
|
-
} catch (e) {
|
|
271
|
-
// If metadata or value list cannot be resolved, skip the check and do not block save
|
|
272
|
-
oLogger.warning("validateCollectionUpdatesAgainstValueHelp: could not validate '" + sPropertyName + "': " + (e && e.message));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return aValidationErrors;
|
|
279
|
-
},
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Updates the EasyFill dialog model to reflect the current table validation state.
|
|
283
|
-
* Sets hasTableValidationErrors and a human-readable summary message (up to 3 errors shown).
|
|
284
|
-
*
|
|
285
|
-
* @param {Array} aValidationErrors - array of validation error objects
|
|
286
|
-
* @param {object} oDialogModel - the easyFillDialogModel JSONModel
|
|
287
|
-
* @param {object} oRb - i18n resource bundle
|
|
288
|
-
*/
|
|
289
|
-
applyTableValidationState: function(aValidationErrors, oDialogModel, oRb) {
|
|
290
|
-
if (!aValidationErrors || aValidationErrors.length === 0) {
|
|
291
|
-
oDialogModel.setProperty("/hasTableValidationErrors", false);
|
|
292
|
-
oDialogModel.setProperty("/tableValidationMessage", "");
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Show up to 3 errors in the summary message to avoid overwhelming the user
|
|
297
|
-
var sSummary = aValidationErrors.slice(0, 3).map(function(oError) {
|
|
298
|
-
return oError.collectionLabel + " / " + oError.rowLabel + " / " + oError.propertyLabel;
|
|
299
|
-
}).join(", ");
|
|
300
|
-
|
|
301
|
-
oDialogModel.setProperty("/hasTableValidationErrors", true);
|
|
302
|
-
oDialogModel.setProperty(
|
|
303
|
-
"/tableValidationMessage",
|
|
304
|
-
oRb.getText("EASY_FILL_TABLE_VALIDATION_MESSAGE", [sSummary])
|
|
305
|
-
);
|
|
306
|
-
|
|
307
|
-
oLogger.warning("applyTableValidationState: " + aValidationErrors.length + " validation error(s) found");
|
|
191
|
+
// Also return true if there are pending new row contexts
|
|
192
|
+
return Object.keys((oTableStagingState && oTableStagingState.mPendingNewRowContexts) || {}).some(function(sCollectionName) {
|
|
193
|
+
return ((oTableStagingState.mPendingNewRowContexts[sCollectionName]) || []).length > 0;
|
|
194
|
+
});
|
|
308
195
|
},
|
|
309
196
|
|
|
310
197
|
/**
|
|
@@ -321,10 +208,18 @@ sap.ui.define([
|
|
|
321
208
|
* @param {function} fnResetTransientContext - EasyFillFormRenderer.resetTransientContext
|
|
322
209
|
*/
|
|
323
210
|
resetEasyFill: function(bRemoveTextAreaValue, oDialogModel, oController, mCollectionUpdates, oEasyFillLayoutMode, fnRevertStagedUpdates, fnResetTransientContext) {
|
|
324
|
-
//
|
|
325
|
-
var
|
|
326
|
-
|
|
327
|
-
|
|
211
|
+
// Remove dynamically-added table ObjectPageSections from the shared OPL
|
|
212
|
+
var sTableSectionMarker = "easyfillTableSection";
|
|
213
|
+
var oObjectPageLayout = oController.byId("EasyFillObjectPageLayout");
|
|
214
|
+
if (oObjectPageLayout) {
|
|
215
|
+
oObjectPageLayout.getSections().filter(function(oSection) {
|
|
216
|
+
return oSection.getCustomData().some(function(oData) {
|
|
217
|
+
return oData.getKey() === sTableSectionMarker;
|
|
218
|
+
});
|
|
219
|
+
}).forEach(function(oSection) {
|
|
220
|
+
oObjectPageLayout.removeSection(oSection);
|
|
221
|
+
oSection.destroy();
|
|
222
|
+
});
|
|
328
223
|
}
|
|
329
224
|
|
|
330
225
|
// Revert any staged table row values back to original
|
|
@@ -343,11 +238,13 @@ sap.ui.define([
|
|
|
343
238
|
oDialogModel.setProperty("/feedbackPressedDown", false);
|
|
344
239
|
oDialogModel.setProperty("/isFullScreen", true);
|
|
345
240
|
oDialogModel.setProperty("/hasTableUpdates", false);
|
|
346
|
-
oDialogModel.setProperty("/
|
|
347
|
-
oDialogModel.setProperty("/tableValidationMessage", "");
|
|
241
|
+
oDialogModel.setProperty("/attemptedMultipleNewRows", false);
|
|
348
242
|
oDialogModel.setProperty("/easyFillMode", oEasyFillLayoutMode.CondensedMode);
|
|
349
243
|
oDialogModel.setProperty("/llmData", {});
|
|
350
244
|
oDialogModel.setProperty("/sections", []);
|
|
245
|
+
oDialogModel.setProperty("/updatableFields", {});
|
|
246
|
+
oDialogModel.setProperty("/nonUpdatableFields", {});
|
|
247
|
+
oDialogModel.setProperty("/hasNonUpdatableFields", false);
|
|
351
248
|
|
|
352
249
|
// Clear the mutable collection updates map in place
|
|
353
250
|
Object.keys(mCollectionUpdates).forEach(function(sKey) {
|
|
@@ -391,54 +288,6 @@ sap.ui.define([
|
|
|
391
288
|
return null;
|
|
392
289
|
},
|
|
393
290
|
|
|
394
|
-
/**
|
|
395
|
-
* Checks whether a given value exists in a value-help collection via an OData $filter read.
|
|
396
|
-
* Returns true if the value is found or if the read fails (fail-open to not block save unexpectedly).
|
|
397
|
-
*
|
|
398
|
-
* @param {string} sCollectionPath - value-help entity set name
|
|
399
|
-
* @param {string} sValueListProperty - property name in the value-help to filter on
|
|
400
|
-
* @param {*} vValue - the value to look up
|
|
401
|
-
* @param {object} oObjectPageModel - the OData model
|
|
402
|
-
* @returns {Promise<boolean>}
|
|
403
|
-
*/
|
|
404
|
-
_readValueListByEquality: function(sCollectionPath, sValueListProperty, vValue, oObjectPageModel) {
|
|
405
|
-
return new Promise(function(resolve) {
|
|
406
|
-
oObjectPageModel.read("/" + sCollectionPath, {
|
|
407
|
-
filters: [
|
|
408
|
-
new Filter({
|
|
409
|
-
path: sValueListProperty,
|
|
410
|
-
operator: FilterOperator.EQ,
|
|
411
|
-
value1: vValue
|
|
412
|
-
})
|
|
413
|
-
],
|
|
414
|
-
success: function(oResponse) {
|
|
415
|
-
// Value found if the filtered result set is non-empty
|
|
416
|
-
resolve(!!(oResponse && Array.isArray(oResponse.results) && oResponse.results.length > 0));
|
|
417
|
-
},
|
|
418
|
-
error: function() {
|
|
419
|
-
// On error, resolve true to not block save (fail-open)
|
|
420
|
-
resolve(true);
|
|
421
|
-
}
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
},
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Extracts the display label for an OData property.
|
|
428
|
-
* Prefers Common.Label annotation, falls back to sap:label.
|
|
429
|
-
*
|
|
430
|
-
* @param {object} oPropertyMeta - OData property metadata
|
|
431
|
-
* @returns {string|null}
|
|
432
|
-
*/
|
|
433
|
-
_getPropertyLabel: function(oPropertyMeta) {
|
|
434
|
-
if (!oPropertyMeta) { return null; }
|
|
435
|
-
var oLabel = oPropertyMeta["com.sap.vocabularies.Common.v1.Label"];
|
|
436
|
-
if (oLabel && oLabel.String) {
|
|
437
|
-
return oLabel.String;
|
|
438
|
-
}
|
|
439
|
-
return oPropertyMeta["sap:label"] || null;
|
|
440
|
-
},
|
|
441
|
-
|
|
442
291
|
_isEditableProperty: function(oPropertyMeta, oRowObject) {
|
|
443
292
|
if (!oPropertyMeta) {
|
|
444
293
|
return false;
|
|
@@ -2,8 +2,9 @@ sap.ui.define([
|
|
|
2
2
|
"sap/ui/model/json/JSONModel",
|
|
3
3
|
"sap/m/MessageToast",
|
|
4
4
|
"sap/suite/ui/generic/template/genericUtilities/FeLogger",
|
|
5
|
-
"sap/suite/ui/generic/template/genericUtilities/FeError"
|
|
6
|
-
|
|
5
|
+
"sap/suite/ui/generic/template/genericUtilities/FeError",
|
|
6
|
+
"sap/ui/core/ResizeHandler"
|
|
7
|
+
], function(JSONModel, MessageToast, FeLogger, FeError, ResizeHandler) {
|
|
7
8
|
"use strict";
|
|
8
9
|
|
|
9
10
|
var sClassName = "lib.ai.EasyFill.EasyFillDialogController";
|
|
@@ -58,12 +59,15 @@ sap.ui.define([
|
|
|
58
59
|
feedbackPressedDown: false,
|
|
59
60
|
isEasyFillButtonEnabled: false,
|
|
60
61
|
llmData: {},
|
|
62
|
+
updatableFields: {},
|
|
63
|
+
nonUpdatableFields: {},
|
|
64
|
+
hasNonUpdatableFields: false,
|
|
61
65
|
easyFillMode: oEasyFillLayoutMode.CondensedMode,
|
|
62
66
|
sections: [],
|
|
63
67
|
isFullScreen: true,
|
|
64
68
|
hasTableUpdates: false,
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
attemptedMultipleNewRows: false,
|
|
70
|
+
isSplitterPageMode: false
|
|
67
71
|
};
|
|
68
72
|
|
|
69
73
|
oController.getView().setModel(new JSONModel(oData), "easyFillDialogModel");
|
|
@@ -94,6 +98,34 @@ sap.ui.define([
|
|
|
94
98
|
true // use view as parent
|
|
95
99
|
).then(function(oDialog) {
|
|
96
100
|
oDialog.open();
|
|
101
|
+
|
|
102
|
+
// Register a ResizeHandler on the ResponsiveSplitter
|
|
103
|
+
// The dialog is kept alive across opens so we must not register more than once.
|
|
104
|
+
if (!oDialog._easyFillResizeHandlerId) {
|
|
105
|
+
oDialog.attachEventOnce("afterOpen", function() {
|
|
106
|
+
// Locate the splitter by its stable fragment ID
|
|
107
|
+
var oSplitter = oController.byId("EasyFillMainFlex") &&
|
|
108
|
+
oController.byId("EasyFillMainFlex").findAggregatedObjects(true, function(o) {
|
|
109
|
+
return o.isA("sap.ui.layout.ResponsiveSplitter");
|
|
110
|
+
})[0];
|
|
111
|
+
|
|
112
|
+
if (oSplitter) {
|
|
113
|
+
var oDialogModel = oController.getView().getModel("easyFillDialogModel");
|
|
114
|
+
// sapUiRSVisiblePaginator is added/removed by the splitter itself on resize
|
|
115
|
+
oDialog._easyFillResizeHandlerId = ResizeHandler.register(oSplitter, function() {
|
|
116
|
+
var bInPageMode = oSplitter.$().hasClass("sapUiRSVisiblePaginator");
|
|
117
|
+
oDialogModel.setProperty("/isSplitterPageMode", bInPageMode);
|
|
118
|
+
if (bInPageMode && !oDialogModel.getProperty("/isFullScreen")) {
|
|
119
|
+
// Reset fullscreen state so pane sizes are correct when dialog is widened again
|
|
120
|
+
oDialogModel.setProperty("/isFullScreen", true);
|
|
121
|
+
oController.byId("inputAreaSplitPane").getLayoutData().setSize("40%");
|
|
122
|
+
oController.byId("reviewAreaSplitPane").getLayoutData().setSize("60%");
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
97
129
|
oLogger.debug("openDialog: EasyFillDialog opened");
|
|
98
130
|
});
|
|
99
131
|
},
|
|
@@ -107,6 +139,8 @@ sap.ui.define([
|
|
|
107
139
|
var oDialog = oController.byId("EasyFillDialog");
|
|
108
140
|
if (oDialog && oDialog.isOpen()) {
|
|
109
141
|
oDialog.close();
|
|
142
|
+
// Reset page-mode flag so the button is visible on the next open
|
|
143
|
+
oController.getView().getModel("easyFillDialogModel").setProperty("/isSplitterPageMode", false);
|
|
110
144
|
oLogger.debug("closeDialog: EasyFillDialog closed");
|
|
111
145
|
}
|
|
112
146
|
},
|
|
@@ -131,10 +165,19 @@ sap.ui.define([
|
|
|
131
165
|
oController.getOwnerComponent().getEntitySet()
|
|
132
166
|
);
|
|
133
167
|
oDialogModel.setProperty("/easyFillMode", sSelectedKey);
|
|
134
|
-
var oLLMResult = oDialogModel.getProperty("/llmData");
|
|
168
|
+
var oLLMResult = oDialogModel.getProperty("/llmData") || {};
|
|
169
|
+
// Use stored updatable subset when available; fall back to full LLM result
|
|
170
|
+
// only when it is absent (e.g. before the first AI submit).
|
|
171
|
+
// Important: an empty map is a valid state (all fields are non-updatable)
|
|
172
|
+
// and must not trigger fallback, otherwise non-updatable fields appear as filled.
|
|
173
|
+
var oStoredUpdatable = oDialogModel.getProperty("/updatableFields");
|
|
174
|
+
var oUpdatableFields = (oStoredUpdatable !== undefined && oStoredUpdatable !== null)
|
|
175
|
+
? oStoredUpdatable
|
|
176
|
+
: oLLMResult;
|
|
177
|
+
var oNonUpdatableFields = oDialogModel.getProperty("/nonUpdatableFields") || {};
|
|
135
178
|
var aData = (sSelectedKey === oEasyFillLayoutMode.CondensedMode)
|
|
136
|
-
? oFieldCollector.getSectionsForCondensedView(oLLMResult)
|
|
137
|
-
: oFieldCollector.getSectionsForObjectPageView(oEntityType, oLLMResult, oRb);
|
|
179
|
+
? oFieldCollector.getSectionsForCondensedView(oLLMResult, oUpdatableFields, oNonUpdatableFields)
|
|
180
|
+
: oFieldCollector.getSectionsForObjectPageView(oEntityType, oLLMResult, oRb, oNonUpdatableFields);
|
|
138
181
|
oDialogModel.setProperty("/sections", aData);
|
|
139
182
|
},
|
|
140
183
|
|
|
@@ -253,10 +296,14 @@ sap.ui.define([
|
|
|
253
296
|
*/
|
|
254
297
|
formatSectionTitle: function(sTitle, oController) {
|
|
255
298
|
if (!sTitle) { return ""; }
|
|
299
|
+
|
|
300
|
+
var oResourceBundle = oController.getView().getModel("i18n").getResourceBundle();
|
|
301
|
+
|
|
302
|
+
// Handle i18n pattern in title
|
|
256
303
|
var oMatch = sTitle.match(/\{@?i18n>([^}]+)\}/);
|
|
257
304
|
if (oMatch) {
|
|
258
305
|
var sKey = oMatch[1];
|
|
259
|
-
return
|
|
306
|
+
return oResourceBundle.getText(sKey);
|
|
260
307
|
}
|
|
261
308
|
return sTitle;
|
|
262
309
|
},
|