@sapui5/sap.suite.ui.generic.template 1.151.1 → 1.153.0

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 (87) 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/control/visualfilterbar/SmartVisualFilterBar.js +4 -3
  4. package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
  5. package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
  6. package/src/sap/suite/ui/generic/template/ListReport/Component.js +4 -2
  7. package/src/sap/suite/ui/generic/template/ListReport/controller/ControllerImplementation.js +0 -6
  8. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_sv.properties +1 -1
  9. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  10. package/src/sap/suite/ui/generic/template/ListReport/view/fragments/FullscreenPage.fragment.xml +3 -0
  11. package/src/sap/suite/ui/generic/template/ObjectPage/Component.js +5 -0
  12. package/src/sap/suite/ui/generic/template/ObjectPage/controller/ControllerImplementation.js +31 -0
  13. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
  14. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/Actions.fragment.xml +1 -1
  15. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  16. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  17. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +13 -7
  18. package/src/sap/suite/ui/generic/template/genericUtilities/designtime/messagebundle.properties +0 -0
  19. package/src/sap/suite/ui/generic/template/js/AnnotationHelper.js +21 -17
  20. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +19 -3
  21. package/src/sap/suite/ui/generic/template/lib/ShareUtils.js +1 -1
  22. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillAIOrchestrator.js +16 -6
  23. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillApplyHandler.js +35 -47
  24. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillDialogController.js +80 -64
  25. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFieldCollector.js +442 -259
  26. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFormRenderer.js +186 -161
  27. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +137 -161
  28. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillTableRenderer.js +157 -191
  29. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +67 -85
  30. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +56 -4
  31. package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +11 -2
  32. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ar.properties +7 -1
  33. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_bg.properties +7 -1
  34. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ca.properties +7 -1
  35. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cnr.properties +7 -1
  36. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cs.properties +7 -1
  37. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cy.properties +7 -1
  38. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_da.properties +7 -1
  39. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_de.properties +7 -1
  40. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_el.properties +7 -1
  41. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en.properties +7 -1
  42. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_GB.properties +7 -1
  43. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_sappsd.properties +7 -1
  44. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saprigi.properties +7 -1
  45. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saptrc.properties +13 -7
  46. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +7 -1
  47. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es_MX.properties +7 -1
  48. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_et.properties +7 -1
  49. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fi.properties +11 -5
  50. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr.properties +10 -4
  51. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr_CA.properties +7 -1
  52. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hi.properties +7 -1
  53. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hr.properties +7 -1
  54. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hu.properties +7 -1
  55. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_id.properties +7 -1
  56. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_it.properties +7 -1
  57. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_iw.properties +7 -1
  58. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +7 -1
  59. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_kk.properties +7 -1
  60. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ko.properties +7 -1
  61. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lt.properties +7 -1
  62. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lv.properties +7 -1
  63. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_mk.properties +7 -1
  64. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ms.properties +7 -1
  65. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_nl.properties +7 -1
  66. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_no.properties +7 -1
  67. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pl.properties +7 -1
  68. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt.properties +7 -1
  69. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt_PT.properties +7 -1
  70. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ro.properties +7 -1
  71. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ru.properties +7 -1
  72. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sh.properties +7 -1
  73. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sk.properties +7 -1
  74. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +8 -2
  75. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sr.properties +7 -1
  76. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sv.properties +7 -1
  77. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_th.properties +7 -1
  78. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_tr.properties +7 -1
  79. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +7 -1
  80. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_vi.properties +7 -1
  81. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +7 -1
  82. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +7 -1
  83. package/src/sap/suite/ui/generic/template/lib/insights/InsightsCardHelper.js +40 -8
  84. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +3 -2
  85. package/src/sap/suite/ui/generic/template/lib/presentationControl/SmartTableHandler.js +4 -0
  86. package/src/sap/suite/ui/generic/template/library.js +1 -1
  87. package/src/sap/suite/ui/generic/template/themes/base/ObjectPage.less +7 -1
