@sapui5/sap.suite.ui.generic.template 1.147.1 → 1.148.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 (43) 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/controller/ControllerImplementation.js +5 -3
  4. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_bg.properties +3 -3
  5. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_da.properties +3 -3
  6. package/src/sap/suite/ui/generic/template/AnalyticalListPage/i18n/i18n_id.properties +2 -2
  7. package/src/sap/suite/ui/generic/template/AnalyticalListPage/manifest.json +1 -1
  8. package/src/sap/suite/ui/generic/template/Canvas/manifest.json +1 -1
  9. package/src/sap/suite/ui/generic/template/ListReport/controller/ControllerImplementation.js +32 -3
  10. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_id.properties +1 -1
  11. package/src/sap/suite/ui/generic/template/ListReport/i18n/i18n_uk.properties +1 -1
  12. package/src/sap/suite/ui/generic/template/ListReport/manifest.json +1 -1
  13. package/src/sap/suite/ui/generic/template/ObjectPage/Component.js +4 -0
  14. package/src/sap/suite/ui/generic/template/ObjectPage/controller/ControllerImplementation.js +57 -25
  15. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n.properties +6 -0
  16. package/src/sap/suite/ui/generic/template/ObjectPage/i18n/i18n_en_US_saprigi.properties +4 -0
  17. package/src/sap/suite/ui/generic/template/ObjectPage/manifest.json +6 -1
  18. package/src/sap/suite/ui/generic/template/ObjectPage/templateSpecificPreparationHelper.js +35 -19
  19. package/src/sap/suite/ui/generic/template/ObjectPage/view/fragments/Footer.fragment.xml +103 -42
  20. package/src/sap/suite/ui/generic/template/QuickCreate/manifest.json +1 -1
  21. package/src/sap/suite/ui/generic/template/QuickView/manifest.json +1 -1
  22. package/src/sap/suite/ui/generic/template/fragments/EasyFilter.fragment.xml +3 -0
  23. package/src/sap/suite/ui/generic/template/genericUtilities/controlHelper.js +30 -29
  24. package/src/sap/suite/ui/generic/template/genericUtilities/controlStateWrapperFactory/SmartFilterBarWrapper.js +15 -0
  25. package/src/sap/suite/ui/generic/template/lib/AppComponent.js +1 -1
  26. package/src/sap/suite/ui/generic/template/lib/CRUDHelper.js +93 -55
  27. package/src/sap/suite/ui/generic/template/lib/CRUDManager.js +7 -0
  28. package/src/sap/suite/ui/generic/template/lib/CommonEventHandlers.js +19 -13
  29. package/src/sap/suite/ui/generic/template/lib/CommonUtils.js +4 -1
  30. package/src/sap/suite/ui/generic/template/lib/ComponentUtils.js +17 -7
  31. package/src/sap/suite/ui/generic/template/lib/StableIdDefinition.js +35 -34
  32. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/EasyFillHandler.js +853 -130
  33. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/ObjectPageSectionHandler.js +282 -0
  34. package/src/sap/suite/ui/generic/template/lib/ai/EasyFill/fragments/EasyFillDialog.fragment.xml +138 -72
  35. package/src/sap/suite/ui/generic/template/lib/ai/EasyFilterBarHandler.js +409 -22
  36. package/src/sap/suite/ui/generic/template/lib/i18n/i18n.properties +21 -0
  37. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_ja.properties +6 -6
  38. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_uk.properties +3 -3
  39. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_CN.properties +6 -6
  40. package/src/sap/suite/ui/generic/template/lib/i18n/i18n_zh_TW.properties +6 -6
  41. package/src/sap/suite/ui/generic/template/lib/navigation/NavigationController.js +1 -1
  42. package/src/sap/suite/ui/generic/template/library.js +25 -2
  43. package/src/sap/suite/ui/generic/template/themes/base/ObjectPage.less +14 -0
@@ -23,36 +23,59 @@
23
23
 
24
24
  <template:if test="{= ${parameter>/isDraftEnabled} &amp;&amp; ${entitySet>com.sap.vocabularies.Common.v1.DraftRoot} }">
25
25
  <template:if test="{= !${device>/system/desktop} &amp;&amp; (${device>/system/tablet} || ${device>/system/phone})}">
