@sapui5/sap.suite.ui.generic.template 1.148.0 → 1.148.2

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 (81) 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/i18n/i18n_fr_CA.properties +2 -2
  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/controller/ControllerImplementation.js +6 -3
  7. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_fr.properties +1 -1
  8. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  9. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +1 -1
  10. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/Actions.fragment.xml +13 -13
  11. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  12. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  13. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +20 -1
  14. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
  15. package/src/sap/suite/ui/generic/template/lib/CRUDManager.js +0 -7
  16. package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +57 -6
  17. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillAIOrchestrator.js +216 -0
  18. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillApplyHandler.js +325 -0
  19. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillDialogController.js +358 -0
  20. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFieldCollector.js +848 -0
  21. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFormRenderer.js +292 -0
  22. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +652 -1071
  23. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillTableRenderer.js +940 -0
  24. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +41 -26
  25. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +90 -73
  26. package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +35 -8
  27. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ar.properties +29 -7
  28. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_bg.properties +29 -7
  29. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ca.properties +29 -7
  30. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cnr.properties +29 -7
  31. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cs.properties +29 -7
  32. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cy.properties +29 -7
  33. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_da.properties +29 -7
  34. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_de.properties +29 -7
  35. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_el.properties +29 -7
  36. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en.properties +29 -7
  37. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_GB.properties +29 -7
  38. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saprigi.properties +29 -7
  39. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +29 -7
  40. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es_MX.properties +29 -7
  41. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_et.properties +29 -7
  42. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fi.properties +29 -7
  43. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr.properties +30 -8
  44. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr_CA.properties +31 -9
  45. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hi.properties +29 -7
  46. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hr.properties +30 -8
  47. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hu.properties +29 -7
  48. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_id.properties +29 -7
  49. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_it.properties +29 -7
  50. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_iw.properties +29 -7
  51. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +29 -7
  52. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_kk.properties +29 -7
  53. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ko.properties +29 -7
  54. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lt.properties +29 -7
  55. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lv.properties +29 -7
  56. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_mk.properties +29 -7
  57. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ms.properties +29 -7
  58. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_nl.properties +30 -8
  59. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_no.properties +29 -7
  60. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pl.properties +29 -7
  61. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt.properties +29 -7
  62. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt_PT.properties +29 -7
  63. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ro.properties +29 -7
  64. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ru.properties +29 -7
  65. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sh.properties +29 -7
  66. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sk.properties +29 -7
  67. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +29 -7
  68. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sr.properties +29 -7
  69. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sv.properties +29 -7
  70. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_th.properties +29 -7
  71. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_tr.properties +29 -7
  72. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +29 -7
  73. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_vi.properties +29 -7
  74. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +29 -7
  75. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +29 -7
  76. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
  77. package/src/sap/suite/ui/generic/template/library.js +1 -1
  78. package/src/sap/suite/ui/generic/template/themes/base/ObjectPage.less +30 -4
  79. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/ObjectPageSectionHandler.js +0 -282
  80. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillNonUpdatableSmartForm.fragment.xml +0 -18
  81. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillUpdatebleSmartForm.fragment.xml +0 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapui5/sap.suite.ui.generic.template",
3
- "version": "1.148.0",
3
+ "version": "1.148.2",
4
4
  "description": "SAPUI5 Library sap.suite.ui.generic.template",
