@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.
- package/package.json +1 -1
- package/src/sap/suite/ui/generic/template/.library +1 -1
- package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_fr_CA.properties +2 -2
- 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/i18n/i18n_fr.properties +1 -1
- 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/ObjectPage/view/fragments/Actions.fragment.xml +13 -13
- 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 +20 -1
- package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
- package/src/sap/suite/ui/generic/template/lib/CRUDManager.js +0 -7
- package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +57 -6
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillAIOrchestrator.js +216 -0
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillApplyHandler.js +325 -0
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillDialogController.js +358 -0
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFieldCollector.js +848 -0
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillFormRenderer.js +292 -0
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +652 -1071
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillTableRenderer.js +940 -0
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +41 -26
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +90 -73
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +35 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ar.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_bg.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ca.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cnr.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cs.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_cy.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_da.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_de.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_el.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_GB.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_en_US_saprigi.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_es_MX.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_et.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fi.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr.properties +30 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_fr_CA.properties +31 -9
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hi.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hr.properties +30 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_hu.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_id.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_it.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_iw.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_kk.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ko.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lt.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_lv.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_mk.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ms.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_nl.properties +30 -8
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_no.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pl.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_pt_PT.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ro.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ru.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sh.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sk.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sl.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sr.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_sv.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_th.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_tr.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_vi.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +29 -7
- package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +29 -7
- 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 +30 -4
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/ObjectPageSectionHandler.js +0 -282
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillNonUpdatableSmartForm.fragment.xml +0 -18
- package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillUpdatebleSmartForm.fragment.xml +0 -15
package/package.json
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
|
@@ -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
|
-
|
|
943
|
-
|
|
944
|
-
|
|
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);
|
|
@@ -120,19 +120,7 @@
|
|
|
120
120
|
</template:if>
|
|
121
121
|
</template:repeat>
|
|
122
122
|
|
|
123
|
-
<
|
|
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}"
|
|
@@ -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.
|
|
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
|
|
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
|
-
|
|
1386
|
-
path
|
|
1387
|
-
|
|
1388
|
-
|
|
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
|
+
});
|