26
- <MenuButton id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'ActivateMenu'})}"
27
- text="{= ${ui>/createMode} ? ${i18n>CREATE} : ${i18n>SAVE}}"
28
- buttonMode="Split"
29
- defaultAction="._templateEventHandlers.onSave"
30
- useDefaultActionOnly="true"
31
- enabled="{ui>/enabled}"
32
- type="Emphasized"
33
- visible="{ui>/editable}">
34
- <menu>
35
- <Menu>
36
- <MenuItem text="{i18n>VALIDATE_DRAFT}" press="._templateEventHandlers.onValidateDraft" />
37
- </Menu>
38
- </menu>
39
- </MenuButton>
40
- </template:if>
41
-
42
- <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/Save" var="saveAction">
43
- <Button id="{saveAction>id}"
44
- text="{saveAction>text}"
45
- type="{saveAction>type}"
46
- enabled="{ui>/enabled}"
47
- fesr:press="fe:save"
48
- press="{saveAction>press}"
49
- visible="{saveAction>visible}" />
50
- <template:if test="!${saveAction>isStandardAction}">
51
- <layoutData>
52
- <OverflowToolbarLayoutData priority="{path: 'saveAction>importance', formatter: 'AH.getToolbarButtonPriorityFromImportance'}"/>
53
- </layoutData>
26
+ <template:then>
27
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/Save" var="saveAction">
28
+ <MenuButton id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'ActivateMenu'})}"
29
+ text="{saveAction>text}"
30
+ buttonMode="Split"
31
+ defaultAction="._templateEventHandlers.onSave"
32
+ useDefaultActionOnly="true"
33
+ enabled="{ui>/enabled}"
34
+ type="Emphasized"
35
+ visible="{ui>/editable}">
36
+ <menu>
37
+ <Menu>
38
+ <template:if test="{= ${parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack} }">
39
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack" var="saveAndBackAction">
40
+ <MenuItem id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'ActivateAndBackMenu'})}"
41
+ text="{saveAndBackAction>text}"
42
+ press="{saveAndBackAction>callbackName}" />
43
+ </template:with>
44
+ </template:if>
45
+ <MenuItem text="{i18n>VALIDATE_DRAFT}" press="._templateEventHandlers.onValidateDraft" />
46
+ </Menu>
47
+ </menu>
48
+ </MenuButton>
49
+ </template:with>
50
+ </template:then>
51
+ <template:else>
52
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/Save" var="saveAction">
53
+ <Button id="{saveAction>id}"
54
+ text="{saveAction>text}"
55
+ type="{saveAction>type}"
56
+ enabled="{ui>/enabled}"
57
+ fesr:press="fe:save"
58
+ press="{saveAction>press}"
59
+ visible="{saveAction>visible}" />
60
+ <template:if test="!${saveAction>isStandardAction}">
61
+ <layoutData>
62
+ <OverflowToolbarLayoutData priority="{path: 'saveAction>importance', formatter: 'AH.getToolbarButtonPriorityFromImportance'}"/>
63
+ </layoutData>
64
+ </template:if>
65
+ </template:with>
66
+ <template:if test="{= ${parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack} }">
67
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack" var="saveAndBackAction">
68
+ <Button id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'CommonAction', sAction: 'saveAndBack'})}"
69
+ text="{saveAndBackAction>text}"
70
+ press="{saveAndBackAction>press}"
71
+ visible="{saveAndBackAction>visible}"
72
+ enabled="{ui>/enabled}"
73
+ fesr:press="fe:saveAndBack"
74
+ type="Transparent" />
75
+ </template:with>
54
76
  </template:if>
55
- </template:with>
77
+ </template:else>
78
+ </template:if>
56
79
 
57
80
  <Button id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'CommonAction', sAction: 'discard'})}"
58
81
  text="{i18n>ST_DISCARD_DRAFT_BTN}"
@@ -70,20 +93,58 @@
70
93
  </template:if>
71
94
 
72
95
  <template:if test="{= !${parameter>/isDraftEnabled} }">