5
5
  "keywords": [
6
6
  "sapui5",
@@ -7,7 +7,7 @@
7
7
 
8
8
  (c) Copyright 2009-2015 SAP SE. All rights reserved
9
9
  </copyright>
10
- <version>1.148.0</version>
10
+ <version>1.148.2</version>
11
11
 
12
12
  <documentation>Library with generic Suite UI templates.</documentation>
13
13
 
@@ -23,7 +23,7 @@ KPI_TOOLTIP_CRITICAL={0} {1}\nStatut\: risque
23
23
 
24
24
  KPI_DETERMINING_ERROR={0}\nImpossible de d\u00E9terminer la valeur
25
25
 
26
- KPI_DETERMINING_WARNING={0}\nDonn\u00E9es non valides ou introuvables
26
+ KPI_DETERMINING_WARNING={0}\nDonn\u00E9es invalides ou introuvables
27
27
 
28
28
  KPI_AUTHORIZATION_ISSUE=Probl\u00E8me d'autorisation
29
29
 
@@ -172,7 +172,7 @@ M_VISUAL_FILTER_HIDDEN_MEASURE=Impossible de charger le filtre visuel. La mesure
172
172
 
173
173
  REQUIRED_VH_FIELDS_OVERLAY_MESSAGE=Impossible de charger les donn\u00E9es car des champs obligatoires sont manquants. Contactez votre administrateur.
174
174
 
175
- INVALID_MEASURE_DONUT_MESSAGE=Mesure non valide trouv\u00E9e pour graphique en anneaux. La mesure doit \u00EAtre cumulative et positive.
175
+ INVALID_MEASURE_DONUT_MESSAGE=Mesure invalide trouv\u00E9e pour graphique en anneaux. La mesure doit \u00EAtre cumulative et positive.
176
176
 
177
177
  SHARE=Partager
178
178
 
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.148.0"
11
+ "version": "1.148.2"
12
12
  },
13
13
  "title": "{{TITLE}}",
14
14
  "description": "{{DESCRIPTION}}",
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.148.0"
11
+ "version": "1.148.2"
12
12
  },
13
13
  "title": "Canvas",
14
14
  "description": "Canvas Page",
@@ -939,9 +939,12 @@ sap.ui.define([
939
939
  var oTempModel = oTemplateUtils.oComponentUtils.getTemplatePrivateModel();
940
940
  if (oTempModel.getProperty("/listReport/filterMode") === "easyFilter") {
941
941
  oSmartFilterbar.setVisible(false);
942
- var oTemplatePrivateModel = oTemplateUtils.oComponentUtils.getTemplatePrivateModel();
943
- oTemplatePrivateModel.setProperty("/listReport/firstSelection", true);
944
- oTemplatePrivateModel.setProperty("/generic/bDataAreShownInTable", false);
942
+ // Only show gray overlay when data in table is present.
943
+ // filters scenario where gray overlay shows up when No data Illustrated msg is rendered
944
+ if (oTempModel.getProperty("/generic/bDataAreShownInTable")) {
945
+ oTempModel.setProperty("/listReport/firstSelection", true);
946
+ oTempModel.setProperty("/generic/bDataAreShownInTable", false);
947
+ }
945
948
  } else {
946
949
  PXFeedback.triggerPXIntegration("toggleSwitchV2");
947
950
  oSmartFilterbar.setVisible(true);
@@ -5,7 +5,7 @@ DESCRIPTION=Rapport de liste
5
5
 
6
6
  ALL_OBJECTS=Tous
7
7
 
8
- ALL_OBJECTS_HIDING_DRAFT=Toutes (les versions pr\u00E9liminaires masqu\u00E9es)
8
+ ALL_OBJECTS_HIDING_DRAFT=Tous (versions pr\u00E9liminaires masqu\u00E9es)
9
9
 
10
10
  UNCHANGED=Non modifi\u00E9
11
11
 
@@ -8,7 +8,7 @@
8
8
  "i18n": "i18n/i18n.properties",
9
9
  "applicationVersion": {
10
10
  "__comment": "applicationVersion oder componentversion??",
11
- "version": "1.148.0"
11
+ "version": "1.148.2"
12
12
  },
13
13
  "title": "{{TITLE}}",
14
14
  "description": "{{DESCRIPTION}}",
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.148.0"
9
+ "version": "1.148.2"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -120,19 +120,7 @@
120
120
  </template:if>
121
121
  </template:repeat>
122
122
 
123
- <uxap:ObjectPageHeaderActionButton id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'Summarize'}) }"
124
- text="{i18n>SUMMARIZE}"
125
- icon="sap-icon://ai"
126
- hideText="false"
127
- importance="High"
128
- enabled="{ui>/enabled}"
129
- press="._templateEventHandlers.onSummarize"
130
- ariaHasPopup="Dialog"
131
- fesr:press="fe:sum:summarize"
132
- type="Ghost"
133
- dt:designtime="not-adaptable"
134
- visible="{_templPrivGlobal>/generic/fioriAI/isSummarizationEnabled}" />
135
- <template:if test="{= !${parameter>/manifest/sap.ui.generic.app/pages/0/component/settings/treeTable}}">
123
+ <template:if test="{= !${parameter>/manifest/sap.ui.generic.app/pages/0/component/settings/treeTable}}">
136
124
  <template:if test="{parts: [{path: 'entitySet>Org.OData.Capabilities.V1.UpdateRestrictions'}, {path: 'entitySet>'}, {path: 'parameter>/treeNode/page/navigation/edit/target'}, {path: 'parameter>/treeNodeAncestors'}, {path: 'parameter>/isDraftEnabled'}], formatter: 'AHActionButtons.isEditButtonRequired'}">