@@ -52,9 +52,14 @@ sap.ui.define([
52
52
  var oTransientContextForEasyFill = null; // Transient OData context for staged AI scalar values
53
53
  var oObjectPageContext = null; // Live ObjectPage binding context
54
54
  var oObjectPageModel = null; // OData model of the ObjectPage
55
- var mUpdatableLookupMap = {}; // { fieldName: value } for updatable fields only
55
+ var mUpdatableLookupMap = {}; // { fieldName: aiValue } updatable only
56
56
  var oRb = null; // i18n resource bundle
57
57
  var oAIPopoverRef = { popover: null }; // Mutable ref for lazy-loaded AINotice popover
58
+ // Built fresh on every AI submit by walking the rendered ObjectPage controls.
59
+ // Re-built each time so it reflects the latest edit-mode SmartField state,
60
+ // including extension fragment fields and custom fields.
61
+ var oOPStructureMap = null;
62
+ var mLiveEditable = null;
58
63
 
59
64
  // Collection state — tracks OData row contexts and property metadata for SmartTable collections
60
65
  var mCollectionState = {
@@ -67,10 +72,13 @@ sap.ui.define([
67
72
  };
68
73
 
69
74
  var mCollectionUpdates = Object.create(null); // { navProperty: [ rowUpdate ] } from AI response
75
+ var mRejectedNewRows = {}; // { navProperty: "all"|"mixed" } — hoisted so mode-switch can access it
70
76
  var mLastFieldMapping = null; // retained so table sections can be re-rendered on mode switch
71
77
  var oTableStagingState = {
72
78
  mStagedRows: Object.create(null),
73
- mPendingNewRowContexts: Object.create(null)
79
+ mPendingNewRowContexts: Object.create(null),
80
+ mExcludedRows: Object.create(null), // { navProp: { index: true } } existing rows excluded by user
81
+ mExcludedNewRows: Object.create(null) // { navProp: { index: true } } new rows excluded by user
74
82
  };
75
83
 
76
84
  // ─── Internal Helpers ────────────────────────────────────────────────────
@@ -87,15 +95,11 @@ sap.ui.define([
87
95
  oRb = oController.getView().getModel("i18n").getResourceBundle();
88
96
  oObjectPageModel = oObjectPage.getModel();
89
97
 
90
- // Initialize dialog model and deferred group once per view lifetime
91
98
  EasyFillDialogController.initDialogModel(oController, oObjectPageModel, EasyFillLayoutMode);
92
99
 
93
- // Use the provided context override or fall back to the current OP binding context
94
100
  oObjectPageContext = oContext || oObjectPage.getBindingContext();
95
101
 
96
- // Build the handler/formatter map that the dialog fragment binds to
97
102
  var oHandlers = _buildDialogHandlers();
98
-
99
103
  await EasyFillDialogController.openDialog(oController, oTemplateUtils, oHandlers);
100
104
  }
101
105
 
@@ -114,37 +118,23 @@ sap.ui.define([
114
118
  // immediately on whatever SmartForms are currently in the DOM, and then
115
119
  // again via fnOnFieldChange once the new SmartFields are rendered.
116
120
  onSelectionChange: function(oEvent) {
117
- // Step 1: clean up table content injected for the CURRENT mode BEFORE the
118
- // model update. This ensures the OPL aggregation is free of manually-added
119
- // sections when the sections binding recreates controls for the new mode,
120
- // so getSections() in renderCollectionPreviews returns only bound sections.
121
121
  var oOpl = oController.byId("EasyFillObjectPageLayout");
122
122
  if (oOpl && mLastFieldMapping && Object.keys(mCollectionUpdates).length > 0) {
123
123
  EasyFillTableRenderer.removeTableSections(oOpl);
124
124
  }
125
125
 
126
- // Step 2: update model — this triggers the OPL sections binding to recreate
127
- // bound section controls for the new mode.
128
126
  EasyFillDialogController.onSelectionChange(
129
- oEvent, oController, oTemplateUtils, oRb,
130
- EasyFillFieldCollector, EasyFillLayoutMode
127
+ oEvent, oController,
128
+ EasyFillFieldCollector, EasyFillLayoutMode, oOPStructureMap
131
129
  );
130
+ _populateAllVisibleGroups();
132
131
 
133
- // Step 3: re-render table previews for the new mode.
134
- // _removeTableSections is skipped inside renderCollectionPreviews because
135
- // bReuseStaging=true, since cleanup was already done in step 1 above.
136
132
  if (mLastFieldMapping && Object.keys(mCollectionUpdates).length > 0) {
137
133
  EasyFillTableRenderer.renderCollectionPreviews(
138
- mCollectionUpdates,
139
- mLastFieldMapping,
140
- [],
141
- oController,
142
- oRb,
143
- mCollectionState,
144
- oTableStagingState,
145
- oObjectPageModel,
146
- _validateFieldsAndUpdateConfirmState,
147
- true // bReuseStaging — also skips re-cleanup (already done above)
134
+ mCollectionUpdates, mLastFieldMapping, [],
135
+ oController, oRb, mCollectionState, oTableStagingState,
136
+ oObjectPageModel, _validateFieldsAndUpdateConfirmState,
137
+ true, mRejectedNewRows
148
138
  );
149
139
  }
150
140
  _validateFieldsAndUpdateConfirmState();
@@ -213,11 +203,6 @@ sap.ui.define([
213
203
  EasyFillDialogController.closeDialog(oController);
214
204
  },
215
205
 
216
- // ── Field value formatter (binding expression builder) ────────────
217
- formatFieldValue: function(sFieldName) {
218
- return "{" + sFieldName + "}";
219
- },
220
-
221
206
  // ── Submit user text to AI ────────────────────────────────────────
222
207
  onEasyFillSubmitInputToAI: async function() {
223
208
  await _handleAISubmit();
@@ -228,41 +213,6 @@ sap.ui.define([
228
213
  _resetEasyFill(true);
229
214
  },
230
215
 
231
- // ── SmartForm group population formatter ──────────────────────────
232
- populateSmartFields: function(sId, aFields, sEasyFillMode) {
233
- return EasyFillFormRenderer.populateSmartFields(
234
- sId, aFields, sEasyFillMode,
235
- oController,
236
- oTransientContextForEasyFill,
237
- oObjectPageContext,
238
- mUpdatableLookupMap,
239
- oDialogModel().getProperty("/llmData"),
240
- _validateFieldsAndUpdateConfirmState
241
- );
242
- },
243
-
244
- // ── Section visibility: hide SmartForm sections with no fields ──────────────
245
- hasSectionFields: function(aFields, aChildren) {
246
- if (Array.isArray(aFields) && aFields.length > 0) {
247
- return true;
248
- }
249
-
250
- function hasFieldsInNode(oNode) {
251
- if (!oNode) {
252
- return false;
253
- }
254
- if (Array.isArray(oNode.fields) && oNode.fields.length > 0) {
255
- return true;
256
- }
257
- if (Array.isArray(oNode.children)) {
258
- return oNode.children.some(hasFieldsInNode);
259
- }
260
- return false;
261
- }
262
-
263
- return Array.isArray(aChildren) && aChildren.some(hasFieldsInNode);
264
- },
265
-
266
216
  // ── Fullscreen toggle ─────────────────────────────────────────────
267
217
  onToggleFullScreen: function() {
268
218
  EasyFillDialogController.onToggleFullScreen(oController);
@@ -286,8 +236,29 @@ sap.ui.define([
286
236
  async function _handleAISubmit() {
287
237
  var oModel = oDialogModel();
288
238
  oModel.setProperty("/isBusy", true);
289
-
290
- // Build complete LLM field mapping (entity fields + collection fields)
239
+ try {
240
+
241
+ var sEntitySetName = oController.getOwnerComponent().getEntitySet();
242
+ var oEntityType = oTemplateUtils.oCommonUtils.getMetaModelEntityType(sEntitySetName);
243
+
244
+ // Walk the rendered ObjectPage to build structure map + editability in one pass.
245
+ // Uses findAggregatedObjects on the real FLP ObjectPage — confirmed approach:
246
+ // OP SmartFields created via AHModel.simplePath DO expose getBindingInfo("value").path.
247
+ // Walking up the parent chain gives section/group context without reading annotations.
248
+ // Fallback: if walk produces no fields (edge case), retains previous map.
249
+ // Single walk of the rendered ObjectPage — same proven approach as buildLiveEditabilityMap.
250
+ // Called here (in edit mode, after entity context resolves) so getBindingInfo("value").path
251
+ // is available. Produces section/group/field structure AND live editability in one pass.
252
+ // Annotation fallback kicks in automatically if rendered walk finds nothing.
253
+ var oFreshMap = EasyFillFieldCollector.buildObjectPageStructureMap(oObjectPage, oEntityType, oRb);
254
+ oOPStructureMap = oFreshMap;
255
+ mLiveEditable = oFreshMap.liveEditable;
256
+
257
+ // Build complete LLM field mapping (entity fields + collection fields).
258
+ // All visible fields are sent to the LLM — including read-only ones —
259
+ // so the LLM can return suggestions for every field.
260
+ // mLiveEditable is used AFTER the LLM responds (in getUpdatableAndNonUpdatableFields)
261
+ // to classify returned fields as editable (Filled Fields) or read-only (Unfilled Fields).
291
262
  var mFieldMapping = EasyFillAIOrchestrator.buildFieldMapping(
292
263
  oTemplateUtils, oController, oObjectPage, oObjectPageModel,
293
264
  oObjectPageContext, EasyFillFieldCollector, mCollectionState
@@ -300,9 +271,6 @@ sap.ui.define([
300
271
  oTemplateUtils
301
272
  );
302
273
 
303
- // Reset editable fields tracker for fresh population
304
- oModel.setProperty("/isBusy", false);
305
-
306
274
  // Convert date strings in AI response to JS Date objects
307
275
  EasyFillAIOrchestrator.formatDateValues(aiCallResult, mFieldMapping);
308
276
 
@@ -319,68 +287,49 @@ sap.ui.define([
319
287
  var collectionFields = oSplitResult.collectionFields;
320
288
 
321
289
  // Separate updatable from non-updatable fields
322
- var sEntitySetName = oController.getOwnerComponent().getEntitySet();
323
- var oEntityType = oTemplateUtils.oCommonUtils.getMetaModelEntityType(sEntitySetName);
324
290
  var oMetaModel = oObjectPageModel.getMetaModel();
325
291
  var oEntitySet = oMetaModel.getODataEntitySet(sEntitySetName);
326
292
  var oSplit = EasyFillFieldCollector.getUpdatableAndNonUpdatableFields(
327
- simpleFields, oEntityType, oObjectPageContext, oEntitySet
293
+ simpleFields, oEntityType, oObjectPageContext, oEntitySet, mLiveEditable
328
294
  );
329
295
  mUpdatableLookupMap = oSplit.updatableFields;
330
296
  var mNonUpdatableFields = oSplit.nonUpdatableFields;
331
297
 
332
- // Build section tree for selected view mode
333
- var aData = (sSelectedKey === EasyFillLayoutMode.CondensedMode)
334
- ? EasyFillFieldCollector.getSectionsForCondensedView(simpleFields, mUpdatableLookupMap, mNonUpdatableFields)
335
- : EasyFillFieldCollector.getSectionsForObjectPageView(oEntityType, simpleFields, oRb, mNonUpdatableFields);
336
-
337
- // Reset form (destroy previous SmartForm content + revert table staging)
338
- // then create a fresh transient context for the new AI result.
339
- // Restore the user's chosen layout mode afterwards because _resetEasyFill
340
- // unconditionally resets it to CondensedMode — without this, renderCollectionPreviews
341
- // would see the wrong mode and embed table sections inside the SmartForm SubSection
342
- // instead of adding them as standalone OPL sections (OP mode) or vice-versa.
298
+ // Compute sections array for the selected view mode.
299
+ // Condensed: two flat groups from scratch.
300
+ // OP mode: O(fields) pass over the pre-built structure map — no annotation re-walk.
301
+ var aSections = (sSelectedKey === EasyFillLayoutMode.CondensedMode || !oOPStructureMap)
302
+ ? EasyFillFieldCollector.getSectionInfoForCondensedMode(mUpdatableLookupMap, mNonUpdatableFields)
303
+ : EasyFillFieldCollector.applyLLMResultToStructureMap(
304
+ oOPStructureMap.fieldMap, oOPStructureMap.sections,
305
+ mUpdatableLookupMap, mNonUpdatableFields
306
+ );
307
+
343
308
  _resetEasyFill();
344
309
  oModel.setProperty("/easyFillMode", sSelectedKey);
345
310
  oTransientContextForEasyFill = EasyFillFormRenderer.makeTransientContext(
346
311
  null, oObjectPageModel, oController
347
312
  );
348
313
 
349
- // Update dialog model with section data and AI result.
350
- // llmData must be set BEFORE sections so that when the sections binding fires
351
- // and triggers the populateSmartFields formatter synchronously, the AI-suggested
352
- // values are already available and can be written to the transient context.
353
- oModel.setProperty("/llmData", simpleFields);
354
- oModel.setProperty("/updatableFields", mUpdatableLookupMap);
355
- oModel.setProperty("/nonUpdatableFields", mNonUpdatableFields);
356
- oModel.setProperty("/sections", aData);
314
+ oModel.setProperty("/llmData", simpleFields);
315
+ oModel.setProperty("/updatableFields", mUpdatableLookupMap);
316
+ oModel.setProperty("/nonUpdatableFields", mNonUpdatableFields);
317
+ oModel.setProperty("/sections", aSections);
357
318
  oModel.setProperty("/hasNonUpdatableFields", Object.keys(mNonUpdatableFields).length > 0);
358
-
359
- // Show warning if AI attempted to add multiple new rows but only one was accepted
360
319
  oModel.setProperty("/attemptedMultipleNewRows", oSplitResult.attemptedMultipleNewRows === true);
320
+ _populateAllVisibleGroups();
361
321
 
362
- // Process collection/table updates
363
322
  mCollectionUpdates = collectionFields;
364
323
  mLastFieldMapping = mFieldMapping;
365
- var mRejectedNewRows = oSplitResult.collectionsWithRejectedNewRows || {};
366
- // hasTableUpdates is true when there are accepted updates OR rejected-only tables to show
324
+ mRejectedNewRows = oSplitResult.collectionsWithRejectedNewRows || {};
367
325
  var bHasTableUpdates = Object.keys(mCollectionUpdates).length > 0 ||
368
326
  Object.keys(mRejectedNewRows).length > 0;
369
327
  oModel.setProperty("/hasTableUpdates", bHasTableUpdates);
370
328
 
371
- // Render collection previews into the table preview container
372
329
  EasyFillTableRenderer.renderCollectionPreviews(
373
- mCollectionUpdates,
374
- mFieldMapping,
375
- [],
376
- oController,
377
- oRb,
378
- mCollectionState,
379
- oTableStagingState,
380
- oObjectPageModel,
381
- _validateFieldsAndUpdateConfirmState,
382
- false,
383
- mRejectedNewRows
330
+ mCollectionUpdates, mFieldMapping, [],
331
+ oController, oRb, mCollectionState, oTableStagingState,
332
+ oObjectPageModel, _validateFieldsAndUpdateConfirmState, false, mRejectedNewRows
384
333
  );
385
334
 
386
335
  _validateFieldsAndUpdateConfirmState();
@@ -397,6 +346,9 @@ sap.ui.define([
397
346
  // AI call failed — show error illustration
398
347
  oModel.setProperty("/stateType", "Error");
399
348
  }
349
+ } finally {
350
+ oModel.setProperty("/isBusy", false);
351
+ }
400
352
  }
401
353
 
402
354
  /**
@@ -417,41 +369,61 @@ sap.ui.define([
417
369
  return true;
418
370
  }
419
371
 
420
- // Collect one Promise<errorArray> per SmartForm found in the layout
421
- var aCheckPromises = [];
422
- oObjectPageLayout.getSections().forEach(function(oSection) {
423
- oSection.getSubSections().forEach(function(oSubSection) {
424
- oSubSection.getBlocks().forEach(function(oBlock) {
425
- var aSmartFormCandidates = [];
426
- if (oBlock.isA("sap.ui.comp.smartform.SmartForm")) {
427
- aSmartFormCandidates.push(oBlock);
428
- } else if (typeof oBlock.getItems === "function") {
429
- // In condensed mode the SmartForm is nested inside a wrapper VBox;
430
- // look one level deeper to find it (mirrors EasyFillFormRenderer).
431
- oBlock.getItems().forEach(function(oItem) {
432
- if (oItem.isA("sap.ui.comp.smartform.SmartForm")) {
433
- aSmartFormCandidates.push(oItem);
434
- }
435
- });
436
- }
437
- aSmartFormCandidates.forEach(function(oSmartForm) {
438
- // .catch(() => []) absorbs internal SmartField metadata-promise rejections
439
- // that fire when SmartFields are destroyed during a mode switch.
440
- aCheckPromises.push(
441
- Promise.resolve(oSmartForm.check()).catch(function() { return []; })
442
- );
443
- });
444
- });
445
- });
372
+ var aCheckPromises = EasyFillFormRenderer.collectSmartForms(oObjectPageLayout).map(async function(oSmartForm) {
373
+ try { return await oSmartForm.check(); } catch (e) { return []; }
446
374
  });
447
375
 
448
- // Resolve all checks in parallel; valid only when every SmartForm has no errors
449
376
  var aResults = await Promise.all(aCheckPromises);
450
377
  return aResults.every(function(aErrors) {
451
- return Array.isArray(aErrors) && aErrors.length === 0;
378
+ // SmartForm.check() with validationMode="Async" resolves with an array of
379
+ // error objects when invalid, or [] / null / true when valid.
380
+ // Array.isArray guard handles the non-array zero-error sentinel.
381
+ return Array.isArray(aErrors) ? aErrors.length === 0 : !aErrors || aErrors === true;
452
382
  });
453
383
  }
454
384
 
385
+ /**
386
+ * Walks the current easyFillDialogModel>/sections array and calls
387
+ * EasyFillFormRenderer.populateGroupFields for every visible group that has
388
+ * activeFields. Deferred by setTimeout(0) so the sections= and groups= bindings
389
+ * have finished creating their controls before we try to find them.
390
+ */
391
+ function _populateAllVisibleGroups() {
392
+ setTimeout(function() {
393
+ var aSections = oDialogModel().getProperty("/sections") || [];
394
+ var oLLMData = oDialogModel().getProperty("/llmData") || {};
395
+ aSections.forEach(function(oSection) {
396
+ if (!oSection.visible) { return; }
397
+ (oSection.children || []).forEach(function(oGroup) {
398
+ var aFields = Array.isArray(oGroup.aActiveFields) && oGroup.aActiveFields.length
399
+ ? oGroup.aActiveFields : (oGroup.fields || []);
400
+ if (!oGroup.visible || !aFields.length) { return; }
401
+ EasyFillFormRenderer.populateGroupFields(
402
+ oGroup.id, aFields,
403
+ oController,
404
+ oTransientContextForEasyFill,
405
+ oObjectPageContext,
406
+ mUpdatableLookupMap,
407
+ oLLMData,
408
+ _validateFieldsAndUpdateConfirmState
409
+ );
410
+ });
411
+ });
412
+ }, 0);
413
+ }
414
+
415
+ /**
416
+ * Destroys all GroupElements in every visible SmartForm group — called by _resetEasyFill.
417
+ */
418
+ function _destroyAllGroupElements() {
419
+ EasyFillFormRenderer.collectSmartForms(oController.byId("EasyFillObjectPageLayout"))
420
+ .forEach(function(oForm) {
421
+ oForm.getGroups().forEach(function(oGroup) {
422
+ oGroup.destroyGroupElements();
423
+ });
424
+ });
425
+ }
426
+
455
427
  /**
456
428
  * Re-computes isSaveEnabled from the combined SmartForm and table SmartField validity
457
429
  * flag. Called as the single source of truth for the Confirm button state.
@@ -551,6 +523,10 @@ sap.ui.define([
551
523
  */
552
524
  function _resetEasyFill(bRemoveTextAreaValue) {
553
525
  mLastFieldMapping = null;
526
+ mRejectedNewRows = {};
527
+ // mUpdatableLookupMap is NOT reset here — it is overwritten by the next AI submit
528
+ // and explicitly cleared by EasyFillApplyHandler.resetEasyFill on Clear All / Cancel
529
+ _destroyAllGroupElements();
554
530
  EasyFillApplyHandler.resetEasyFill(
555
531
  !!bRemoveTextAreaValue,
556
532
  oDialogModel(),
@@ -584,20 +560,14 @@ sap.ui.define([
584
560
 
585
561
  // Collect all editable SmartFields from the EasyFill dialog SmartForms
586
562
  var aEditableFields = [];
587
- oObjectPageLayout.getSections().forEach(function(oSection) {
588
- oSection.getSubSections().forEach(function(oSubSection) {
589
- oSubSection.getBlocks().forEach(function(oBlock) {
590
- if (oBlock.isA("sap.ui.comp.smartform.SmartForm")) {
591
- oBlock.getGroups().forEach(function(oGroup) {
592
- oGroup.getGroupElements().forEach(function(oGroupElement) {
593
- oGroupElement.getElements().forEach(function(oElement) {
594
- if (oElement.isA && oElement.isA("sap.ui.comp.smartfield.SmartField") && oElement.getEditable()) {
595
- aEditableFields.push(oElement);
596
- }
597
- });
598
- });
599
- });
600
- }
563
+ EasyFillFormRenderer.collectSmartForms(oObjectPageLayout).forEach(function(oSmartForm) {
564
+ oSmartForm.getGroups().forEach(function(oGroup) {
565
+ oGroup.getGroupElements().forEach(function(oGroupElement) {
566
+ oGroupElement.getElements().forEach(function(oElement) {
567
+ if (oElement.isA && oElement.isA("sap.ui.comp.smartfield.SmartField") && oElement.getEditable()) {
568
+ aEditableFields.push(oElement);
569
+ }
570
+ });
601
571
  });
602
572
  });
603
573
  });
@@ -712,8 +682,10 @@ sap.ui.define([
712
682
  * CRUDManager.addEntry directly ensures the SmartTable binding is refreshed and side
713
683
  * effects are executed after the row is created — without that refresh the ObjectPage
714
684
  * table would not show the newly created row.
685
+ * Multiple new rows per table are created sequentially to avoid race conditions on
686
+ * the draft document.
715
687
  *
716
- * @param {object} mNewRowValues - map of { navProperty: plainValuesObject }
688
+ * @param {object} mNewRowValues - map of { navProperty: plainValuesObject[] }
717
689
  * @returns {Promise<void>}
718
690
  */
719
691
  async function _createNewRows(mNewRowValues) {
@@ -729,13 +701,17 @@ sap.ui.define([
729
701
  if (!oSmartTable) {
730
702
  continue;
731
703
  }
732
- try {
733
- // bSuppressNavigation=true: stay on the OP (don't navigate to the new sub-item).
734
- // bIgnoreTableRefresh not passed (undefined/falsy): the SmartTable binding is
735
- // refreshed and side effects are executed so the new row becomes visible.
736
- await oTemplateUtils.oCommonEventHandlers.addEntry(oSmartTable, true, undefined, mNewRowValues[sNavProp]);
737
- } catch (e) {
738
- // addEntry handles its own error messaging via CommonEventHandlers/CRUDManager
704
+ var aRowValues = mNewRowValues[sNavProp];
705
+ // aRowValues is now an array — iterate and create each row sequentially
706
+ if (!Array.isArray(aRowValues)) {
707
+ aRowValues = [aRowValues];
708
+ }
709
+ for (var j = 0; j < aRowValues.length; j++) {
710
+ try {
711
+ await oTemplateUtils.oCommonEventHandlers.addEntry(oSmartTable, true, undefined, aRowValues[j]);
712
+ } catch (e) {
713
+ // addEntry handles its own error messaging via CommonEventHandlers/CRUDManager
714
+ }
739
715
  }
740
716
  }
741
717
  }