73
- <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/Save" var="saveAction">
74
- <Button id="{saveAction>id}"
75
- text="{saveAction>text}"
76
- type="{saveAction>type}"
77
- fesr:press="fe:save"
78
- press="{saveAction>press}"
79
- visible="{saveAction>visible}" />
80
- <template:if test="!${saveAction>isStandardAction}">
81
- <layoutData>
82
- <OverflowToolbarLayoutData priority="{path: 'saveAction>importance', formatter: 'AH.getToolbarButtonPriorityFromImportance'}"/>
83
- </layoutData>
84
- </template:if>
85
- </template:with>
96
+ <template:if test="{= !${device>/system/desktop} &amp;&amp; (${device>/system/tablet} || ${device>/system/phone}) &amp;&amp; ${parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack}}">
97
+ <template:then>
98
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/Save" var="saveAction">
99
+ <MenuButton id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'ActivateMenu'})}"
100
+ text="{saveAction>text}"
101
+ buttonMode="Split"
102
+ defaultAction="{saveAction>callbackName}"
103
+ useDefaultActionOnly="true"
104
+ type="Emphasized"
105
+ visible="{saveAction>visible}">
106
+ <menu>
107
+ <Menu>
108
+ <template:if test="{= ${parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack} }">
109
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack" var="saveAndBackAction">
110
+ <MenuItem id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'ActivateAndBackMenu'})}"
111
+ text="{saveAndBackAction>text}"
112
+ press="{saveAndBackAction>callbackName}" />
113
+ </template:with>
114
+ </template:if>
115
+ </Menu>
116
+ </menu>
117
+ </MenuButton>
118
+ </template:with>
119
+ </template:then>
120
+ <template:else>
121
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/Save" var="saveAction">
122
+ <Button id="{saveAction>id}"
123
+ text="{saveAction>text}"
124
+ type="{saveAction>type}"
125
+ fesr:press="fe:save"
126
+ press="{saveAction>press}"
127
+ visible="{saveAction>visible}" />
128
+ <template:if test="!${saveAction>isStandardAction}">
129
+ <layoutData>
130
+ <OverflowToolbarLayoutData priority="{path: 'saveAction>importance', formatter: 'AH.getToolbarButtonPriorityFromImportance'}"/>
131
+ </layoutData>
132
+ </template:if>
133
+ </template:with>
86
134
 
135
+ <template:if test="{= ${parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack} }">
136
+ <template:with path="parameter>/templateSpecific/pageLevelActions/commandExecution/SaveAndBack" var="saveAndBackAction">
137
+ <Button id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'CommonAction', sAction: 'saveAndBack'})}"
138
+ text="{saveAndBackAction>text}"
139
+ press="{saveAndBackAction>press}"
140
+ visible="{saveAndBackAction>visible}"
141
+ enabled="{ui>/enabled}"
142
+ fesr:press="fe:saveAndBack"
143
+ type="Transparent" />
144
+ </template:with>
145
+ </template:if>
146
+ </template:else>
147
+ </template:if>
87
148
  <template:if test="{= ${parameter>/treeNode/level} === 1}">
88
149
  <Button id="{:= ${parameter>/stableId}.getStableId({type: 'ObjectPageAction', subType: 'SaveAndEdit'})}"
89
150
  text="{i18n>SAVE_AND_EDIT}"
@@ -6,7 +6,7 @@
6
6
  "type": "component",
7
7
  "i18n": "i18n/i18n.properties",
8
8
  "applicationVersion": {
9
- "version": "1.147.1"
9
+ "version": "1.148.0"
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.147.1"
9
+ "version": "1.148.0"
10
10
  },
11
11
  "title": "{{TITLE}}",
12
12
  "description": "{{DESCRIPTION}}",
@@ -5,6 +5,9 @@
5
5
  showValueHelp="._templateEventHandlers.onEasyFilterShowValueHelp"
6
6
  queryChanged="._templateEventHandlers.onEasyFilterQueryChanged"
7
7
  tokensChanged="._templateEventHandlers.onEasyFilterTokensChanged"
8
+ tokensChangedByUser="._templateEventHandlers.onEasyFilterTokensChangedByUser"
9
+ sortersChanged="._templateEventHandlers.onEasyFilterSortersChanged"
10
+ groupLevelsChanged="._templateEventHandlers.onEasyFilterGroupLevelsChanged"
8
11
  beforeQueryProcessing="._templateEventHandlers.onEasyFilterBeforeQueryProcessing"
9
12
  afterQueryProcessing="._templateEventHandlers.onEasyFilterAfterQueryProcessing"
10
13
  clearFilters="._templateEventHandlers.onEasyFilterClearFilters"