137
125
  <uxap:ObjectPageHeaderActionButton
138
126
  id="EasyFill"
@@ -150,6 +138,18 @@
150
138
  />
151
139
  </template:if>
152
140
  </template:if>
141
+ <uxap:ObjectPageHeaderActionButton id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'Summarize'}) }"
142
+ text="{i18n>SUMMARIZE}"
143
+ icon="sap-icon://ai"
144
+ hideText="false"
145
+ importance="High"
146
+ enabled="{ui>/enabled}"
147
+ press="._templateEventHandlers.onSummarize"
148
+ ariaHasPopup="Dialog"
149
+ fesr:press="fe:sum:summarize"
150
+ type="Ghost"
151
+ dt:designtime="not-adaptable"
152
+ visible="{_templPrivGlobal>/generic/fioriAI/isSummarizationEnabled}" />
153
153
  <template:if test="{parameter>/settings/showRelatedApps}">
154
154
  <uxap:ObjectPageHeaderActionButton id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'RelatedApps'}) }"
155
155
  text="{i18n>RELATED_APPS}"
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.148.0"
9
+ "version": "1.148.2"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.148.0"
9
+ "version": "1.148.2"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -27,6 +27,7 @@ sap.ui.define([
27
27
  var aBasicFilters = [];
28
28
  var oSmartFilterBar = oControl;
29
29
  var oEasyFilterCallbacks = null;
30
+ var oPendingEasyFilterState = null;
30
31
 
31
32
  var oVariantManagementInitializedPromise;
32
33
 
@@ -86,6 +87,11 @@ sap.ui.define([
86
87
  filterMode: oCustomData[dataPropertyNameGeneric].filterMode,
87
88
  easyFilter: oCustomData[dataPropertyNameGeneric].easyFilter
88
89
  });
90
+ } else {
91
+ oPendingEasyFilterState = {
92
+ filterMode: oCustomData[dataPropertyNameGeneric].filterMode,
93
+ easyFilter: oCustomData[dataPropertyNameGeneric].easyFilter
94
+ };
89
95
  }
90
96
  });
91
97
 
@@ -142,7 +148,8 @@ sap.ui.define([
142
148
  .map(oFilterItem => oFilterItem.getName()),
143
149
  ...aRemovedFromStandard
144
150
  ])],
145
- customFilters: mParams.oCustomFiltersWrapper.getState()
151
+ customFilters: mParams.oCustomFiltersWrapper.getState(),
152
+ easyFilterState: oEasyFilterCallbacks ? oEasyFilterCallbacks.getState() : null
146
153
  };
147
154
  }
148
155
 
