@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.
Files changed (77) hide show
  1. package/package.json +1 -1
  2. package/src/sap/suite/ui/generic/template/.library +1 -1
  3. package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
  4. package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
  5. package/src/sap/suite/ui/generic/template/ListReport/controller/ControllerImplementation.js +6 -3
  6. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  7. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
  8. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  9. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  10. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +48 -8
  11. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
  12. package/src/sap/suite/ui/generic/template/lib/CRUDManager.js +7 -8
  13. package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +8 -1
  14. package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +10 -2
  15. package/src/sap/suite/ui/generic/template/lib/MessageUtils.js +4 -3
  16. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillAIOrchestrator.js +43 -12
  17. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillApplyHandler.js +67 -218
  18. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillDialogController.js +55 -8
  19. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFieldCollector.js +214 -35
  20. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFormRenderer.js +93 -18
  21. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +426 -48
  22. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillTableRenderer.js +512 -63
  23. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +33 -23
  24. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +90 -73
  25. package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +24 -0
  26. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ar.properties +26 -8
  27. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_bg.properties +26 -8
  28. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ca.properties +26 -8
  29. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cnr.properties +26 -8
  30. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cs.properties +26 -8
  31. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cy.properties +26 -8
  32. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_da.properties +26 -8
  33. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_de.properties +30 -12
  34. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_el.properties +26 -8
  35. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en.properties +26 -8
  36. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_GB.properties +26 -8
  37. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saprigi.properties +26 -8
  38. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +26 -8
  39. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es_MX.properties +26 -8
  40. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_et.properties +26 -8
  41. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fi.properties +26 -8
  42. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr.properties +29 -11
  43. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr_CA.properties +27 -9
  44. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hi.properties +26 -8
  45. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hr.properties +27 -9
  46. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hu.properties +26 -8
  47. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_id.properties +26 -8
  48. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_it.properties +26 -8
  49. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_iw.properties +26 -8
  50. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +26 -8
  51. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_kk.properties +26 -8
  52. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ko.properties +26 -8
  53. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lt.properties +26 -8
  54. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lv.properties +26 -8
  55. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_mk.properties +26 -8
  56. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ms.properties +26 -8
  57. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_nl.properties +26 -8
  58. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_no.properties +26 -8
  59. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pl.properties +26 -8
  60. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt.properties +26 -8
  61. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt_PT.properties +26 -8
  62. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ro.properties +26 -8
  63. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ru.properties +26 -8
  64. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sh.properties +26 -8
  65. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sk.properties +26 -8
  66. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +26 -8
  67. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sr.properties +26 -8
  68. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sv.properties +37 -19
  69. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_th.properties +26 -8
  70. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_tr.properties +26 -8
  71. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +26 -8
  72. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_vi.properties +26 -8
  73. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +26 -8
  74. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +26 -8
  75. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
  76. package/src/sap/suite/ui/generic/template/library.js +1 -1
  77. 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
- "sap/ui/model/Filter",
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
- return Object.keys(mCollectionUpdates).some(function(sCollectionName) {
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
- var aValidationErrors = [];
194
- var aCollectionNames = Object.keys(mCollectionUpdates || {});
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
- // Destroy all rendered table preview sections
325
- var oTablePreviewContainer = oController.byId("EasyFillTablePreviewContainer");
326
- if (oTablePreviewContainer) {
327
- oTablePreviewContainer.destroyItems();
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("/hasTableValidationErrors", false);
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
- ], function(JSONModel, MessageToast, FeLogger, FeError) {
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
- hasTableValidationErrors: false,
66
- tableValidationMessage: ""
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 oController.getView().getModel("i18n").getResourceBundle().getText(sKey);
306
+ return oResourceBundle.getText(sKey);
260
307
  }
261
308
  return sTitle;
262
309
  },