@@ -1,29 +1,29 @@
1
1
  sap.ui.define([
2
- "sap/ui/dom/getFirstEditableInput",
2
+ "sap/ui/dom/getFirstEditableInput",
3
3
  "sap/suite/ui/generic/template/genericUtilities/FeLogger",
4
4
  "sap/ui/core/Element",
5
5
  "sap/ui/table/plugins/MultiSelectionPlugin"
6
6
  ], function(getFirstEditableInput, FeLogger, Element, MultiSelectionPlugin) {
7
7
  "use strict";
8
-
8
+
9
9
  var oFeLogger = new FeLogger("genericUtilities.controlHelper");
10
10
  var oLogger = oFeLogger.getLogger();
11
-
11
+
12
12
  var byId = Element.getElementById;
13
-
13
+
14
14
  function isControlOfType(sPathToType, oControl){
15
15
  var FNClass = sap.ui.require(sPathToType);
16
16
  return typeof FNClass === "function" && (oControl instanceof FNClass);
17
17
  }
18
-
18
+
19
19
  function getUI5ControlForDomElement(oDom){
20
20
  for (; oDom; oDom = oDom.parentNode) {
21
21
  if (oDom.hasAttribute && oDom.hasAttribute("data-sap-ui")) {
22
22
  return byId(oDom.id);
23
23
  }
24
- }
24
+ }
25
25
  }
26
-
26
+
27
27
  function focusUI5Control(oControl, oFocusInfo){
28
28
  if (oControl && oControl.focus) {
29
29
  oLogger.debug("Set focus on control with id " + oControl.getId());
@@ -52,9 +52,9 @@ sap.ui.define([
52
52
  if (oTest !== oControl){
53
53
  oLogger.warning(oCurrentFocus ? ("Focus is now on control with id " + oCurrentFocus.getId()) : "There is no focus now");
54
54
  }
55
- }
55
+ }
56
56
  }
57
-
57
+
58
58
  function focusDom(oDom, oFocusInfo){
59
59
  var oUi5Control = getUI5ControlForDomElement(oDom);
60
60
  focusUI5Control(oUi5Control, oFocusInfo);
@@ -66,12 +66,12 @@ sap.ui.define([
66
66
  }
67
67
 
68
68
  // returns a Promise that resolves to the boolean information whether the SmartField is a possible focus target for input.
69
- function getSmartFieldIsFocussableForInputPromise(oSmartField) {
69
+ function getSmartFieldIsFocussableForInputPromise(oSmartField, isSmartForm) {
70
70
  return oSmartField._getComputedMetadata().then(function () {
71
71
  return (oSmartField.getMode() === "edit") && (oSmartField._getICRenderedPromise() || Promise.resolve());
72
72
  }).then(function () {
73
- var oFirstFocusableInput = !oSmartField._bEdmBoolDetected && getFirstEditableInput(oSmartField.getDomRef());
74
- return !(!oFirstFocusableInput || oFirstFocusableInput.type === "checkbox");
73
+ var oFirstFocusableInput = (!oSmartField._bEdmBoolDetected || isSmartForm) && getFirstEditableInput(oSmartField.getDomRef());
74
+ return !(!oFirstFocusableInput || (oFirstFocusableInput.type === "checkbox" && !isSmartForm));
75
75
  }).catch(function () {
76
76
  return false;
77
77
  });
@@ -82,12 +82,12 @@ sap.ui.define([
82
82
  function getControlWithFocus(){
83
83
  return getUI5ControlForDomElement(document.activeElement);
84
84
  }
85
-
85
+
86
86
  // Returns the parent of a given sap.ui.core.Element, but considers that for Components the parent is to be found via the oContainer property.
87
87
  function getParent(oElement){
88
88
  return oElement.getParent() || oElement.oContainer;
89
89
  }
90
-
90
+
91
91
  // If oChild is identified to be invisible, null is returned. Otherwise its parent is returned.
92
92
  // If the parent does not exist a faulty value is returned.
93
93
  // This is a heuristic method.
@@ -113,7 +113,7 @@ sap.ui.define([
113
113
  }
114
114
  return vRet;
115
115
  }
116
-
116
+
117
117
  // Return a list of all children of the given control (in the 'correct' order). Only implemented for certain control types.
118
118
  // For the other control types it returns null or an empty array depending on bAlwaysReturnAList.
119
119
  function getChildren(oControl, bAlwaysReturnAList){
@@ -127,7 +127,7 @@ sap.ui.define([
127
127
  return oControl.getBlocks().concat(oControl.getMoreBlocks());
128
128
  }
129
129
  if (isControlOfType("sap/ui/comp/smartform/Group", oControl)){
130
- return oControl.getFormElements();
130
+ return oControl.getFormElements();
131
131
  }
132
132
  if (isControlOfType("sap/ui/table/Column", oControl)){
133
133
  var aRet = oControl.getMultiLabels();
@@ -135,11 +135,11 @@ sap.ui.define([
135
135
  if (oLabel){
136
136
  aRet.push(oLabel);
137
137
  }
138
- return aRet;
139
- }
138
+ return aRet;
139
+ }
140
140
  return bAlwaysReturnAList ? [] : null;
141
141
  }
142
-
142
+
143
143
  // Sorter that compares the position of two child controls which have a common parent.
144
144
  // Returns a positive integer when oChild1 is larger, a negative number if oChild2 is larger, and 0 if they are identical.
145
145
  // Depends on getChildren() being implemented for commonParent. If this is not the case, at least a reproducable order is guaranteed.
@@ -160,13 +160,13 @@ sap.ui.define([
160
160
  }
161
161
  if (iPositionCompare & Node.DOCUMENT_POSITION_FOLLOWING){
162
162
  return -1;
163
- }
163
+ }
164
164
  }
165
165
  return 1 - 2 * (!oDomRef1 === !oDomRef2 ? oChild1.getId() < oChild2.getId() : !oDomRef2); // if we cannot determine a reasonable order we still want to have a reproducable order. Note that elements with DomRef must clearly be separated from those without.
166
166
  }
167
167
  return (iPos1 >= 0 && iPos2 >= 0) ? (iPos1 - iPos2) : (iPos2 - iPos1); // if only one child has been identified in the list of children it takes precedence.
168
168
  }
169
-
169
+
170
170
  // This function defines which instances of sap.ui.core.Element are relevant for investigation (Currently used in fnSearchInTree).
171
171
  // They must posess a property 'visible' (which is guaranteed for all instances of sap.ui.core.Control) which is true.
172
172
  // If they have a property 'enabled' this must be true as well.
@@ -176,7 +176,7 @@ sap.ui.define([
176
176
  return checkForRelevance(oCell);
177
177
  }) : (typeof oElement.getVisible === "function" && oElement.getVisible() && (typeof oElement.getEnabled !== "function" || oElement.getEnabled()));
178
178
  }
179
-
179
+
180
180
  // This function allows a depth-first search in an element tree starting with root oElement
181
181
  // Thereby, the following logic is applied
182
182
  // - Children of an element are determined by function getChildren in this class. If this provides an empty array method findElements of the element is used
@@ -188,14 +188,14 @@ sap.ui.define([
188
188
  // Note that mAlreadyAnalyzed will be updated by this function
189
189
  // fnHandleElement(oElement) is a function that will be called on all relevant elements of the tree.
190
190
  // This function can work asynchronously (i.e. return a Promise) or synchronously (i.e. return something which is not a Promise) on a case-by-case basis.
191
- // In the second case the return value will be considered as the result of the function. In the first case the value the Promise resolves to will be considered as the result.
191
+ // In the second case the return value will be considered as the result of the function. In the first case the value the Promise resolves to will be considered as the result.
192
192
  // If the result is a truthy value for one element this value is considered as the result of fnSearchInTree and the processing is stopped.
193
193
  // fnSearchInTree returns this result synchronously if all calls of fnHandleElement which have been performed until then have worked synchronously.
194
194
  // If the result of fnHandleElement is faulty the depth-first search of the tree proceeds. Thereby the processing of the subtree of oElement is
195
195
  // skipped if the result was exactly false. For other faulty values the subtree will be processed next.
196
196
  // Note that this process will never work on two elements in parallel. If the processing of one element is asynchronous the process is interrupted until
197
197
  // the result of this step is available. Only then the next element will be analyzed.
198
- // If fnHandleElement never results in a truthy value then fnSearchInTree results in null.
198
+ // If fnHandleElement never results in a truthy value then fnSearchInTree results in null.
199
199
  function fnSearchInTree(mAlreadyAnalyzed, oElement, fnHandleElement){
200
200
  mAlreadyAnalyzed = mAlreadyAnalyzed || Object.create(null);
201
201
  var sId = oElement.getId();
@@ -213,7 +213,7 @@ sap.ui.define([
213
213
  if (!aChildren){ // if getChildren does not care for the control type of oElement
214
214
  aChildren = oElement.findElements(false);
215
215
  aChildren.sort(fnSortChildControls.bind(null, oElement));
216
- }
216
+ }
217
217
  aChildren.some(function(oChild){
218
218
  vResult = fnSearchInTree(mAlreadyAnalyzed, oChild, fnHandleElement);
219
219
  return vResult; // If vResult is truthy it is either a Promise (which makes the processing asynchronous) or the result of fnSearchInTree. In both cases we should stop now.
@@ -233,12 +233,12 @@ sap.ui.define([
233
233
  }
234
234
  // When coming here we have synchronously either found a node with a truthy result or have processed the whole tree without finding any truthy result
235
235
  mAlreadyAnalyzed[sId] = 2;
236
- return vResult || null;
236
+ return vResult || null;
237
237
  }
238
238
 
239
239
  /**
240
240
  * Returns the selection plugin for the given UI table
241
- * @param {sap.ui.table.Table} oUiTable
241
+ * @param {sap.ui.table.Table} oUiTable
242
242
  * @returns {sap.ui.table.plugins.MultiSelectionPlugin|undefined}
243
243
  */
244
244
  function fnGetSelectionPluginForUITable (oUiTable) {
@@ -274,6 +274,7 @@ sap.ui.define([
274
274
  isObjectPageSubSection: isControlOfType.bind(null, "sap/uxap/ObjectPageSubSection"),
275
275
  isObjectObjectPageLayout: isControlOfType.bind(null, "sap/uxap/ObjectPageLayout"),
276
276
  isMenuButton: isControlOfType.bind(null, "sap/m/MenuButton"),
277
+ isMenuItem: isControlOfType.bind(null, "sap/m/MenuItem"),
277
278
  isMenu: isControlOfType.bind(null, "sap/m/Menu"),
278
279
  getUI5ControlForDomElement: getUI5ControlForDomElement,
279
280
  focusControl: focusControl,
@@ -286,10 +287,10 @@ sap.ui.define([
286
287
  searchInTree: fnSearchInTree.bind(null, null),
287
288
  getSelectionPluginForUITable: fnGetSelectionPluginForUITable
288
289
  };
289
-
290
+
290
291
  oControlHelper.isTable = function(oControl){
291
292
  return oControlHelper.isSmartTable(oControl) || oControlHelper.isUiTable(oControl) || oControlHelper.isMTable(oControl);
292
293
  };
293
-
294
+
294
295
  return oControlHelper;
295
296
  });
@@ -26,6 +26,7 @@ sap.ui.define([
26
26
  var bIsApplying = false;
27
27
  var aBasicFilters = [];
28
28
  var oSmartFilterBar = oControl;
29
+ var oEasyFilterCallbacks = null;
29
30
 
30
31
  var oVariantManagementInitializedPromise;
31
32
 
@@ -56,6 +57,11 @@ sap.ui.define([
56
57
  var oCustomData = Object.create(null);
57
58
  oCustomData[dataPropertyNameGeneric] = oSVMWrapperCallbacks.getManagedControlStates();
58
59
  oCustomData[dataPropertyNameGeneric].customFilters = mParams.oCustomFiltersWrapper.getState();
60
+ if (oEasyFilterCallbacks) {
61
+ var oEFState = oEasyFilterCallbacks.getState();
62
+ oCustomData[dataPropertyNameGeneric].filterMode = oEFState.filterMode;
63
+ oCustomData[dataPropertyNameGeneric].easyFilter = oEFState.easyFilter;
64
+ }
59
65
  oSmartFilterBar.setCustomFilterData(oCustomData);
60
66
  });
61
67
 
@@ -75,6 +81,12 @@ sap.ui.define([
75
81
  aBasicFilters = oSmartFilterBar.getAllFilterItems(true);
76
82
  mParams.oCustomFiltersWrapper.setState(oCustomFiltersState);
77
83
  oSVMWrapperCallbacks.setManagedControlStates(oCustomData[dataPropertyNameGeneric]);
84
+ if (oEasyFilterCallbacks) {
85
+ oEasyFilterCallbacks.setState({
86
+ filterMode: oCustomData[dataPropertyNameGeneric].filterMode,
87
+ easyFilter: oCustomData[dataPropertyNameGeneric].easyFilter
88
+ });
89
+ }
78
90
  });
79
91
 
80
92
  }
@@ -236,6 +248,9 @@ sap.ui.define([
236
248
  attachStateChanged: fnAttachStateChanged,
237
249
  // specific properties (needed to workaround direct connection between SFB and SVM)
238
250
  setSVMWrapperCallbacks: setSVMWrapperCallbacks,
251
+ setEasyFilterCallbacks: function(oCallbacks) {
252
+ oEasyFilterCallbacks = oCallbacks;
253
+ },
239
254
  bVMConnection: oSmartFilterBar.getSmartVariant(),
240
255
  suppressSelection: oSmartFilterBar.setSuppressSelection.bind(oSmartFilterBar), // if multiple reasons for suppressing overlap, a counter (to avoid to early resume) could be implemented here
241
256
  oVariantManagementInitializedPromise: oVariantManagementInitializedPromise
@@ -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.147.1
962
+ * @version 1.148.0
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", {
@@ -333,67 +333,105 @@ sap.ui.define(["sap/ui/model/Context", "sap/suite/ui/generic/template/lib/Messag
333
333
  }
334
334
 
335
335
  /*
336
- Allows direct edit on the entires on the list, unlike the method 'edit'above, this method first edit the entry with preserveChanges as true
337
- If the response indicates an unsaved change or locked record, a corresponding dialog is shown to proceed or cancel with the edit.
338
- */
339
- function directEdit(oTransactionController, sEntitySet, sBindingPath, oModel, oApplication, oCommonUtils, oViewDependencyHelper, oViewProxy, bOpenInEditMode){
336
+ * Initiates editing of a list entry directly (without navigating to the object page first).
337
+ * Unlike the 'edit' method above, the first editEntity call uses preserveChanges=true.
338
+ * If the backend responds with a 409 (conflict) the DraftAdministrativeData is read to
339
+ * distinguish between a locked record and a record with unsaved changes by another user.
340
+ * A corresponding dialog is shown to let the user decide how to proceed.
341
+ *
342
+ * @param {object} oTransactionController - transaction controller providing editEntity
343
+ * @param {string} sEntitySet - name of the entity set
344
+ * @param {object} oBindingContext - UI5 Context of the row being edited;
345
+ * the OData model and binding path are derived
346
+ * from it via .getModel() / .getPath()
347
+ * @param {object} oApplication - application proxy (busy helper, component utils, …)
348
+ * @param {string} sAppId - ID of the AppComponent; used as the localStorage cache
349
+ * key for the content-id batch optimisation
350
+ * @param {object} oCommonUtils - common utilities (getText, …)
351
+ * @param {object} oViewDependencyHelper - used to mark the root page as dirty
352
+ * @param {object} oViewProxy - used for navigateUp on cancellation
353
+ * @param {boolean} bOpenInEditMode - whether the page was opened directly in edit mode
354
+ */
355
+ function directEdit(oTransactionController, sEntitySet, oBindingContext, oApplication, sAppId, oCommonUtils, oViewDependencyHelper, oViewProxy, bOpenInEditMode){
340
356
  var oDraftContext = oTransactionController.getDraftController().getDraftContext();
341
- var oPromise = new Promise(function(resolve,reject) {
342
- oModel.createBindingContext(sBindingPath, null, null, function(oBindingContext){
343
- if (oDraftContext.isDraftEnabled(sEntitySet)) {
344
- oTransactionController.editEntity(oBindingContext, true).then(function(oResponse) {
345
- oBindingContext.getModel().invalidateEntry(oBindingContext);
346
- oViewDependencyHelper.setRootPageToDirty();
347
- resolve({
348
- context: oResponse.context
349
- });
350
- }, function(oResponse) {
351
- if (oResponse && oResponse.response && oResponse.response.statusCode === "409") {
352
- //remove transient message associated with rc 409 in order to prevent message pop-up
353
- oApplication.removeTransientMessages();
354
- fnReadDraftAdministrativeData(oModel, sBindingPath, oApplication.getBusyHelper()).then(
355
- function(oResponse) {
356
- if (oResponse.DraftAdministrativeData.InProcessByUser) {
357
- reject({
358
- lockedByUser: oResponse.DraftAdministrativeData.InProcessByUserDescription || oResponse.DraftAdministrativeData.InProcessByUser
359
- });
360
- } else { //unsaved changes
361
- var editConfirmation = function(){
362
- var oUnsavedChangesEditPromise = oTransactionController.editEntity(oBindingContext, false).then(function(oResponse){
363
- oBindingContext.getModel().invalidateEntry(oBindingContext);
364
- oViewDependencyHelper.setRootPageToDirty();
365
- resolve({
366
- context: oResponse.context
367
- });
368
- });
369
- oApplication.getBusyHelper().setBusy(oUnsavedChangesEditPromise, true);
370
- };
371
- var editRejection = reject({
372
- cancelled: true
373
- });
374
- var unSavedChangesDialogPromise = fnUnsavedChangesDialog(undefined, oResponse.DraftAdministrativeData,oCommonUtils, oViewProxy, bOpenInEditMode);
375
- unSavedChangesDialogPromise.then(editConfirmation,editRejection);
376
- }
377
- },
378
- function(oResponse) {
379
- // DraftAdminData read failed
357
+
358
+ if (!oDraftContext.isDraftEnabled(sEntitySet)) {
359
+ return Promise.resolve({ context: oBindingContext });
360
+ }
361
+
362
+ var oModel = oBindingContext.getModel();
363
+ // Fetch sRootExpand for the content-id batch optimisation.
364
+ // getRootExpand is intentionally not provided: directEdit is always invoked from
365
+ // the List Report before the Object Page is active, so getRootExpand is not yet
366
+ // available. CacheHelper falls back to the localStorage cache, which is still
367
+ // much faster than fetching expands in a separate backend request.
368
+ var oInfoForContentIdPromise = CacheHelper.getInfoForContentIdPromise(sEntitySet, oModel, sAppId);
369
+
370
+ var oRet = oInfoForContentIdPromise.then(function(oInfoObject) {
371
+ var sRootExpand = oInfoObject.contentIdRequestPossible ? oInfoObject.parametersForContentIdRequest.sRootExpand : null;
372
+
373
+ return new Promise(function(resolve, reject) {
374
+ var oFirstEditPromise = oTransactionController.editEntity(oBindingContext, true, sRootExpand);
375
+ // Track the busy state against the individual network request so the busy
376
+ // indicator remains active for exactly as long as the request is in flight.
377
+ oApplication.getBusyHelper().setBusy(oFirstEditPromise, true);
378
+ oFirstEditPromise.then(function(oResponse) {
379
+ oModel.invalidateEntry(oBindingContext);
380
+ oViewDependencyHelper.setRootPageToDirty();
381
+ resolve({ context: oResponse.context });
382
+ }, function(oResponse) {
383
+ if (oResponse && oResponse.response && oResponse.response.statusCode === "409") {
384
+ //remove transient message associated with rc 409 in order to prevent message pop-up
385
+ oApplication.removeTransientMessages();
386
+ fnReadDraftAdministrativeData(oModel, oBindingContext.getPath(), oApplication.getBusyHelper()).then(
387
+ function(oResponse) {
388
+ if (oResponse.DraftAdministrativeData.InProcessByUser) {
380
389
  reject({
381
- draftAdminReadResponse: oResponse
390
+ lockedByUser: oResponse.DraftAdministrativeData.InProcessByUserDescription || oResponse.DraftAdministrativeData.InProcessByUser
382
391
  });
383
- });
384
- oApplication.getBusyHelper().setBusy(oPromise, true);
385
- } else {
386
- reject(oResponse);
387
- }
388
- });
389
- } else {
390
- return resolve({
391
- context: oBindingContext
392
+ } else { //unsaved changes
393
+ var editConfirmation = function() {
394
+ // Re-run editEntity without preserveChanges so the
395
+ // unsaved changes of another user are overwritten.
396
+ var oUnsavedChangesEditPromise = oTransactionController.editEntity(oBindingContext, false, sRootExpand).then(function(oResponse) {
397
+ oModel.invalidateEntry(oBindingContext);
398
+ oViewDependencyHelper.setRootPageToDirty();
399
+ resolve({ context: oResponse.context });
400
+ });
401
+ oApplication.getBusyHelper().setBusy(oUnsavedChangesEditPromise, true);
402
+ };
403
+ // editRejection is passed as the rejection handler of Promise.then(),
404
+ // so it must be a function reference; calling reject() inline here
405
+ // would execute it immediately instead of on dialog cancellation.
406
+ var editRejection = function() { reject({ cancelled: true }); };
407
+ var unSavedChangesDialogPromise = fnUnsavedChangesDialog(undefined, oResponse.DraftAdministrativeData, oCommonUtils, oViewProxy, bOpenInEditMode);
408
+ unSavedChangesDialogPromise.then(editConfirmation, editRejection);
409
+ }
410
+ },
411
+ function(oResponse) {
412
+ // DraftAdminData read failed
413
+ reject({ draftAdminReadResponse: oResponse });
414
+ }
415
+ );
416
+ } else {
417
+ reject(oResponse);
418
+ }
392
419
  });
393
- }
394
420
  });
395
421
  });
396
- return oPromise;
422
+
423
+ // Ensure the active context is registered in ContextBookkeeping before the edit
424
+ // resolves. This caches the draft sibling path so subsequent navigation can use
425
+ // the cached value without an additional /SiblingEntity request.
426
+ // editingStarted() notifies all listeners (e.g. the message button helper) that
427
+ // the editing phase has begun for this context.
428
+ var bContextRegistered = oApplication.checkContextData(oBindingContext);
429
+ if (!bContextRegistered) {
430
+ oApplication.registerContext(oBindingContext, 1, sEntitySet);
431
+ }
432
+ oApplication.editingStarted(oBindingContext, oRet);
433
+
434
+ return oRet;
397
435
  }
398
436
 
399
437
  function deleteEntity(oDraftController, fnExecuteDelete, oApplicationProxy, oContext, bIsActiveEntity, sActionType){
@@ -589,6 +589,13 @@ 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
+ }
592
599
  reject();
593
600
  });
594
601
  oBusyHelper.setBusy(oSubmitChange);