@@ -175,6 +182,14 @@ sap.ui.define([
175
182
 
176
183
  mParams.oCustomFiltersWrapper.setState(oState && oState.customFilters);
177
184
 
185
+ if (oState && oState.easyFilterState) {
186
+ if (oEasyFilterCallbacks) {
187
+ oEasyFilterCallbacks.setState(oState.easyFilterState);
188
+ } else {
189
+ oPendingEasyFilterState = oState.easyFilterState;
190
+ }
191
+ }
192
+
178
193
  // set visibility
179
194
  // TODO:
180
195
  // - How to deal with old states (not containing all information about visibility) -> legacy state handler?
@@ -250,6 +265,10 @@ sap.ui.define([
250
265
  setSVMWrapperCallbacks: setSVMWrapperCallbacks,
251
266
  setEasyFilterCallbacks: function(oCallbacks) {
252
267
  oEasyFilterCallbacks = oCallbacks;
268
+ if (oPendingEasyFilterState) {
269
+ oEasyFilterCallbacks.setState(oPendingEasyFilterState);
270
+ oPendingEasyFilterState = null;
271
+ }
253
272
  },
254
273
  bVMConnection: oSmartFilterBar.getSmartVariant(),
255
274
  suppressSelection: oSmartFilterBar.setSuppressSelection.bind(oSmartFilterBar), // if multiple reasons for suppressing overlap, a counter (to avoid to early resume) could be implemented here
@@ -959,7 +959,7 @@ sap.ui.define([
959
959
  * @public
960
960
  * @extends sap.ui.core.UIComponent
961
961
  * @author SAP SE
962
- * @version 1.148.0
962
+ * @version 1.148.2
963
963
  * @name sap.suite.ui.generic.template.lib.AppComponent
964
964
  */
965
965
  var oAppComponent = UIComponent.extend("sap.suite.ui.generic.template.lib.AppComponent", {
@@ -589,13 +589,6 @@ sap.ui.define(["sap/ui/base/Object",
589
589
  oServices.oTemplateCapabilities.oMessageButtonHelper.showMessagePopover();
590
590
  }
591
591
  }
592
- // Reset pending changes to prevent infinite loop when entering edit mode again.
593
- // Invalid values cause infinite loop because the pending changes (with invalid values) are resubmitted when the user clicks Edit, triggering the same error.
594
- var oContext = oController.getView().getBindingContext();
595
- var sContextPath = oContext && oContext.getPath();
596
- if (sContextPath && oModel && oModel.hasPendingChanges()) {
597
- oModel.resetChanges([sContextPath], undefined, true);
598
- }
599
592
  reject();
600
593
  });
601
594
  oBusyHelper.setBusy(oSubmitChange);
@@ -95,6 +95,7 @@ sap.ui.define(["sap/ui/base/Object",
95
95
  }
96
96
 
97
97
  var mVirtualItems = Object.create(null); // cache for virtual items passed to onListNavigateExtension.
98
+ var mCellHideRowsUpdateHandlers = Object.create(null); // keyed by SmartTable ID: stores rowsUpdated/updateFinished handler for cell hiding
98
99
  var oCurrentPaginatorInfo; // store paginator info while using the pagination
99
100
  function getPaginatorInfo(oTable, oRow, oState){
100
101
  var oRet = oCurrentPaginatorInfo;
@@ -1362,32 +1363,78 @@ sap.ui.define(["sap/ui/base/Object",
1362
1363
  /**
1363
1364
  * This method is called in the onDataReceived event of the specified SmartTable.
1364
1365
  * It handles everything which can be done regarding hiding of cells at this point in time.
1366
+ * It also ensures that cell-level hiding is reapplied when rows are updated (e.g. after
1367
+ * scrolling in a GridTable or after the SmartTable rebuilds its inner table columns).
1365
1368
  */
1366
1369
  function fnHideTableCells(oSmartTable, oHiddenColumnInfo) {
1370
+ if (!oHiddenColumnInfo.columnKeyToCellHiddenPath) {
1371
+ return;
1372
+ }
1373
+ fnApplyCellHiddenBindings(oSmartTable, oHiddenColumnInfo);
1374
+ // Ensure that cell hiding is reapplied whenever the inner table updates its rows.
1375
+ // This is needed because row controls may be recreated (e.g. when the SmartTable
1376
+ // rebuilds columns after setUiState or deactivateColumns), which causes previously
1377
+ // applied cell-level bindings to be lost.
1378
+ fnAttachRowsUpdateHandler(oSmartTable, oHiddenColumnInfo);
1379
+ }
1380
+
1381
+ /**
1382
+ * Applies cell-level visible bindings for all column keys in columnKeyToCellHiddenPath.
1383
+ */
1384
+ function fnApplyCellHiddenBindings(oSmartTable, oHiddenColumnInfo) {
1367
1385
  for (var sColumnKey in oHiddenColumnInfo.columnKeyToCellHiddenPath) {
1368
1386
  var sPath = oHiddenColumnInfo.columnKeyToCellHiddenPath[sColumnKey];
1369
1387
  fnHandleTableCellVisibility(oSmartTable, sColumnKey, sPath);
1370
1388
  }
1371
1389
  }
1372
1390
 
1391
+ /**
1392
+ * Attaches a one-time event handler to the inner table's row update event so that
1393
+ * cell-level hiding is reapplied when rows are recreated. The handler re-attaches
1394
+ * itself on every dataReceived to keep working across rebinds.
1395
+ */
1396
+ function fnAttachRowsUpdateHandler(oSmartTable, oHiddenColumnInfo) {
1397
+ var oTable = oSmartTable.getTable();
1398
+ var sSmartTableId = oSmartTable.getId();
1399
+ var sEventName = controlHelper.isUiTable(oTable) ? "rowsUpdated" : "updateFinished";
1400
+ // Detach any previously attached handler to avoid duplicates
1401
+ if (mCellHideRowsUpdateHandlers[sSmartTableId]) {
1402
+ oTable.detachEvent(sEventName, mCellHideRowsUpdateHandlers[sSmartTableId]);
1403
+ }
1404
+ mCellHideRowsUpdateHandlers[sSmartTableId] = function () {
1405
+ fnApplyCellHiddenBindings(oSmartTable, oHiddenColumnInfo);
1406
+ };
1407
+ oTable.attachEvent(sEventName, mCellHideRowsUpdateHandlers[sSmartTableId]);
1408
+ }
1409
+
1373
1410
  /**
1374
1411
  * This method is called for each Row of Table,to control the visibility of the Cell based on the Hidden property in LineItem.
1375
1412
  */
1376
1413
  function fnHandleTableCellVisibility(oSmartTable, sColumnKey, sPath) {
1377
1414
  var oSmartTableHandler = oServices.oPresentationControlHandlerFactory.getPresentationControlHandler(oSmartTable);
1378
1415
  var oTable = oSmartTable.getTable();
1379
- var aItems = oTable.getRows ? oTable.getRows() : oTable.getItems();
1416
+ var aItems = controlHelper.isUiTable(oTable) ? oTable.getRows() : oTable.getItems();
1380
1417
  var oColumn = oSmartTableHandler.getColumnByKey(sColumnKey);
1381
1418
  //if the column is visible in the table, then only we bind the visible property of the cell
1382
1419
  if (oColumn && oColumn.getVisible()){
1383
1420
  aItems.forEach(function(oItem) {
1384
1421
  var oCell = oItem.getCells()[oTable.indexOfColumn(oColumn)];
1385
- oCell && oCell.bindProperty("visible", {
1386
- path: sPath,
1387
- formatter: function (bIsHidden) {
1388
- return !bIsHidden;
1422
+ if (oCell) {
1423
+ // Only apply the binding if it is not already set with the correct path.
1424
+ // This avoids unnecessary teardown/recreation during scroll (rowsUpdated),
1425
+ // while still applying the binding to new cell instances created after a
1426
+ // column rebuild. If a different visible binding already exists (e.g. from
1427
+ // the application), we overwrite it with the cell-hiding binding.
1428
+ var oExistingBinding = oCell.getBindingInfo("visible");
1429
+ if (!oExistingBinding || oExistingBinding.parts[0].path !== sPath) {
1430
+ oCell.bindProperty("visible", {
1431
+ path: sPath,
1432
+ formatter: function (bIsHidden) {
1433
+ return !bIsHidden;
1434
+ }
1435
+ });
1389
1436
  }
1390
- });
1437
+ }
1391
1438
  });
1392
1439
  }
1393
1440
  }
@@ -2901,6 +2948,10 @@ sap.ui.define(["sap/ui/base/Object",
2901
2948
  var fnRenderTeamsContactCollabOptions = testableHelper.testable(fnRenderTeamsContactCollabOptions, "fnRenderTeamsContactCollabOptions");
2902
2949
  var removeUnsupportedColumnsToExport = testableHelper.testable(removeUnsupportedColumnsToExport, "removeUnsupportedColumnsToExport");
2903
2950
  var fnAddMultiEditFieldGroupProperties = testableHelper.testable(fnAddMultiEditFieldGroupProperties,"fnAddMultiEditFieldGroupProperties");
2951
+ var fnHideTableCells = testableHelper.testable(fnHideTableCells, "fnHideTableCells");
2952
+ var fnApplyCellHiddenBindings = testableHelper.testable(fnApplyCellHiddenBindings, "fnApplyCellHiddenBindings");
2953
+ var fnAttachRowsUpdateHandler = testableHelper.testable(fnAttachRowsUpdateHandler, "fnAttachRowsUpdateHandler");
2954
+ var fnHandleTableCellVisibility = testableHelper.testable(fnHandleTableCellVisibility, "fnHandleTableCellVisibility");
2904
2955
  /* eslint-enable */
2905
2956
 
2906
2957
  return {
@@ -0,0 +1,216 @@
1
+ sap.ui.define([
2
+ "sap/suite/ui/generic/template/genericUtilities/FeLogger",
3
+ "sap/suite/ui/generic/template/genericUtilities/FeError"
4
+ ], function(FeLogger, FeError) {
5
+ "use strict";
6
+
7
+ var sClassName = "lib.ai.EasyFill.EasyFillAIOrchestrator";
8
+ var oLogger = new FeLogger(sClassName).getLogger();
9
+
10
+ /**
11
+ * EasyFillAIOrchestrator
12
+ *
13
+ * Responsible for:
14
+ * 1. Submitting user input text to the AI (LLM) service and returning parsed results.
15
+ * 2. Post-processing the AI response: date conversion, splitting simple vs. collection fields.
16
+ * 3. Building the complete field mapping payload (entity fields + collection fields) to send to the LLM.
17
+ *
18
+ * This module contains no UI logic — it only bridges the user input and AI service.
19
+ * All UI state updates after the AI call are handled by the caller (EasyFillHandler / EasyFillDialogController).
20
+ */
21
+ return {
22
+
23
+ /**
24
+ * Builds the complete LLM field mapping by combining main entity fields and collection (table) fields.
25
+ * Delegates to EasyFillFieldCollector for the actual metadata extraction.
26
+ *
27
+ * @param {object} oTemplateUtils - FE template utilities (used for entity type lookup)
28
+ * @param {object} oController - MVC controller instance
29
+ * @param {object} oObjectPage - the ObjectPage control
30
+ * @param {object} oObjectPageModel - the OData model of the ObjectPage
31
+ * @param {object} oObjectPageContext - current ObjectPage binding context
32
+ * @param {object} oFieldCollector - EasyFillFieldCollector instance
33
+ * @param {object} mCollectionState - mutable collection state object (passed into appendCollectionMap)
34
+ * @returns {object} mFieldMapping — flat map of all fields to send to the LLM
35
+ */
36
+ buildFieldMapping: function(oTemplateUtils, oController, oObjectPage, oObjectPageModel, oObjectPageContext, oFieldCollector, mCollectionState) {
37
+ var oEntityType = oTemplateUtils.oCommonUtils.getMetaModelEntityType(
38
+ oController.getOwnerComponent().getEntitySet()
39
+ );
40
+
41
+ /**
42
+ * Resolves the display label for an OData property.
43
+ * Prefers the Common.Label annotation, falls back to sap:label attribute.
44
+ *
45
+ * @param {object} oProperty - OData property metadata
46
+ * @returns {string} label string
47
+ */
48
+ var fnGetLabel = function(oProperty) {
49
+ if (oProperty["com.sap.vocabularies.Common.v1.Label"]) {
50
+ // Use the annotation helper to format the label expression
51
+ try {
52
+ var AnnotationHelperModel = sap.ui.require("sap/ui/model/odata/AnnotationHelper");
53
+ if (AnnotationHelperModel) {
54
+ return AnnotationHelperModel.format(oObjectPageContext, oProperty["com.sap.vocabularies.Common.v1.Label"]);
55
+ }
56
+ } catch (e) {
57
+ oLogger.warning("buildFieldMapping: could not format annotation label for " + oProperty.name);
58
+ }
59
+ }
60
+ return oProperty["sap:label"] || oProperty.name;
61
+ };
62
+
63
+ // Build entity set field map (simple fields)
64
+ var mFieldMapping = oFieldCollector.getEntitySetMap(oEntityType, oObjectPageContext, fnGetLabel);
65
+
66
+ // Append collection (SmartTable) fields and update collection state tracking maps
67
+ oFieldCollector.appendCollectionMap(
68
+ mFieldMapping,
69
+ oObjectPage,
70
+ oObjectPageModel,
71
+ oTemplateUtils,
72
+ mCollectionState,
73
+ fnGetLabel
74
+ );
75
+
76
+ return mFieldMapping;
77
+ },
78
+
79
+ /**
80
+ * Sends the user's free-text input to the AI service and returns the structured result.
81
+ * The AI service is accessed via oTemplateUtils.oServices.oFioriAIHandler.
82
+ *
83
+ * @param {string} sInputText - the user's free-text input from the EasyFill textarea
84
+ * @param {object} mFieldMapping - the complete field mapping built by buildFieldMapping()
85
+ * @param {object} oTemplateUtils - FE template utilities (used to access oFioriAIHandler)
86
+ * @returns {Promise<object>} AI service result: { success: boolean, data: object }
87
+ */
88
+ submitToAI: async function(sInputText, mFieldMapping, oTemplateUtils) {
89
+ oLogger.debug("submitToAI: sending input to AI service");
90
+ try {
91
+ var aiCallResult = await oTemplateUtils.oServices.oFioriAIHandler.fioriaiLib.EasyFill.extractFieldValuesFromText(
92
+ sInputText,
93
+ mFieldMapping
94
+ );
95
+ return aiCallResult;
96
+ } catch (e) {
97
+ oLogger.error("submitToAI: AI call failed: " + (e && e.message));
98
+ return { success: false, data: {} };
99
+ }
100
+ },
101
+
102
+ /**
103
+ * Converts date-like string values in the AI response to JavaScript Date objects,
104
+ * based on the OData data type declared in the field mapping.
105
+ * Handles Edm.DateTimeOffset and Edm.DateTime types.
106
+ *
107
+ * @param {object} aiCallResult - the raw AI service result ({ success, data })
108
+ * @param {object} mFieldMapping - the field mapping used during the AI call
109
+ */
110
+ formatDateValues: function(aiCallResult, mFieldMapping) {
111
+ if (!aiCallResult || !aiCallResult.success || !aiCallResult.data) {
112
+ return;
113
+ }
114
+ Object.keys(aiCallResult.data).forEach(function(sKey) {
115
+ var oFieldMeta = mFieldMapping[sKey];
116
+ if (!oFieldMeta) { return; }
117
+ var sDataType = oFieldMeta.dataType;
118
+ if (sDataType === "Edm.DateTimeOffset" || sDataType === "Edm.DateTime") {
119
+ var vValue = aiCallResult.data[sKey];
120
+ if (vValue && typeof vValue === "string") {
121
+ aiCallResult.data[sKey] = new Date(vValue);
122
+ oLogger.debug("formatDateValues: converted field '" + sKey + "' to Date");
123
+ }
124
+ }
125
+ });
126
+ },
127
+
128
+ /**
129
+ * Splits the flat AI response data into two buckets:
130
+ * - simpleFields: scalar field values for the main entity (SmartForm fields)
131
+ * - collectionFields: row-level updates for SmartTable collections
132
+ *
133
+ * Collection fields are identified by the isCollection flag in the field mapping.
134
+ * For tables that allow creation (mCollectionState.mCollectionAllowsCreation), rows
135
+ * without _rowIndex or _contextPath are treated as new rows to be created.
136
+ * Only one new row per table is supported; extra new rows are flagged via multipleNewRows.
137
+ * Tables where the AI proposed new rows but creation is not allowed are tracked in
138
+ * collectionsWithRejectedNewRows so the renderer can show a per-table warning strip.
139
+ *
140
+ * @param {object} oAiData - the AI response data map { fieldName: value | rowArray }
141
+ * @param {object} mFieldMapping - the complete field mapping
142
+ * @param {object} oFieldCollector - EasyFillFieldCollector (used for SmartTable validation)
143
+ * @param {object} oObjectPage - the ObjectPage control (used for SmartTable validation)
144
+ * @param {object} mCollectionState - collection tracking state (used for allowsCreation check)
145
+ * @returns {{ simpleFields: object, collectionFields: object, attemptedMultipleNewRows: boolean, collectionsWithRejectedNewRows: object }}
146
+ */
147
+ splitAIResultByCollection: function(oAiData, mFieldMapping, oFieldCollector, oObjectPage, mCollectionState) {
148
+ var oSplitResult = {
149
+ simpleFields: {},
150
+ collectionFields: {},
151
+ attemptedMultipleNewRows: false,
152
+ // Map of { navProperty: "all" | "mixed" } for tables where AI proposed new rows
153
+ // but creation is not allowed. "all" = only new rows proposed; "mixed" = some
154
+ // existing updates + some rejected new rows.
155
+ collectionsWithRejectedNewRows: {}
156
+ };
157
+
158
+ Object.keys(oAiData || {}).forEach(function(sFieldName) {
159
+ var oFieldMeta = mFieldMapping[sFieldName];
160
+ var vFieldValue = oAiData[sFieldName];
161
+
162
+ // Determine if this field value is a collection (array of row updates)
163
+ var aCollectionRows = null;
164
+ if (Array.isArray(vFieldValue)) {
165
+ aCollectionRows = vFieldValue;
166
+ } else if (vFieldValue && Array.isArray(vFieldValue.rows)) {
167
+ aCollectionRows = vFieldValue.rows;
168
+ }
169
+
170
+ if (oFieldMeta && oFieldMeta.isCollection === true && aCollectionRows) {
171
+ var bAllowsCreation = !!(mCollectionState && mCollectionState.mCollectionAllowsCreation &&
172
+ mCollectionState.mCollectionAllowsCreation[sFieldName]);
173
+
174
+ // Separate existing-row updates (have _rowIndex or _contextPath) from new rows
175
+ var aExistingRowUpdates = aCollectionRows.filter(function(oRow) {
176
+ return oRow && typeof oRow === "object" &&
177
+ (typeof oRow._contextPath === "string" || typeof oRow._rowIndex === "number");
178
+ });
179
+ var aRawNewRows = aCollectionRows.filter(function(oRow) {
180
+ return oRow && typeof oRow === "object" &&
181
+ typeof oRow._contextPath !== "string" &&
182
+ typeof oRow._rowIndex !== "number";
183
+ });
184
+
185
+ // Track tables where AI proposed new rows that cannot be created
186
+ if (!bAllowsCreation && aRawNewRows.length > 0) {
187
+ var sRejectionType = aExistingRowUpdates.length === 0 ? "all" : "mixed";
188
+ oSplitResult.collectionsWithRejectedNewRows[sFieldName] = sRejectionType;
189
+ }
190
+
191
+ var aNewRows = bAllowsCreation ? aRawNewRows : [];
192
+
193
+ // Cap new rows to one per table; flag if the AI proposed more
194
+ if (aNewRows.length > 1) {
195
+ oSplitResult.attemptedMultipleNewRows = true;
196
+ aNewRows = [aNewRows[0]];
197
+ }
198
+
199
+ var aRowUpdates = aExistingRowUpdates.concat(aNewRows);
200
+
201
+ var oValidation = oFieldCollector.isValidSmartTable(oFieldMeta.entitySet, oObjectPage);
202
+ if (aRowUpdates.length > 0 && oValidation.isValid) {
203
+ oSplitResult.collectionFields[sFieldName] = aRowUpdates;
204
+ oLogger.debug("splitAIResultByCollection: accepted collection field '" + sFieldName + "' with " +
205
+ aExistingRowUpdates.length + " updates and " + aNewRows.length + " new row(s)");
206
+ }
207
+ } else {
208
+ // Scalar field → goes to simpleFields
209
+ oSplitResult.simpleFields[sFieldName] = vFieldValue;
210
+ }
211
+ });
212
+
213
+ return oSplitResult;
214
+ }
215
+ };
216
+ });