@sapui5/sap.fe.core 1.97.0 → 1.99.1

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 (249) hide show
  1. package/package.json +5 -4
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +377 -405
  4. package/src/sap/fe/core/AnnotationHelper.ts +385 -0
  5. package/src/sap/fe/core/AppComponent.js +6 -3
  6. package/src/sap/fe/core/AppStateHandler.js +229 -181
  7. package/src/sap/fe/core/AppStateHandler.ts +171 -0
  8. package/src/sap/fe/core/BaseController.js +3 -2
  9. package/src/sap/fe/core/BusyLocker.js +105 -121
  10. package/src/sap/fe/core/BusyLocker.ts +98 -0
  11. package/src/sap/fe/core/CommonUtils.js +2073 -2379
  12. package/src/sap/fe/core/CommonUtils.ts +2078 -0
  13. package/src/sap/fe/core/ExtensionAPI.js +16 -7
  14. package/src/sap/fe/core/PageController.js +84 -119
  15. package/src/sap/fe/core/PageController.ts +101 -0
  16. package/src/sap/fe/core/RouterProxy.js +986 -807
  17. package/src/sap/fe/core/RouterProxy.ts +838 -0
  18. package/src/sap/fe/core/Synchronization.js +51 -35
  19. package/src/sap/fe/core/Synchronization.ts +29 -0
  20. package/src/sap/fe/core/TemplateComponent.js +173 -155
  21. package/src/sap/fe/core/TemplateComponent.ts +166 -0
  22. package/src/sap/fe/core/TemplateModel.js +97 -54
  23. package/src/sap/fe/core/TemplateModel.ts +64 -0
  24. package/src/sap/fe/core/TransactionHelper.js +1576 -1579
  25. package/src/sap/fe/core/TransactionHelper.ts +1706 -0
  26. package/src/sap/fe/core/actions/draft.js +560 -581
  27. package/src/sap/fe/core/actions/draft.ts +594 -0
  28. package/src/sap/fe/core/actions/messageHandling.js +545 -511
  29. package/src/sap/fe/core/actions/messageHandling.ts +532 -0
  30. package/src/sap/fe/core/actions/nonDraft.js +17 -19
  31. package/src/sap/fe/core/actions/nonDraft.ts +12 -0
  32. package/src/sap/fe/core/actions/operations.js +1074 -1211
  33. package/src/sap/fe/core/actions/operations.ts +1162 -0
  34. package/src/sap/fe/core/actions/sticky.js +102 -105
  35. package/src/sap/fe/core/actions/sticky.ts +102 -0
  36. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +3 -2
  37. package/src/sap/fe/core/controllerextensions/EditFlow.js +229 -260
  38. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +3 -2
  39. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +288 -13
  40. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +27 -23
  41. package/src/sap/fe/core/controllerextensions/InternalRouting.js +82 -46
  42. package/src/sap/fe/core/controllerextensions/KPIManagement.js +113 -25
  43. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +135 -44
  44. package/src/sap/fe/core/controllerextensions/MassEdit.js +172 -0
  45. package/src/sap/fe/core/controllerextensions/MessageHandler.js +22 -9
  46. package/src/sap/fe/core/controllerextensions/PageReady.js +3 -3
  47. package/src/sap/fe/core/controllerextensions/PageReady.ts +12 -8
  48. package/src/sap/fe/core/controllerextensions/Paginator.js +37 -9
  49. package/src/sap/fe/core/controllerextensions/Placeholder.js +8 -4
  50. package/src/sap/fe/core/controllerextensions/Routing.js +25 -5
  51. package/src/sap/fe/core/controllerextensions/RoutingListener.js +3 -2
  52. package/src/sap/fe/core/controllerextensions/Share.js +22 -8
  53. package/src/sap/fe/core/controllerextensions/SideEffects.js +9 -9
  54. package/src/sap/fe/core/controllerextensions/SideEffects.ts +22 -21
  55. package/src/sap/fe/core/controllerextensions/ViewState.js +3 -2
  56. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +2 -1
  57. package/src/sap/fe/core/controls/CommandExecution.js +3 -2
  58. package/src/sap/fe/core/controls/ConditionalWrapper.js +3 -2
  59. package/src/sap/fe/core/controls/CustomQuickViewPage.js +3 -2
  60. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +9 -5
  61. package/src/sap/fe/core/controls/FieldWrapper.js +18 -23
  62. package/src/sap/fe/core/controls/FilterBar.js +3 -2
  63. package/src/sap/fe/core/controls/FormElementWrapper.js +3 -7
  64. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +3 -2
  65. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +2 -1
  66. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +3 -2
  67. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +5 -4
  68. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +3 -2
  69. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +3 -2
  70. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  71. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +79 -0
  72. package/src/sap/fe/core/converters/ConverterContext.js +14 -2
  73. package/src/sap/fe/core/converters/ConverterContext.ts +14 -3
  74. package/src/sap/fe/core/converters/ManifestSettings.js +1 -1
  75. package/src/sap/fe/core/converters/ManifestSettings.ts +4 -0
  76. package/src/sap/fe/core/converters/ManifestWrapper.js +56 -32
  77. package/src/sap/fe/core/converters/ManifestWrapper.ts +24 -6
  78. package/src/sap/fe/core/converters/MetaModelConverter.js +67 -6
  79. package/src/sap/fe/core/converters/MetaModelConverter.ts +70 -14
  80. package/src/sap/fe/core/converters/TemplateConverter.js +1 -1
  81. package/src/sap/fe/core/converters/TemplateConverter.ts +2 -2
  82. package/src/sap/fe/core/converters/annotations/DataField.js +3 -3
  83. package/src/sap/fe/core/converters/annotations/DataField.ts +1 -1
  84. package/src/sap/fe/core/converters/common/AnnotationConverter.js +33 -21
  85. package/src/sap/fe/core/converters/controls/Common/Action.js +11 -2
  86. package/src/sap/fe/core/converters/controls/Common/Action.ts +8 -2
  87. package/src/sap/fe/core/converters/controls/Common/Chart.js +5 -3
  88. package/src/sap/fe/core/converters/controls/Common/Chart.ts +11 -3
  89. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +3 -3
  90. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +2 -2
  91. package/src/sap/fe/core/converters/controls/Common/Form.js +20 -10
  92. package/src/sap/fe/core/converters/controls/Common/Form.ts +24 -4
  93. package/src/sap/fe/core/converters/controls/Common/KPI.js +69 -4
  94. package/src/sap/fe/core/converters/controls/Common/KPI.ts +72 -0
  95. package/src/sap/fe/core/converters/controls/Common/Table.js +390 -398
  96. package/src/sap/fe/core/converters/controls/Common/Table.ts +497 -484
  97. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +527 -0
  98. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +655 -0
  99. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +489 -37
  100. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +506 -58
  101. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  102. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  103. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +17 -9
  104. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +24 -9
  105. package/src/sap/fe/core/converters/helpers/Aggregation.js +18 -3
  106. package/src/sap/fe/core/converters/helpers/Aggregation.ts +28 -5
  107. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -1
  108. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -0
  109. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +4 -4
  110. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +3 -3
  111. package/src/sap/fe/core/converters/templates/ListReportConverter.js +13 -6
  112. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +26 -15
  113. package/src/sap/fe/core/designtime/AppComponent.designtime.js +11 -2
  114. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  115. package/src/sap/fe/core/formatters/CriticalityFormatter.ts +1 -1
  116. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  117. package/src/sap/fe/core/formatters/FPMFormatter.ts +4 -10
  118. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  119. package/src/sap/fe/core/formatters/KPIFormatter.ts +3 -1
  120. package/src/sap/fe/core/formatters/TableFormatter.js +39 -28
  121. package/src/sap/fe/core/formatters/TableFormatter.ts +43 -28
  122. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  123. package/src/sap/fe/core/formatters/ValueFormatter.ts +30 -7
  124. package/src/sap/fe/core/fpm/Component.js +3 -2
  125. package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
  126. package/src/sap/fe/core/helpers/AppStartupHelper.ts +391 -0
  127. package/src/sap/fe/core/helpers/BindingExpression.js +484 -437
  128. package/src/sap/fe/core/helpers/BindingExpression.ts +480 -463
  129. package/src/sap/fe/core/helpers/ClassSupport.js +27 -15
  130. package/src/sap/fe/core/helpers/ClassSupport.ts +31 -20
  131. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +63 -59
  132. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.ts +56 -0
  133. package/src/sap/fe/core/helpers/EditState.js +81 -84
  134. package/src/sap/fe/core/helpers/EditState.ts +81 -0
  135. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +62 -48
  136. package/src/sap/fe/core/helpers/ExcelFormatHelper.ts +49 -0
  137. package/src/sap/fe/core/helpers/FPMHelper.js +52 -56
  138. package/src/sap/fe/core/helpers/FPMHelper.ts +62 -0
  139. package/src/sap/fe/core/helpers/KeepAliveHelper.js +4 -5
  140. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +10 -10
  141. package/src/sap/fe/core/helpers/MassEditHelper.js +687 -0
  142. package/src/sap/fe/core/helpers/ModelHelper.js +229 -225
  143. package/src/sap/fe/core/helpers/ModelHelper.ts +227 -0
  144. package/src/sap/fe/core/helpers/PasteHelper.js +210 -132
  145. package/src/sap/fe/core/helpers/PasteHelper.ts +196 -0
  146. package/src/sap/fe/core/helpers/SemanticDateOperators.js +332 -313
  147. package/src/sap/fe/core/helpers/SemanticDateOperators.ts +330 -0
  148. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +66 -67
  149. package/src/sap/fe/core/helpers/SemanticKeyHelper.ts +73 -0
  150. package/src/sap/fe/core/helpers/StableIdHelper.js +4 -7
  151. package/src/sap/fe/core/helpers/StableIdHelper.ts +2 -6
  152. package/src/sap/fe/core/jsx-runtime/jsx.js +1 -1
  153. package/src/sap/fe/core/jsx-runtime/jsx.ts +1 -1
  154. package/src/sap/fe/core/library.js +30 -3
  155. package/src/sap/fe/core/library.support.js +12 -5
  156. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
  157. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
  158. package/src/sap/fe/core/messagebundle.properties +61 -13
  159. package/src/sap/fe/core/messagebundle_ar.properties +33 -2
  160. package/src/sap/fe/core/messagebundle_bg.properties +33 -2
  161. package/src/sap/fe/core/messagebundle_ca.properties +33 -2
  162. package/src/sap/fe/core/messagebundle_cs.properties +34 -3
  163. package/src/sap/fe/core/messagebundle_cy.properties +33 -2
  164. package/src/sap/fe/core/messagebundle_da.properties +33 -2
  165. package/src/sap/fe/core/messagebundle_de.properties +33 -2
  166. package/src/sap/fe/core/messagebundle_el.properties +33 -2
  167. package/src/sap/fe/core/messagebundle_en.properties +32 -1
  168. package/src/sap/fe/core/messagebundle_en_GB.properties +32 -1
  169. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +36 -1
  170. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +33 -2
  171. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +33 -2
  172. package/src/sap/fe/core/messagebundle_es.properties +33 -2
  173. package/src/sap/fe/core/messagebundle_es_MX.properties +33 -2
  174. package/src/sap/fe/core/messagebundle_et.properties +33 -2
  175. package/src/sap/fe/core/messagebundle_fi.properties +34 -3
  176. package/src/sap/fe/core/messagebundle_fr.properties +38 -7
  177. package/src/sap/fe/core/messagebundle_fr_CA.properties +33 -2
  178. package/src/sap/fe/core/messagebundle_hi.properties +33 -2
  179. package/src/sap/fe/core/messagebundle_hr.properties +33 -2
  180. package/src/sap/fe/core/messagebundle_hu.properties +34 -3
  181. package/src/sap/fe/core/messagebundle_id.properties +36 -5
  182. package/src/sap/fe/core/messagebundle_it.properties +33 -2
  183. package/src/sap/fe/core/messagebundle_iw.properties +33 -2
  184. package/src/sap/fe/core/messagebundle_ja.properties +33 -2
  185. package/src/sap/fe/core/messagebundle_kk.properties +33 -2
  186. package/src/sap/fe/core/messagebundle_ko.properties +33 -2
  187. package/src/sap/fe/core/messagebundle_lt.properties +33 -2
  188. package/src/sap/fe/core/messagebundle_lv.properties +33 -2
  189. package/src/sap/fe/core/messagebundle_ms.properties +33 -2
  190. package/src/sap/fe/core/messagebundle_nl.properties +33 -2
  191. package/src/sap/fe/core/messagebundle_no.properties +33 -2
  192. package/src/sap/fe/core/messagebundle_pl.properties +33 -2
  193. package/src/sap/fe/core/messagebundle_pt.properties +34 -3
  194. package/src/sap/fe/core/messagebundle_pt_PT.properties +33 -2
  195. package/src/sap/fe/core/messagebundle_ro.properties +33 -2
  196. package/src/sap/fe/core/messagebundle_ru.properties +33 -2
  197. package/src/sap/fe/core/messagebundle_sh.properties +33 -2
  198. package/src/sap/fe/core/messagebundle_sk.properties +33 -2
  199. package/src/sap/fe/core/messagebundle_sl.properties +33 -2
  200. package/src/sap/fe/core/messagebundle_sv.properties +34 -3
  201. package/src/sap/fe/core/messagebundle_th.properties +33 -2
  202. package/src/sap/fe/core/messagebundle_tr.properties +33 -2
  203. package/src/sap/fe/core/messagebundle_uk.properties +33 -2
  204. package/src/sap/fe/core/messagebundle_vi.properties +33 -2
  205. package/src/sap/fe/core/messagebundle_zh_CN.properties +33 -2
  206. package/src/sap/fe/core/messagebundle_zh_TW.properties +33 -2
  207. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +2 -2
  208. package/src/sap/fe/core/services/AsyncComponentServiceFactory.ts +3 -1
  209. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +269 -202
  210. package/src/sap/fe/core/services/CacheHandlerServiceFactory.ts +212 -0
  211. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
  212. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +9 -5
  213. package/src/sap/fe/core/services/NavigationServiceFactory.js +406 -300
  214. package/src/sap/fe/core/services/NavigationServiceFactory.ts +316 -0
  215. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +149 -81
  216. package/src/sap/fe/core/services/ResourceModelServiceFactory.ts +80 -0
  217. package/src/sap/fe/core/services/RoutingServiceFactory.js +987 -1152
  218. package/src/sap/fe/core/services/RoutingServiceFactory.ts +898 -0
  219. package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
  220. package/src/sap/fe/core/services/ShellServicesFactory.ts +45 -11
  221. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +42 -85
  222. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +57 -100
  223. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +461 -478
  224. package/src/sap/fe/core/services/TemplatedViewServiceFactory.ts +453 -0
  225. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +10 -8
  226. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.ts +8 -0
  227. package/src/sap/fe/core/support/AnnotationIssue.support.js +15 -3
  228. package/src/sap/fe/core/support/AnnotationIssue.support.ts +16 -2
  229. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -2
  230. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.ts +1 -1
  231. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  232. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  233. package/src/sap/fe/core/templating/DataModelPathHelper.js +10 -48
  234. package/src/sap/fe/core/templating/DataModelPathHelper.ts +14 -46
  235. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  236. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  237. package/src/sap/fe/core/templating/FieldControlHelper.js +8 -8
  238. package/src/sap/fe/core/templating/FieldControlHelper.ts +25 -7
  239. package/src/sap/fe/core/templating/FilterHelper.js +139 -70
  240. package/src/sap/fe/core/templating/FilterHelper.ts +140 -70
  241. package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
  242. package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
  243. package/src/sap/fe/core/templating/UIFormatters.js +45 -110
  244. package/src/sap/fe/core/templating/UIFormatters.ts +39 -75
  245. package/src/sap/fe/core/type/Email.js +1 -1
  246. package/src/sap/fe/core/type/Email.ts +4 -6
  247. package/ui5.yaml +0 -3
  248. package/src/sap/fe/core/controls/filterbar.d.js +0 -8
  249. package/src/sap/fe/core/controls/filterbar.d.ts +0 -0
@@ -12,7 +12,6 @@ import {
12
12
  LineItem,
13
13
  PathAnnotationExpression,
14
14
  PresentationVariantTypeTypes,
15
- PropertyAnnotationValue,
16
15
  PropertyPath,
17
16
  SelectionVariantType,
18
17
  SelectOptionType,
@@ -30,12 +29,13 @@ import {
30
29
  SelectionMode,
31
30
  TableColumnSettings,
32
31
  TableManifestConfiguration,
32
+ TableManifestSettingsConfiguration,
33
33
  TemplateType,
34
34
  VariantManagementType,
35
35
  ViewPathConfiguration,
36
36
  VisualizationType
37
37
  } from "../../ManifestSettings";
38
- import { EntityType, Property } from "@sap-ux/annotation-converter";
38
+ import { EntityType, Property, TypeDefinition } from "@sap-ux/annotation-converter";
39
39
  import { TableID } from "../../helpers/ID";
40
40
  import {
41
41
  AnnotationAction,
@@ -69,13 +69,12 @@ import {
69
69
  ExpressionOrPrimitive,
70
70
  formatResult,
71
71
  ifElse,
72
- isBinding,
73
72
  isConstant,
74
73
  not,
75
74
  or,
76
75
  resolveBindingString
77
76
  } from "sap/fe/core/helpers/BindingExpression";
78
- import { Draft, bindingContextPathVisitor, singletonPathVisitor, UI } from "sap/fe/core/converters/helpers/BindingHelper";
77
+ import { Entity, bindingContextPathVisitor, UI } from "sap/fe/core/converters/helpers/BindingHelper";
79
78
  import { KeyHelper } from "sap/fe/core/converters/helpers/Key";
80
79
  import tableFormatters from "sap/fe/core/formatters/TableFormatter";
81
80
  import { MessageType } from "sap/fe/core/formatters/TableFormatterTypes";
@@ -84,11 +83,10 @@ import {
84
83
  getTargetObjectPath,
85
84
  isPathDeletable,
86
85
  isPathSearchable,
87
- isPathInsertable,
88
86
  isPathUpdatable
89
87
  } from "sap/fe/core/templating/DataModelPathHelper";
90
88
  import { replaceSpecialChars } from "sap/fe/core/helpers/StableIdHelper";
91
- import { IssueCategory, IssueSeverity, IssueType } from "sap/fe/core/converters/helpers/IssueManager";
89
+ import { IssueCategory, IssueSeverity, IssueType, IssueCategoryType } from "sap/fe/core/converters/helpers/IssueManager";
92
90
 
93
91
  import ManifestWrapper from "../../ManifestWrapper";
94
92
  import ConverterContext from "../../ConverterContext";
@@ -100,10 +98,26 @@ import {
100
98
  getTargetValueOnDataPoint
101
99
  } from "sap/fe/core/templating/PropertyHelper";
102
100
  import { AggregationHelper } from "../../helpers/Aggregation";
103
- import { DisplayMode, getDisplayMode, getTypeConfig } from "sap/fe/core/templating/UIFormatters";
101
+ import { DisplayMode, EDM_TYPE_MAPPING, getDisplayMode } from "sap/fe/core/templating/DisplayModeFormatter";
104
102
  import { getMessageTypeFromCriticalityType } from "./Criticality";
105
103
  import { FilterFunctions } from "@sap-ux/vocabularies-types/dist/generated/Capabilities";
106
104
  import { getNonSortablePropertiesRestrictions } from "sap/fe/core/templating/EntitySetHelper";
105
+ import {
106
+ generateStandardActionsContext,
107
+ isExternalCreateConfigured,
108
+ StandardActionConfigType,
109
+ getDeleteVisibility,
110
+ getStandardActionCreate,
111
+ getStandardActionDelete,
112
+ getStandardActionPaste,
113
+ getStandardActionMassEdit,
114
+ isDraftOrStickySupported,
115
+ getInsertUpdateActionsTemplating,
116
+ getCreateVisibility,
117
+ isInDisplayMode,
118
+ getMassEditVisibility,
119
+ getRestrictions
120
+ } from "./table/StandardActions";
107
121
 
108
122
  export type TableAnnotationConfiguration = {
109
123
  autoBindOnInit: boolean;
@@ -120,11 +134,10 @@ export type TableAnnotationConfiguration = {
120
134
  rowNavigated: BindingExpression<boolean>;
121
135
  };
122
136
  selectionMode: string | undefined;
123
- show?: {
124
- create?: string | boolean;
125
- delete?: string | boolean;
126
- paste?: BindingExpression<boolean>;
127
- massEdit?: { visible: boolean | string; enabled: boolean | string };
137
+ standardActions: {
138
+ actions: Record<string, StandardActionConfigType>;
139
+ isInsertUpdateTemplated: boolean;
140
+ updatablePropertyPath: string;
128
141
  };
129
142
  displayMode?: boolean;
130
143
  threshold: number;
@@ -135,7 +148,6 @@ export type TableAnnotationConfiguration = {
135
148
 
136
149
  /** Create new entries */
137
150
  create: CreateBehaviour | CreateBehaviourExternal;
138
- parentEntityDeleteEnabled?: BindingExpression<boolean>;
139
151
  title: string;
140
152
  searchable: boolean;
141
153
  };
@@ -198,6 +210,7 @@ export type TableControlConfiguration = {
198
210
  showRowCount: boolean;
199
211
  enableMassEdit: boolean | undefined;
200
212
  enableAutoColumnWidth: boolean;
213
+ dataStateIndicatorFilter: string | undefined;
201
214
  };
202
215
 
203
216
  export type TableType = "GridTable" | "ResponsiveTable" | "AnalyticalTable";
@@ -233,6 +246,7 @@ export type AnnotationTableColumn = BaseTableColumn & {
233
246
  annotationPath: string;
234
247
  relativePath: string;
235
248
  label?: string;
249
+ tooltip?: string;
236
250
  groupLabel?: string;
237
251
  group?: string;
238
252
  isGroupable?: boolean;
@@ -240,6 +254,7 @@ export type AnnotationTableColumn = BaseTableColumn & {
240
254
  showDataFieldsLabel?: boolean;
241
255
  isKey?: boolean;
242
256
  unit?: string;
257
+ unitText?: string;
243
258
  exportSettings?: {
244
259
  template?: string;
245
260
  label?: string;
@@ -298,7 +313,7 @@ export type TableVisualization = {
298
313
  actions: BaseAction[];
299
314
  aggregates?: Record<string, AggregateData>;
300
315
  enableAnalytics?: boolean;
301
- enableDataStateFilter: boolean;
316
+ enableAnalyticsSearch?: boolean;
302
317
  operationAvailableMap: string;
303
318
  operationAvailableProperties: string;
304
319
  };
@@ -490,6 +505,10 @@ function updateTableVisualizationForAnalytics(
490
505
  tableVisualization.enableAnalytics = true;
491
506
  tableVisualization.aggregates = aggregatesDefinitions;
492
507
 
508
+ const aggregationHelper = new AggregationHelper(entityType, converterContext);
509
+ const allowedTransformations = aggregationHelper.getAllowedTransformations();
510
+ tableVisualization.enableAnalyticsSearch = allowedTransformations ? allowedTransformations.indexOf("search") >= 0 : true;
511
+
493
512
  // Add group and sort conditions from the presentation variant
494
513
  tableVisualization.annotation.groupConditions = getGroupConditions(presentationVariantAnnotation, tableVisualization.columns);
495
514
  tableVisualization.annotation.aggregateConditions = getAggregateConditions(
@@ -545,13 +564,17 @@ export function updateLinkedProperties(entityType: EntityType, tableColumns: Tab
545
564
  tableColumns.forEach(oColumn => {
546
565
  const oTableColumn = oColumn as AnnotationTableColumn;
547
566
  if (oTableColumn.propertyInfos === undefined && oTableColumn.relativePath) {
548
- const oProperty = entityType.entityProperties.find(oProp => oProp.name === oTableColumn.relativePath);
567
+ const oProperty = entityType.entityProperties.find((oProp: Property) => oProp.name === oTableColumn.relativePath);
549
568
  if (oProperty) {
550
- const sUnit = getAssociatedCurrencyProperty(oProperty)?.name || getAssociatedUnitProperty(oProperty)?.name;
551
- if (sUnit) {
552
- const oUnitColumn = findColumnByPath(sUnit);
553
-
569
+ const oUnit = getAssociatedCurrencyProperty(oProperty) || getAssociatedUnitProperty(oProperty);
570
+ if (oUnit) {
571
+ const oUnitColumn = findColumnByPath(oUnit.name);
554
572
  oTableColumn.unit = oUnitColumn?.name;
573
+ } else {
574
+ const sUnit = oProperty?.annotations?.Measures?.ISOCurrency || oProperty?.annotations?.Measures?.Unit;
575
+ if (sUnit) {
576
+ oTableColumn.unitText = `${sUnit}`;
577
+ }
555
578
  }
556
579
 
557
580
  const displayMode = getDisplayMode(oProperty),
@@ -604,7 +627,6 @@ export function createTableVisualization(
604
627
  control: tableManifestConfig,
605
628
  actions: removeDuplicateActions(getTableActions(lineItemAnnotation, visualizationPath, converterContext, navigationSettings)),
606
629
  columns: columns,
607
- enableDataStateFilter: converterContext.getTemplateType() === "ObjectPage",
608
630
  operationAvailableMap: JSON.stringify(operationAvailableMap),
609
631
  operationAvailableProperties: getOperationAvailableProperties(operationAvailableMap, converterContext)
610
632
  };
@@ -630,7 +652,6 @@ export function createDefaultTableVisualization(converterContext: ConverterConte
630
652
  control: tableManifestConfig,
631
653
  actions: [],
632
654
  columns: columns,
633
- enableDataStateFilter: converterContext.getTemplateType() === "ObjectPage",
634
655
  operationAvailableMap: JSON.stringify(operationAvailableMap),
635
656
  operationAvailableProperties: getOperationAvailableProperties(operationAvailableMap, converterContext)
636
657
  };
@@ -688,6 +709,22 @@ function getOperationAvailableMap(lineItemAnnotation: LineItem | undefined, conv
688
709
  return operationAvailableMap;
689
710
  }
690
711
 
712
+ /**
713
+ * Gets updatable propertyPath for the current entityset if valid.
714
+ *
715
+ * @param converterContext The instance of the converter context
716
+ * @returns {string} The updatable property for the rows
717
+ */
718
+ function getCurrentEntitySetUpdatablePath(converterContext: ConverterContext): string {
719
+ const restrictions = getRestrictions(converterContext);
720
+ const entitySet = converterContext.getEntitySet();
721
+ const updatable = restrictions.isUpdatable;
722
+ const isOnlyDynamicOnCurrentEntity: any = updatable.isOnlyCurrentEntityExpression && !isConstant(updatable.expression);
723
+ const updatablePropertyPath = (entitySet?.annotations.Capabilities?.UpdateRestrictions?.Updatable as any)?.path;
724
+
725
+ return isOnlyDynamicOnCurrentEntity ? (updatablePropertyPath as string) : "";
726
+ }
727
+
691
728
  /**
692
729
  * Method to retrieve all property paths assigned to the Core.OperationAvailable annotation.
693
730
  *
@@ -910,7 +947,8 @@ export function getSelectionMode(
910
947
  converterContext: ConverterContext,
911
948
  isEntitySet: boolean,
912
949
  targetCapabilities: TableCapabilityRestriction,
913
- isDeleteButtonVisible?: Expression<boolean>
950
+ deleteButtonVisibilityExpression?: Expression<boolean>,
951
+ massEditVisibilityExpression: Expression<boolean> = constant(false)
914
952
  ): string | undefined {
915
953
  if (!lineItemAnnotation) {
916
954
  return SelectionMode.None;
@@ -931,12 +969,31 @@ export function getSelectionMode(
931
969
  isParentDeletable = isPathDeletable(converterContext.getDataModelObjectPath(), undefined);
932
970
  parentEntitySetDeletable = isParentDeletable ? compileBinding(isParentDeletable, true) : isParentDeletable;
933
971
  }
934
- if (selectionMode && selectionMode === SelectionMode.None && isDeleteButtonVisible) {
935
- return compileBinding(ifElse(isDeleteButtonVisible, constant("Multi"), constant("None")));
972
+
973
+ const bMassEditEnabled: boolean = !isConstant(massEditVisibilityExpression) || massEditVisibilityExpression.value !== false;
974
+ if (selectionMode && selectionMode === SelectionMode.None && deleteButtonVisibilityExpression) {
975
+ if (converterContext.getTemplateType() === TemplateType.ObjectPage && bMassEditEnabled) {
976
+ // Mass Edit in OP is enabled only in edit mode.
977
+ return compileBinding(
978
+ ifElse(
979
+ and(equal(bindingExpression("/editMode", "ui"), "Editable"), massEditVisibilityExpression),
980
+ constant("Multi"),
981
+ ifElse(deleteButtonVisibilityExpression, constant("Multi"), constant("None"))
982
+ )
983
+ );
984
+ } else if (bMassEditEnabled) {
985
+ return SelectionMode.Multi;
986
+ }
987
+
988
+ return compileBinding(ifElse(deleteButtonVisibilityExpression, constant("Multi"), constant("None")));
936
989
  }
937
990
  if (!selectionMode || selectionMode === SelectionMode.Auto) {
938
991
  selectionMode = SelectionMode.Multi;
939
992
  }
993
+ if (bMassEditEnabled) {
994
+ // Override default selection mode when mass edit is visible
995
+ selectionMode = selectionMode === SelectionMode.Single ? SelectionMode.Single : SelectionMode.Multi;
996
+ }
940
997
 
941
998
  if (
942
999
  hasBoundActionsAlwaysVisibleInToolBar(lineItemAnnotation, converterContext.getEntityType()) ||
@@ -953,12 +1010,22 @@ export function getSelectionMode(
953
1010
  aVisibleBindingExpressions = getVisibleExpForCustomActionsRequiringContext(manifestActions);
954
1011
 
955
1012
  // No action requiring a context:
956
- if (aHiddenBindingExpressions.length === 0 && aVisibleBindingExpressions.length === 0 && isDeleteButtonVisible) {
1013
+ if (
1014
+ aHiddenBindingExpressions.length === 0 &&
1015
+ aVisibleBindingExpressions.length === 0 &&
1016
+ (deleteButtonVisibilityExpression || bMassEditEnabled)
1017
+ ) {
957
1018
  if (!isEntitySet) {
958
- if (targetCapabilities.isDeletable || parentEntitySetDeletable !== "false") {
1019
+ // Example: OP case
1020
+ if (targetCapabilities.isDeletable || parentEntitySetDeletable !== "false" || bMassEditEnabled) {
1021
+ // Building expression for delete and mass edit
1022
+ const buttonVisibilityExpression = or(
1023
+ deleteButtonVisibilityExpression || true, // default delete visibility as true
1024
+ massEditVisibilityExpression
1025
+ );
959
1026
  return compileBinding(
960
1027
  ifElse(
961
- and(equal(bindingExpression("/editMode", "ui"), "Editable"), isDeleteButtonVisible),
1028
+ and(equal(bindingExpression("/editMode", "ui"), "Editable"), buttonVisibilityExpression),
962
1029
  constant(selectionMode),
963
1030
  constant(SelectionMode.None)
964
1031
  )
@@ -967,18 +1034,28 @@ export function getSelectionMode(
967
1034
  return SelectionMode.None;
968
1035
  }
969
1036
  // EntitySet deletable:
970
- } else if (targetCapabilities.isDeletable && isDeleteButtonVisible) {
971
- return compileBinding(ifElse(isDeleteButtonVisible, constant(selectionMode), constant("None")));
1037
+ } else if (bMassEditEnabled) {
1038
+ // example: LR scenario
1039
+ return selectionMode;
1040
+ } else if (targetCapabilities.isDeletable && deleteButtonVisibilityExpression) {
1041
+ return compileBinding(ifElse(deleteButtonVisibilityExpression, constant(selectionMode), constant("None")));
972
1042
  // EntitySet not deletable:
973
1043
  } else {
974
1044
  return SelectionMode.None;
975
1045
  }
976
1046
  // There are actions requiring a context:
977
1047
  } else if (!isEntitySet) {
978
- if (targetCapabilities.isDeletable || parentEntitySetDeletable !== "false") {
1048
+ // Example: OP case
1049
+ if (targetCapabilities.isDeletable || parentEntitySetDeletable !== "false" || bMassEditEnabled) {
1050
+ // Use selectionMode in edit mode if delete is enabled or mass edit is visible
1051
+ const editModebuttonVisibilityExpression = ifElse(
1052
+ bMassEditEnabled && !targetCapabilities.isDeletable,
1053
+ massEditVisibilityExpression,
1054
+ constant(true)
1055
+ );
979
1056
  return compileBinding(
980
1057
  ifElse(
981
- equal(bindingExpression("/editMode", "ui"), "Editable"),
1058
+ and(equal(bindingExpression("/editMode", "ui"), "Editable"), editModebuttonVisibilityExpression),
982
1059
  constant(selectionMode),
983
1060
  ifElse(
984
1061
  or(...aHiddenBindingExpressions.concat(aVisibleBindingExpressions)),
@@ -997,13 +1074,14 @@ export function getSelectionMode(
997
1074
  );
998
1075
  }
999
1076
  //EntitySet deletable:
1000
- } else if (targetCapabilities.isDeletable) {
1001
- return SelectionMode.Multi;
1077
+ } else if (targetCapabilities.isDeletable || bMassEditEnabled) {
1078
+ // Example: LR scenario
1079
+ return selectionMode;
1002
1080
  //EntitySet not deletable:
1003
1081
  } else {
1004
1082
  return compileBinding(
1005
1083
  ifElse(
1006
- or(...aHiddenBindingExpressions.concat(aVisibleBindingExpressions)),
1084
+ or(...aHiddenBindingExpressions.concat(aVisibleBindingExpressions), massEditVisibilityExpression),
1007
1085
  constant(selectionMode),
1008
1086
  constant(SelectionMode.None)
1009
1087
  )
@@ -1109,14 +1187,25 @@ function getHighlightRowBinding(
1109
1187
  defaultHighlightRowDefinition = getMessageTypeFromCriticalityType(criticalityAnnotation);
1110
1188
  }
1111
1189
  }
1112
- return ifElse(
1113
- isDraftRoot && Draft.IsNewObject,
1114
- MessageType.Information as MessageType,
1115
- formatResult(
1116
- [defaultHighlightRowDefinition, bindingExpression(`filteredMessages`, "internal")],
1117
- tableFormatters.rowHighlighting,
1118
- targetEntityType
1119
- )
1190
+
1191
+ const aMissingKeys: any[] = [];
1192
+ targetEntityType?.keys.forEach((key: any) => {
1193
+ if (key.name !== "IsActiveEntity") {
1194
+ aMissingKeys.push(bindingExpression(key.name, undefined));
1195
+ }
1196
+ });
1197
+
1198
+ return formatResult(
1199
+ [
1200
+ defaultHighlightRowDefinition,
1201
+ bindingExpression(`filteredMessages`, "internal"),
1202
+ isDraftRoot && Entity.HasActive,
1203
+ isDraftRoot && Entity.IsActive,
1204
+ `${isDraftRoot}`,
1205
+ ...aMissingKeys
1206
+ ],
1207
+ tableFormatters.rowHighlighting,
1208
+ targetEntityType
1120
1209
  );
1121
1210
  }
1122
1211
 
@@ -1129,10 +1218,10 @@ function _getCreationBehaviour(
1129
1218
  const navigation = navigationSettings?.create || navigationSettings?.detail;
1130
1219
 
1131
1220
  // cross-app
1132
- if (navigation?.outbound && navigation.outboundDetail && navigationSettings?.create) {
1221
+ if (isExternalCreateConfigured(navigationSettings) && navigation) {
1133
1222
  return {
1134
1223
  mode: "External",
1135
- outbound: navigation.outbound,
1224
+ outbound: navigation.outbound as string,
1136
1225
  outboundDetail: navigation.outboundDetail,
1137
1226
  navigationSettings: navigationSettings
1138
1227
  };
@@ -1361,7 +1450,8 @@ const getColumnDefinitionFromProperty = function(
1361
1450
  trueValue: property.type === "Edm.Boolean" ? "Yes" : undefined,
1362
1451
  falseValue: property.type === "Edm.Boolean" ? "No" : undefined
1363
1452
  };
1364
- return {
1453
+
1454
+ const oColumn: any = {
1365
1455
  key: key,
1366
1456
  isGroupable: !isDataPointFakeProperty && !isHidden ? aggregationHelper.isPropertyGroupable(property) : false,
1367
1457
  type: ColumnType.Annotation,
@@ -1384,7 +1474,13 @@ const getColumnDefinitionFromProperty = function(
1384
1474
  caseSensitive: isFilteringCaseSensitive(converterContext),
1385
1475
  typeConfig: oTypeConfig,
1386
1476
  visualSettings: isDataPointFakeProperty ? { widthCalculation: null } : undefined
1387
- } as AnnotationTableColumn;
1477
+ };
1478
+ const sTooltip = _getTooltip(property);
1479
+ if (sTooltip) {
1480
+ oColumn.tooltip = sTooltip;
1481
+ }
1482
+
1483
+ return oColumn as AnnotationTableColumn;
1388
1484
  };
1389
1485
 
1390
1486
  /**
@@ -1426,7 +1522,7 @@ const _isValidColumn = function(dataField: DataFieldAbstractTypes) {
1426
1522
  export const _getVisibleExpression = function(
1427
1523
  dataFieldModelPath: DataModelObjectPath,
1428
1524
  formatOptions?: any,
1429
- returnExpression?: Boolean
1525
+ returnExpression: boolean = false
1430
1526
  ): BindingExpression<string> {
1431
1527
  const targetObject: DataFieldAbstractTypes | DataPointTypeTypes = dataFieldModelPath.targetObject;
1432
1528
  let propertyValue;
@@ -1479,7 +1575,7 @@ export const _getVisibleExpression = function(
1479
1575
  const _getFieldGroupHiddenExpressions = function(
1480
1576
  dataFieldGroup: DataFieldAbstractTypes,
1481
1577
  fieldFormatOptions: any
1482
- ): BindingExpression<string> {
1578
+ ): BindingExpression<string> | undefined {
1483
1579
  const aFieldGroupHiddenExpressions: BindingExpression<string>[] = [];
1484
1580
  if (
1485
1581
  dataFieldGroup.$Type === UIAnnotationTypes.DataFieldForAnnotation &&
@@ -1493,6 +1589,8 @@ const _getFieldGroupHiddenExpressions = function(
1493
1589
  return compileBinding(
1494
1590
  ifElse(or(...(aFieldGroupHiddenExpressions as ExpressionOrPrimitive<boolean>[])), constant(true), constant(false))
1495
1591
  );
1592
+ } else {
1593
+ return undefined;
1496
1594
  }
1497
1595
  };
1498
1596
 
@@ -1533,6 +1631,29 @@ const _getLabel = function(property: DataFieldAbstractTypes | Property, isGroup:
1533
1631
  }
1534
1632
  };
1535
1633
 
1634
+ const _getTooltip = function(source: DataFieldAbstractTypes | Property): string | undefined {
1635
+ if (!source) {
1636
+ return undefined;
1637
+ }
1638
+
1639
+ if (isProperty(source)) {
1640
+ return source.annotations.Common?.QuickInfo
1641
+ ? compileBinding(annotationExpression(source.annotations.Common.QuickInfo.valueOf()))
1642
+ : undefined;
1643
+ } else if (isDataFieldTypes(source)) {
1644
+ return source.Value?.$target?.annotations?.Common?.QuickInfo
1645
+ ? compileBinding(annotationExpression(source.Value.$target.annotations.Common.QuickInfo.valueOf()))
1646
+ : undefined;
1647
+ } else if (source.$Type === UIAnnotationTypes.DataFieldForAnnotation) {
1648
+ const datapointTarget = source.Target?.$target as DataPoint;
1649
+ return datapointTarget?.Value?.$target?.annotations?.Common?.QuickInfo
1650
+ ? compileBinding(annotationExpression(datapointTarget.Value.$target.annotations.Common.QuickInfo.valueOf()))
1651
+ : undefined;
1652
+ } else {
1653
+ return undefined;
1654
+ }
1655
+ };
1656
+
1536
1657
  /**
1537
1658
  * Creates a PropertyInfo for each identified property consumed by a LineItem.
1538
1659
  *
@@ -1797,7 +1918,6 @@ const getColumnsFromAnnotations = function(
1797
1918
  converterContext.getEntityType()
1798
1919
  ])[0];
1799
1920
  if (lineItemAnnotation) {
1800
- // Get columns from the LineItem Annotation
1801
1921
  lineItemAnnotation.forEach(lineItem => {
1802
1922
  if (!_isValidColumn(lineItem)) {
1803
1923
  return;
@@ -1816,10 +1936,9 @@ const getColumnsFromAnnotations = function(
1816
1936
  const sLabel: string | undefined = _getLabel(lineItem, isGroup);
1817
1937
  const name = _getAnnotationColumnName(lineItem);
1818
1938
  const isFieldGroupColumn: boolean = groupPath.indexOf("@com.sap.vocabularies.UI.v1.FieldGroup") > -1;
1819
- const showDataFieldsLabel: boolean =
1820
- isFieldGroupColumn && (lineItem as any)?.Target?.$target?.Data.length > 1
1821
- ? _getShowDataFieldsLabel(name, visualizationPath, converterContext)
1822
- : false;
1939
+ const showDataFieldsLabel: boolean = isFieldGroupColumn
1940
+ ? _getShowDataFieldsLabel(name, visualizationPath, converterContext)
1941
+ : false;
1823
1942
  const dataType: string | undefined = getDataFieldDataType(lineItem);
1824
1943
  const sDateInputFormat: string | undefined = dataType === "Edm.Date" ? "YYYY-MM-DD" : undefined;
1825
1944
  const formatOptions = {
@@ -1866,7 +1985,19 @@ const getColumnsFromAnnotations = function(
1866
1985
  visualSettings.widthCalculation = null;
1867
1986
  }
1868
1987
 
1869
- annotationColumns.push({
1988
+ // TODO: For situation POC - increase width of the column with the situations indicator - works for the situations demo app only!
1989
+ // Might be a good idea to move the complete column width determination to the converter, that would allow us to widen
1990
+ // the columns as needed. This workaround only deals with Date columns.
1991
+ const { hasDraftIndicator } = getDefaultDraftIndicatorForColumn(name, semanticKeys);
1992
+ const widthOverride =
1993
+ (converterContext.getEntityType().annotations as any).FE?.Situations &&
1994
+ hasDraftIndicator &&
1995
+ lineItem.$Type === UIAnnotationTypes.DataField &&
1996
+ lineItem.Value.$target.type === "Edm.Date"
1997
+ ? "11em"
1998
+ : undefined;
1999
+
2000
+ const oColumn: any = {
1870
2001
  key: KeyHelper.generateKeyFromDataField(lineItem),
1871
2002
  type: ColumnType.Annotation,
1872
2003
  label: sLabel,
@@ -1883,14 +2014,20 @@ const getColumnsFromAnnotations = function(
1883
2014
  propertyInfos: relatedPropertyNames.length > 0 ? relatedPropertyNames : undefined,
1884
2015
  additionalPropertyInfos: additionalPropertyNames.length > 0 ? additionalPropertyNames : undefined,
1885
2016
  exportSettings: exportSettings,
1886
- width: lineItem.annotations?.HTML5?.CssDefaults?.width || undefined,
2017
+ width: lineItem.annotations?.HTML5?.CssDefaults?.width || widthOverride || undefined,
1887
2018
  isNavigable: true,
1888
2019
  formatOptions: formatOptions,
1889
2020
  exportContactProperty: relatedPropertiesInfo.exportSettingsContactProperty,
1890
2021
  caseSensitive: isFilteringCaseSensitive(converterContext),
1891
2022
  typeConfig: oTypeConfig,
1892
2023
  visualSettings: visualSettings
1893
- } as AnnotationTableColumn);
2024
+ };
2025
+ const sTooltip = _getTooltip(lineItem);
2026
+ if (sTooltip) {
2027
+ oColumn.tooltip = sTooltip;
2028
+ }
2029
+
2030
+ annotationColumns.push(oColumn as AnnotationTableColumn);
1894
2031
 
1895
2032
  // Collect information of related columns to be created.
1896
2033
  relatedPropertyNames.forEach(name => {
@@ -2021,36 +2158,48 @@ const getColumnsFromManifest = function(
2021
2158
  converterContext,
2022
2159
  entityType
2023
2160
  );
2024
-
2025
- internalColumns[key] = {
2026
- key: key,
2027
- id: "CustomColumn::" + key,
2028
- name: "CustomColumn::" + key,
2029
- header: manifestColumn.header,
2030
- width: manifestColumn.width || undefined,
2031
- horizontalAlign: _getManifestOrDefaultValue(manifestColumn?.horizontalAlign, HorizontalAlign.Begin, isAnnotationColumn),
2032
- type: manifestColumn.type === "Slot" ? ColumnType.Slot : ColumnType.Default,
2033
- availability: _getManifestOrDefaultValue(manifestColumn?.availability, AvailabilityType.Default, isAnnotationColumn),
2034
- template: manifestColumn.template || "undefined",
2035
- position: {
2036
- anchor: manifestColumn.position?.anchor,
2037
- placement: manifestColumn.position === undefined ? Placement.After : manifestColumn.position.placement
2038
- },
2039
- isNavigable: isAnnotationColumn ? undefined : isActionNavigable(manifestColumn, navigationSettings, true),
2040
- settings: manifestColumn.settings,
2041
- sortable: false,
2042
- propertyInfos: propertyInfos,
2043
- formatOptions: {
2044
- ...getDefaultFormatOptionsForTable(),
2045
- ...manifestColumn.formatOptions
2046
- },
2047
- exportSettings: {
2048
- template: propertyInfos ? _appendCustomTemplate(propertyInfos) : undefined,
2049
- fieldLabel: propertyInfos ? manifestColumn.header : undefined,
2050
- wrap: propertyInfos && propertyInfos.length > 1 ? true : false
2051
- },
2052
- caseSensitive: isFilteringCaseSensitive(converterContext)
2053
- };
2161
+ if (!manifestColumn?.template && !isAnnotationColumn) {
2162
+ const Message = "The annotation column '" + key + "' referenced in the manifest is not found";
2163
+ converterContext
2164
+ .getDiagnostics()
2165
+ .addIssue(
2166
+ IssueCategory.Manifest,
2167
+ IssueSeverity.Low,
2168
+ Message,
2169
+ IssueCategoryType,
2170
+ IssueCategoryType?.AnnotationColumns?.InvalidKey
2171
+ );
2172
+ } else {
2173
+ internalColumns[key] = {
2174
+ key: key,
2175
+ id: "CustomColumn::" + key,
2176
+ name: "CustomColumn::" + key,
2177
+ header: manifestColumn.header,
2178
+ width: manifestColumn.width || undefined,
2179
+ horizontalAlign: _getManifestOrDefaultValue(manifestColumn?.horizontalAlign, HorizontalAlign.Begin, isAnnotationColumn),
2180
+ type: manifestColumn.type === "Slot" ? ColumnType.Slot : ColumnType.Default,
2181
+ availability: _getManifestOrDefaultValue(manifestColumn?.availability, AvailabilityType.Default, isAnnotationColumn),
2182
+ template: manifestColumn.template || "undefined",
2183
+ position: {
2184
+ anchor: manifestColumn.position?.anchor,
2185
+ placement: manifestColumn.position === undefined ? Placement.After : manifestColumn.position.placement
2186
+ },
2187
+ isNavigable: isAnnotationColumn ? undefined : isActionNavigable(manifestColumn, navigationSettings, true),
2188
+ settings: manifestColumn.settings,
2189
+ sortable: false,
2190
+ propertyInfos: propertyInfos,
2191
+ formatOptions: {
2192
+ ...getDefaultFormatOptionsForTable(),
2193
+ ...manifestColumn.formatOptions
2194
+ },
2195
+ exportSettings: {
2196
+ template: propertyInfos ? _appendCustomTemplate(propertyInfos) : undefined,
2197
+ fieldLabel: propertyInfos ? manifestColumn.header : undefined,
2198
+ wrap: propertyInfos && propertyInfos.length > 1 ? true : false
2199
+ },
2200
+ caseSensitive: isFilteringCaseSensitive(converterContext)
2201
+ };
2202
+ }
2054
2203
  }
2055
2204
  return internalColumns;
2056
2205
  };
@@ -2094,9 +2243,10 @@ export function getP13nMode(
2094
2243
  // No personalization configured in manifest.
2095
2244
  aPersonalization.push("Sort");
2096
2245
  aPersonalization.push("Column");
2097
- if (variantManagement === VariantManagementType.Control) {
2246
+ if (variantManagement === VariantManagementType.Control || _isFilterBarHidden(manifestWrapper, converterContext)) {
2098
2247
  // Feature parity with V2.
2099
2248
  // Enable table filtering by default only in case of Control level variant management.
2249
+ // Or when the LR filter bar is hidden via manifest setting
2100
2250
  aPersonalization.push("Filter");
2101
2251
  }
2102
2252
  if (bAnalyticalTable) {
@@ -2109,256 +2259,20 @@ export function getP13nMode(
2109
2259
  }
2110
2260
 
2111
2261
  /**
2112
- * Function to determine the visibility of the Delete button.
2113
- *
2114
- * @param converterContext The instance of the converter context
2115
- * @param navigationPath Path to the navigation entity
2116
- * @param isTargetDeletable Flag which determines whether a target is deletable
2117
- * @param viewConfiguration The instance of the configuration for the view path
2118
- * @returns {Expression<boolean>} The expression for the Delete button
2119
- */
2120
- export function getDeleteVisible(
2121
- converterContext: ConverterContext,
2122
- navigationPath: string,
2123
- isTargetDeletable: boolean,
2124
- viewConfiguration?: ViewPathConfiguration
2125
- ): Expression<boolean> {
2126
- const currentEntitySet = converterContext.getEntitySet();
2127
- const dataModelObjectPath = converterContext.getDataModelObjectPath();
2128
- const visitedNavigationPaths = dataModelObjectPath.navigationProperties.map(navProp => navProp.name);
2129
- const isDeleteHiddenExpression = currentEntitySet
2130
- ? annotationExpression(
2131
- (currentEntitySet?.annotations.UI?.DeleteHidden as PropertyAnnotationValue<boolean>) || false,
2132
- visitedNavigationPaths,
2133
- undefined,
2134
- (path: string) => singletonPathVisitor(path, converterContext, visitedNavigationPaths)
2135
- )
2136
- : constant(false);
2137
- const isDeleteHidden: any = compileBinding(isDeleteHiddenExpression);
2138
- let isParentDeletable, parentEntitySetDeletable;
2139
- if (converterContext.getTemplateType() === TemplateType.ObjectPage) {
2140
- isParentDeletable = isPathDeletable(converterContext.getDataModelObjectPath(), navigationPath);
2141
- parentEntitySetDeletable = isParentDeletable ? compileBinding(isParentDeletable) : isParentDeletable;
2142
- }
2143
- const bIsStickySessionSupported = converterContext.getDataModelObjectPath().startingEntitySet?.annotations?.Session
2144
- ?.StickySessionSupported
2145
- ? true
2146
- : false;
2147
- const bIsDraftRoot = currentEntitySet && currentEntitySet.annotations?.Common?.DraftRoot ? true : false;
2148
- const bIsDraftNode = currentEntitySet && currentEntitySet.annotations?.Common?.DraftNode ? true : false;
2149
- const bIsDraftParentEntityForContainment =
2150
- converterContext.getDataModelObjectPath().targetObject?.containsTarget &&
2151
- (converterContext.getDataModelObjectPath().startingEntitySet?.annotations?.Common?.DraftRoot ||
2152
- converterContext.getDataModelObjectPath().startingEntitySet?.annotations?.Common?.DraftNode)
2153
- ? true
2154
- : false;
2155
- if (
2156
- bIsDraftRoot ||
2157
- bIsDraftNode ||
2158
- bIsStickySessionSupported ||
2159
- (!converterContext.getEntitySet() && bIsDraftParentEntityForContainment)
2160
- ) {
2161
- //do not show case the delete button if parentEntitySetDeletable is false
2162
- if (parentEntitySetDeletable === "false") {
2163
- return constant(false);
2164
- //OP
2165
- } else if (parentEntitySetDeletable && isDeleteHidden !== "true") {
2166
- //Delete Hidden in case of true and path based
2167
- if (isDeleteHidden && isDeleteHidden !== "false") {
2168
- return and(equal(bindingExpression("/editMode", "ui"), "Editable"), not(isDeleteHiddenExpression));
2169
- } else {
2170
- return equal(bindingExpression("/editMode", "ui"), "Editable");
2171
- }
2172
- } else if (
2173
- isDeleteHidden === "true" ||
2174
- !isTargetDeletable ||
2175
- (viewConfiguration && converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration)) ||
2176
- converterContext.getTemplateType() === TemplateType.AnalyticalListPage
2177
- ) {
2178
- return constant(false);
2179
- } else if (converterContext.getTemplateType() !== TemplateType.ListReport) {
2180
- if (isDeleteHidden && isDeleteHidden === "false") {
2181
- return and(equal(bindingExpression("/editMode", "ui"), "Editable"), not(isDeleteHiddenExpression));
2182
- } else {
2183
- return equal(bindingExpression("/editMode", "ui"), "Editable");
2184
- }
2185
- } else if (isBinding(isDeleteHiddenExpression)) {
2186
- // UI.DeleteHidden annotation points to a path
2187
- return not(isDeleteHiddenExpression);
2188
- } else {
2189
- return constant(true);
2190
- }
2191
- } else {
2192
- return constant(false);
2193
- }
2194
- }
2195
-
2196
- /**
2197
- * Returns the enablement for the 'Mass Edit' button
2198
- *
2199
- * @param converterContext The converterContext
2200
- * @param bMassEditVisible The visibility of the 'Mass Edit' button
2201
- * @returns {*} Expression or Boolean value for the enablement of the 'Mass Edit' button
2202
- */
2203
-
2204
- export function getEnablementMassEdit(
2205
- converterContext: ConverterContext,
2206
- bMassEditVisible: string | boolean | undefined
2207
- ): string | boolean {
2208
- if (bMassEditVisible) {
2209
- const isParentUpdatable: any = isPathUpdatable(converterContext.getDataModelObjectPath(), undefined, true);
2210
- //when updatable is path based and pointing to current entity set property, that case is handled in table helper and runtime
2211
- if (isParentUpdatable?.currentEntityRestriction) {
2212
- return false;
2213
- }
2214
- const oExpression: any = compileBinding(isParentUpdatable);
2215
- return isParentUpdatable
2216
- ? "{= %{internal>numberOfSelectedContexts} >= 2 && " + compileBinding(isParentUpdatable, oExpression) + "}"
2217
- : false;
2218
- }
2219
- return false;
2220
- }
2221
-
2222
- /**
2223
- * Returns the visibility for the 'Mass Edit' button
2262
+ * Returns a boolean suggesting if a filter bar is being used on the page.
2224
2263
  *
2225
- * @param converterContext The converterContext
2226
- * @param tableManifestConfiguration The manifest configuration for the table
2227
- * @param targetCapabilities The target capability restrictions for the table
2228
- * @param selectionMode The selection mode for the table
2229
- * @returns {*} Expression or Boolean value for the visibility of the 'Mass Edit' button
2230
- */
2231
-
2232
- export function getVisibilityMassEdit(
2233
- converterContext: ConverterContext,
2234
- tableManifestConfiguration: TableControlConfiguration,
2235
- targetCapabilities: TableCapabilityRestriction,
2236
- selectionMode: string | undefined
2237
- ): boolean | string | undefined {
2238
- const entitySet = converterContext.getEntitySet(),
2239
- bUpdateHidden: any = entitySet && entitySet?.annotations.UI?.UpdateHidden?.valueOf(),
2240
- bMassEditEnabled: boolean = tableManifestConfiguration?.enableMassEdit || false,
2241
- iSelectionLimit: number = tableManifestConfiguration?.selectionLimit;
2242
- let bMassEditVisible: boolean = true;
2243
- if ((selectionMode && selectionMode === "Single") || (iSelectionLimit && iSelectionLimit < 2)) {
2244
- bMassEditVisible = false;
2245
- } else if (selectionMode && (selectionMode === "Auto" || selectionMode === "None")) {
2246
- bMassEditVisible = true;
2247
- }
2248
- if (targetCapabilities?.isUpdatable !== false && bMassEditVisible && bMassEditEnabled) {
2249
- if (bUpdateHidden && typeof bUpdateHidden === "boolean") {
2250
- return !bUpdateHidden && converterContext.getTemplateType() === TemplateType.ObjectPage ? compileBinding(UI.IsEditable) : false;
2251
- } else if (bUpdateHidden && bUpdateHidden?.path) {
2252
- return converterContext.getTemplateType() === TemplateType.ObjectPage
2253
- ? compileBinding(and(equal(UI.IsEditable, true), equal(annotationExpression(bUpdateHidden), false)))
2254
- : false;
2255
- }
2256
- return converterContext.getTemplateType() === TemplateType.ObjectPage ? compileBinding(UI.IsEditable) : false;
2257
- }
2258
- return false;
2259
- }
2260
-
2261
- /**
2262
- * Function to determine the visibility of the Create button.
2264
+ * Chart has a dependency to filter bar (issue with loading data). Once resolved, the check for chart should be removed here.
2265
+ * Until then, hiding filter bar is now allowed if a chart is being used on LR.
2263
2266
  *
2264
- * @param converterContext The instance of the converter context
2265
- * @param creationMode The mode used for creation
2266
- * @param isInsertable Annotation expression of InsertRestrictions.Insertable
2267
- * @param viewConfiguration The instance of the configuration for the view path
2268
- * @returns {Expression<boolean>} Expression or Boolean value of the 'UI.CreateHidden' annotation
2269
- */
2270
- export function getCreateVisible(
2271
- converterContext: ConverterContext,
2272
- creationMode: CreationMode | "External",
2273
- isInsertable: Expression<boolean>,
2274
- viewConfiguration?: ViewPathConfiguration
2275
- ): Expression<boolean> {
2276
- const currentEntitySet = converterContext.getEntitySet();
2277
- const dataModelObjectPath = converterContext.getDataModelObjectPath();
2278
- const visitedNavigationPaths = dataModelObjectPath.navigationProperties.map(navProp => navProp.name);
2279
- const isCreateHidden: Expression<boolean> = currentEntitySet
2280
- ? annotationExpression(
2281
- (currentEntitySet?.annotations.UI?.CreateHidden as PropertyAnnotationValue<boolean>) || false,
2282
- visitedNavigationPaths,
2283
- undefined,
2284
- (path: string) => singletonPathVisitor(path, converterContext, visitedNavigationPaths)
2285
- )
2286
- : constant(false);
2287
-
2288
- // if there is a custom new action the create button will be bound against this new action (instead of a POST action).
2289
- // The visibility of the create button then depends on the new action's OperationAvailable annotation (instead of the insertRestrictions):
2290
- // OperationAvailable = true or undefined -> create is visible
2291
- // OperationAvailable = false -> create is not visible
2292
- const newActionName: BindingExpression<string> = currentEntitySet?.annotations.Common?.DraftRoot?.NewAction?.toString();
2293
- const showCreateForNewAction = newActionName
2294
- ? annotationExpression(
2295
- converterContext?.getEntityType().actions[newActionName].annotations?.Core?.OperationAvailable?.valueOf(),
2296
- [],
2297
- true,
2298
- (path: string) => singletonPathVisitor(path, converterContext, [])
2299
- )
2300
- : undefined;
2301
- // - If it's statically not insertable -> create is not visible
2302
- // - If create is statically hidden -> create is not visible
2303
- // - If it's an ALP template -> create is not visible
2304
- // -
2305
- // - Otherwise
2306
- // - If the create mode is external -> create is visible
2307
- // - If we're on the list report ->
2308
- // - If UI.CreateHidden points to a property path -> provide a negated binding to this path
2309
- // - Otherwise, create is visible
2310
- // - Otherwise
2311
- // - This depends on the value of the the UI.IsEditable
2312
- return ifElse(
2313
- or(
2314
- or(
2315
- equal(showCreateForNewAction, false),
2316
- and(isConstant(isInsertable), equal(isInsertable, false), equal(showCreateForNewAction, undefined))
2317
- ),
2318
- isConstant(isCreateHidden) && equal(isCreateHidden, true),
2319
- or(
2320
- viewConfiguration ? converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration) : false,
2321
- converterContext.getTemplateType() === TemplateType.AnalyticalListPage
2322
- )
2323
- ),
2324
- false,
2325
- ifElse(
2326
- creationMode === "External",
2327
- true,
2328
- ifElse(
2329
- converterContext.getTemplateType() === TemplateType.ListReport,
2330
- ifElse(isBinding(isCreateHidden), not(isCreateHidden), true),
2331
- and(not(isCreateHidden), UI.IsEditable)
2332
- )
2333
- )
2334
- );
2335
- }
2336
-
2337
- /**
2338
- * Returns the visibility for the Paste button.
2339
- *
2340
- * @param converterContext The instance of the converter context
2341
- * @param creationBehaviour The chosen behavior of creation
2342
- * @param isInsertable The expression which denotes insert restrictions
2343
- * @param pasteEnabledInManifest The flag which denotes the paste enablement status via manifest
2344
- * @param viewConfiguration The instance of the configuration for the view path
2345
- * @returns {Expression<boolean>} Expression or Boolean value of the UI.CreateHidden annotation
2267
+ * @param {ManifestWrapper} manifestWrapper Manifest settings getter for the page
2268
+ * @param {ConverterContext} converterContext The instance of the converter context
2269
+ * @returns {boolean} Boolean suggesting if a filter bar is being used on the page.
2346
2270
  */
2347
- export function getPasteEnabled(
2348
- converterContext: ConverterContext,
2349
- creationBehaviour: TableAnnotationConfiguration["create"],
2350
- isInsertable: Expression<boolean>,
2351
- pasteEnabledInManifest: boolean,
2352
- viewConfiguration?: ViewPathConfiguration
2353
- ): Expression<boolean> {
2354
- // If create is not visible -> it's not enabled
2355
- // If create is visible ->
2356
- // If it's in the ListReport -> not enabled
2357
- // If it's insertable -> enabled
2358
- return ifElse(
2359
- pasteEnabledInManifest && equal(getCreateVisible(converterContext, creationBehaviour.mode, isInsertable, viewConfiguration), true),
2360
- converterContext.getTemplateType() === TemplateType.ObjectPage && isInsertable,
2361
- false
2271
+ function _isFilterBarHidden(manifestWrapper: ManifestWrapper, converterContext: ConverterContext): boolean {
2272
+ return (
2273
+ manifestWrapper.isFilterBarHidden() &&
2274
+ !converterContext.getManifestWrapper().hasMultipleVisualizations() &&
2275
+ converterContext.getTemplateType() !== TemplateType.AnalyticalListPage
2362
2276
  );
2363
2277
  }
2364
2278
 
@@ -2491,41 +2405,47 @@ export function getTableAnnotationConfiguration(
2491
2405
  p13nMode: string | undefined = getP13nMode(visualizationPath, converterContext, tableManifestConfiguration),
2492
2406
  id = navigationPropertyPath ? TableID(visualizationPath) : TableID(converterContext.getContextPath(), "LineItem");
2493
2407
  const targetCapabilities = getCapabilityRestriction(converterContext);
2494
- const isDeleteButtonVisible = getDeleteVisible(
2408
+ const navigationTargetPath = getNavigationTargetPath(converterContext, navigationPropertyPath);
2409
+ const navigationSettings = pageManifestSettings.getNavigationConfiguration(navigationTargetPath);
2410
+ const standardActionsContext = generateStandardActionsContext(
2495
2411
  converterContext,
2496
- navigationPropertyPath,
2497
- targetCapabilities.isDeletable,
2412
+ navigationSettings,
2413
+ tableManifestConfiguration,
2498
2414
  viewConfiguration
2499
2415
  );
2416
+
2417
+ const deleteButtonVisibilityExpression = getDeleteVisibility(converterContext, standardActionsContext);
2418
+ const createButtonVisibilityExpression = getCreateVisibility(converterContext, standardActionsContext);
2419
+ const massEditButtonVisibilityExpression = getMassEditVisibility(converterContext, standardActionsContext);
2420
+ const isInsertUpdateTemplated = getInsertUpdateActionsTemplating(
2421
+ standardActionsContext,
2422
+ isDraftOrStickySupported(converterContext),
2423
+ compileBinding(createButtonVisibilityExpression) === "false"
2424
+ );
2425
+
2500
2426
  const selectionMode = getSelectionMode(
2501
2427
  lineItemAnnotation,
2502
2428
  visualizationPath,
2503
2429
  converterContext,
2504
2430
  hasAbsolutePath,
2505
2431
  targetCapabilities,
2506
- isDeleteButtonVisible
2432
+ deleteButtonVisibilityExpression,
2433
+ massEditButtonVisibilityExpression
2507
2434
  );
2508
2435
  let threshold = navigationPropertyPath ? 10 : 30;
2509
2436
  if (presentationVariantAnnotation?.MaxItems) {
2510
2437
  threshold = presentationVariantAnnotation.MaxItems.valueOf() as number;
2511
2438
  }
2512
- const navigationTargetPath = getNavigationTargetPath(converterContext, navigationPropertyPath);
2513
- const navigationSettings = pageManifestSettings.getNavigationConfiguration(navigationTargetPath);
2439
+
2514
2440
  const creationBehaviour = _getCreationBehaviour(lineItemAnnotation, tableManifestConfiguration, converterContext, navigationSettings);
2515
- let isParentDeletable: any, parentEntitySetDeletable;
2516
- if (converterContext.getTemplateType() === TemplateType.ObjectPage) {
2517
- isParentDeletable = isPathDeletable(converterContext.getDataModelObjectPath(), undefined, true);
2518
- if (isParentDeletable?.currentEntityRestriction) {
2519
- parentEntitySetDeletable = undefined;
2520
- } else {
2521
- parentEntitySetDeletable = isParentDeletable ? compileBinding(isParentDeletable, true) : isParentDeletable;
2522
- }
2523
- }
2524
- const dataModelObjectPath = converterContext.getDataModelObjectPath();
2525
- const isInsertable: Expression<boolean> = isPathInsertable(dataModelObjectPath);
2526
2441
  const variantManagement: VariantManagementType = pageManifestSettings.getVariantManagement();
2527
- const bMassEditVisible: any = getVisibilityMassEdit(converterContext, tableManifestConfiguration, targetCapabilities, selectionMode);
2528
2442
  const isSearchable = isPathSearchable(converterContext.getDataModelObjectPath());
2443
+ const standardActions = {
2444
+ create: getStandardActionCreate(converterContext, standardActionsContext),
2445
+ "delete": getStandardActionDelete(converterContext, standardActionsContext),
2446
+ paste: getStandardActionPaste(converterContext, standardActionsContext, isInsertUpdateTemplated),
2447
+ massEdit: getStandardActionMassEdit(converterContext, standardActionsContext)
2448
+ };
2529
2449
 
2530
2450
  return {
2531
2451
  id: id,
@@ -2540,34 +2460,22 @@ export function getTableAnnotationConfiguration(
2540
2460
  navigationTargetPath
2541
2461
  ),
2542
2462
  p13nMode: p13nMode,
2543
- show: {
2544
- "delete": compileBinding(isDeleteButtonVisible),
2545
- create: compileBinding(getCreateVisible(converterContext, creationBehaviour?.mode, isInsertable)),
2546
- paste: compileBinding(
2547
- getPasteEnabled(
2548
- converterContext,
2549
- creationBehaviour,
2550
- isInsertable,
2551
- tableManifestConfiguration.enablePaste,
2552
- viewConfiguration
2553
- )
2554
- ),
2555
- massEdit: {
2556
- visible: bMassEditVisible,
2557
- enabled: getEnablementMassEdit(converterContext, bMassEditVisible)
2558
- }
2463
+ standardActions: {
2464
+ actions: standardActions,
2465
+ isInsertUpdateTemplated: isInsertUpdateTemplated,
2466
+ updatablePropertyPath: getCurrentEntitySetUpdatablePath(converterContext)
2559
2467
  },
2560
2468
  displayMode: isInDisplayMode(converterContext, viewConfiguration),
2561
2469
  create: creationBehaviour,
2562
2470
  selectionMode: selectionMode,
2563
2471
  autoBindOnInit:
2564
- converterContext.getTemplateType() !== TemplateType.ListReport &&
2565
- converterContext.getTemplateType() !== TemplateType.AnalyticalListPage &&
2566
- !(viewConfiguration && converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration)),
2472
+ _isFilterBarHidden(pageManifestSettings, converterContext) ||
2473
+ (converterContext.getTemplateType() !== TemplateType.ListReport &&
2474
+ converterContext.getTemplateType() !== TemplateType.AnalyticalListPage &&
2475
+ !(viewConfiguration && pageManifestSettings.hasMultipleVisualizations(viewConfiguration))),
2567
2476
  variantManagement: variantManagement === "Control" && !p13nMode ? VariantManagementType.None : variantManagement,
2568
2477
  threshold: threshold,
2569
2478
  sortConditions: getSortConditions(converterContext, presentationVariantAnnotation, columns),
2570
- parentEntityDeleteEnabled: parentEntitySetDeletable,
2571
2479
  title: title,
2572
2480
  searchable: tableManifestConfiguration.type !== "AnalyticalTable" && !(isConstant(isSearchable) && isSearchable.value === false)
2573
2481
  };
@@ -2606,19 +2514,6 @@ function _getExportDataType(dataType: string, isComplexProperty: boolean = false
2606
2514
  return exportDataType;
2607
2515
  }
2608
2516
 
2609
- function isInDisplayMode(converterContext: ConverterContext, viewConfiguration?: ViewPathConfiguration): boolean {
2610
- const templateType = converterContext.getTemplateType();
2611
- if (
2612
- templateType === TemplateType.ListReport ||
2613
- templateType === TemplateType.AnalyticalListPage ||
2614
- (viewConfiguration && converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration))
2615
- ) {
2616
- return true;
2617
- }
2618
- // updatable will be handled at the property level
2619
- return false;
2620
- }
2621
-
2622
2517
  /**
2623
2518
  * Split the visualization path into the navigation property path and annotation.
2624
2519
  *
@@ -2659,118 +2554,236 @@ export function getSelectionVariantConfiguration(
2659
2554
  return undefined;
2660
2555
  }
2661
2556
 
2557
+ function _getFullScreenBasedOnDevice(
2558
+ tableSettings: TableManifestSettingsConfiguration,
2559
+ converterContext: ConverterContext,
2560
+ isIphone: boolean
2561
+ ): boolean {
2562
+ // If enableFullScreen is not set, use as default true on phone and false otherwise
2563
+ let enableFullScreen = tableSettings.enableFullScreen ?? isIphone;
2564
+ // Make sure that enableFullScreen is not set on ListReport for desktop or tablet
2565
+ if (!isIphone && enableFullScreen && converterContext.getTemplateType() === TemplateType.ListReport) {
2566
+ enableFullScreen = false;
2567
+ converterContext.getDiagnostics().addIssue(IssueCategory.Manifest, IssueSeverity.Low, IssueType.FULLSCREENMODE_NOT_ON_LISTREPORT);
2568
+ }
2569
+ return enableFullScreen;
2570
+ }
2571
+
2572
+ function _getMultiSelectMode(
2573
+ tableSettings: TableManifestSettingsConfiguration,
2574
+ tableType: TableType,
2575
+ converterContext: ConverterContext
2576
+ ): string | undefined {
2577
+ let multiSelectMode: string | undefined;
2578
+ if (tableType !== "ResponsiveTable") {
2579
+ return undefined;
2580
+ }
2581
+ switch (converterContext.getTemplateType()) {
2582
+ case TemplateType.ListReport:
2583
+ case TemplateType.AnalyticalListPage:
2584
+ multiSelectMode = !tableSettings.selectAll ? "ClearAll" : "Default";
2585
+ break;
2586
+ case TemplateType.ObjectPage:
2587
+ multiSelectMode = tableSettings.selectAll === false ? "ClearAll" : "Default";
2588
+ if (converterContext.getManifestWrapper().useIconTabBar()) {
2589
+ multiSelectMode = !tableSettings.selectAll ? "ClearAll" : "Default";
2590
+ }
2591
+ break;
2592
+ default:
2593
+ }
2594
+
2595
+ return multiSelectMode;
2596
+ }
2597
+
2598
+ function _getTableType(
2599
+ tableSettings: TableManifestSettingsConfiguration,
2600
+ aggregationHelper: AggregationHelper,
2601
+ converterContext: ConverterContext
2602
+ ): TableType {
2603
+ let tableType = tableSettings?.type || "ResponsiveTable";
2604
+ if (converterContext.getTemplateType() !== "ObjectPage") {
2605
+ if (tableSettings?.type === "AnalyticalTable" && !aggregationHelper.isAnalyticsSupported()) {
2606
+ tableType = "GridTable";
2607
+ }
2608
+ if (!tableSettings?.type) {
2609
+ if (converterContext.getManifestWrapper().isDesktop() && aggregationHelper.isAnalyticsSupported()) {
2610
+ tableType = "AnalyticalTable";
2611
+ } else {
2612
+ tableType = "ResponsiveTable";
2613
+ }
2614
+ }
2615
+ }
2616
+ return tableType;
2617
+ }
2618
+ function _getFilters(
2619
+ tableSettings: TableManifestSettingsConfiguration,
2620
+ quickFilterPaths: { annotationPath: string }[],
2621
+ quickSelectionVariant: any,
2622
+ path: { annotationPath: string },
2623
+ converterContext: ConverterContext
2624
+ ): any {
2625
+ if (quickSelectionVariant) {
2626
+ quickFilterPaths.push({ annotationPath: path.annotationPath });
2627
+ }
2628
+ return {
2629
+ quickFilters: {
2630
+ enabled:
2631
+ converterContext.getTemplateType() === TemplateType.ListReport ? "{= ${pageInternal>hasPendingFilters} !== true}" : true,
2632
+ showCounts: tableSettings?.quickVariantSelection?.showCounts,
2633
+ paths: quickFilterPaths
2634
+ }
2635
+ };
2636
+ }
2637
+
2638
+ function _getEnableExport(
2639
+ tableSettings: TableManifestSettingsConfiguration,
2640
+ converterContext: ConverterContext,
2641
+ enablePaste: boolean
2642
+ ): boolean {
2643
+ return tableSettings.enableExport !== undefined
2644
+ ? tableSettings.enableExport
2645
+ : converterContext.getTemplateType() !== "ObjectPage" || enablePaste;
2646
+ }
2647
+
2648
+ function _getFilterConfiguration(
2649
+ tableSettings: TableManifestSettingsConfiguration,
2650
+ lineItemAnnotation: LineItem | undefined,
2651
+ converterContext: ConverterContext
2652
+ ): any {
2653
+ if (!lineItemAnnotation) {
2654
+ return {};
2655
+ }
2656
+ const quickFilterPaths: { annotationPath: string }[] = [];
2657
+ const targetEntityType = converterContext.getAnnotationEntityType(lineItemAnnotation);
2658
+ let quickSelectionVariant: any;
2659
+ let filters;
2660
+ tableSettings?.quickVariantSelection?.paths?.forEach((path: { annotationPath: string }) => {
2661
+ quickSelectionVariant = targetEntityType.resolvePath("@" + path.annotationPath);
2662
+ filters = _getFilters(tableSettings, quickFilterPaths, quickSelectionVariant, path, converterContext);
2663
+ });
2664
+
2665
+ let hideTableTitle = false;
2666
+ hideTableTitle = !!tableSettings.quickVariantSelection?.hideTableTitle;
2667
+ return {
2668
+ filters: filters,
2669
+ headerVisible: !(quickSelectionVariant && hideTableTitle)
2670
+ };
2671
+ }
2672
+
2662
2673
  export function getTableManifestConfiguration(
2663
2674
  lineItemAnnotation: LineItem | undefined,
2664
2675
  visualizationPath: string,
2665
2676
  converterContext: ConverterContext,
2666
- checkCondensedLayout: boolean = false
2677
+ checkCondensedLayout = false
2667
2678
  ): TableControlConfiguration {
2668
2679
  const tableManifestSettings: TableManifestConfiguration = converterContext.getManifestControlConfiguration(visualizationPath);
2669
2680
  const tableSettings = (tableManifestSettings && tableManifestSettings.tableSettings) || {};
2670
- let quickSelectionVariant: any;
2671
- const quickFilterPaths: { annotationPath: string }[] = [];
2672
- let enableExport = true;
2673
- let creationMode = CreationMode.NewPage;
2674
- let filters;
2675
- let createAtEnd = true;
2676
- let disableAddRowButtonForEmptyData = false;
2677
- let customValidationFunction;
2678
- let condensedTableLayout = false;
2679
- let hideTableTitle = false;
2680
- let tableType: TableType = "ResponsiveTable";
2681
- let enableFullScreen = false;
2682
- let selectionLimit = 200;
2683
- let multiSelectMode;
2684
- const enableAutoColumnWidth = true;
2685
- let enablePaste = converterContext.getTemplateType() === "ObjectPage";
2681
+ const creationMode = CreationMode.NewPage;
2682
+ const enableAutoColumnWidth = !converterContext.getManifestWrapper().isPhone();
2683
+ const enablePaste =
2684
+ tableSettings.enablePaste !== undefined ? tableSettings.enablePaste : converterContext.getTemplateType() === "ObjectPage"; // Paste is disabled by default excepted for OP
2685
+ const dataStateIndicatorFilter =
2686
+ converterContext.getTemplateType() === TemplateType.ListReport ? "API.dataStateIndicatorFilter" : undefined;
2686
2687
  const isCondensedTableLayoutCompliant = checkCondensedLayout && converterContext.getManifestWrapper().isCondensedLayoutCompliant();
2688
+ const oFilterConfiguration = _getFilterConfiguration(tableSettings, lineItemAnnotation, converterContext);
2689
+ const customValidationFunction = tableSettings.creationMode?.customValidationFunction;
2690
+ const condensedTableLayout = tableSettings.condensedTableLayout !== undefined ? tableSettings.condensedTableLayout : false;
2687
2691
  const entityType = converterContext.getEntityType();
2688
2692
  const aggregationHelper = new AggregationHelper(entityType, converterContext);
2689
- if (lineItemAnnotation) {
2690
- const targetEntityType = converterContext.getAnnotationEntityType(lineItemAnnotation);
2691
- tableSettings?.quickVariantSelection?.paths?.forEach((path: { annotationPath: string }) => {
2692
- quickSelectionVariant = targetEntityType.resolvePath("@" + path.annotationPath);
2693
- // quickSelectionVariant = converterContext.getEntityTypeAnnotation(path.annotationPath);
2694
- if (quickSelectionVariant) {
2695
- quickFilterPaths.push({ annotationPath: path.annotationPath });
2696
- }
2697
- filters = {
2698
- quickFilters: {
2699
- enabled:
2700
- converterContext.getTemplateType() === TemplateType.ListReport
2701
- ? "{= ${pageInternal>hasPendingFilters} !== true}"
2702
- : true,
2703
- showCounts: tableSettings?.quickVariantSelection?.showCounts,
2704
- paths: quickFilterPaths
2705
- }
2706
- };
2707
- });
2708
- creationMode = tableSettings.creationMode?.name || creationMode;
2709
- createAtEnd = tableSettings.creationMode?.createAtEnd !== undefined ? tableSettings.creationMode?.createAtEnd : true;
2710
- customValidationFunction = tableSettings.creationMode?.customValidationFunction;
2711
- // if a custom validation function is provided, disableAddRowButtonForEmptyData should not be considered, i.e. set to false
2712
- disableAddRowButtonForEmptyData = !customValidationFunction ? !!tableSettings.creationMode?.disableAddRowButtonForEmptyData : false;
2713
- condensedTableLayout = tableSettings.condensedTableLayout !== undefined ? tableSettings.condensedTableLayout : false;
2714
- hideTableTitle = !!tableSettings.quickVariantSelection?.hideTableTitle;
2715
- tableType = tableSettings?.type || "ResponsiveTable";
2716
- if (converterContext.getTemplateType() !== "ObjectPage") {
2717
- if (tableSettings?.type === "AnalyticalTable" && !aggregationHelper.isAnalyticsSupported()) {
2718
- tableType = "GridTable";
2719
- }
2720
- if (!tableSettings?.type) {
2721
- if (converterContext.getManifestWrapper().isDesktop() && aggregationHelper.isAnalyticsSupported()) {
2722
- tableType = "AnalyticalTable";
2723
- } else {
2724
- tableType = "ResponsiveTable";
2725
- }
2726
- }
2727
- }
2728
- enableFullScreen = tableSettings.enableFullScreen || false;
2729
- if (enableFullScreen === true && converterContext.getTemplateType() === TemplateType.ListReport) {
2730
- enableFullScreen = false;
2731
- converterContext
2732
- .getDiagnostics()
2733
- .addIssue(IssueCategory.Manifest, IssueSeverity.Low, IssueType.FULLSCREENMODE_NOT_ON_LISTREPORT);
2734
- }
2735
- selectionLimit = tableSettings.selectAll === true || tableSettings.selectionLimit === 0 ? 0 : tableSettings.selectionLimit || 200;
2736
- if (tableType === "ResponsiveTable") {
2737
- if (
2738
- converterContext.getTemplateType() === TemplateType.ListReport ||
2739
- converterContext.getTemplateType() === TemplateType.AnalyticalListPage
2740
- ) {
2741
- multiSelectMode = !!tableSettings.selectAll ? "Default" : "ClearAll";
2742
- }
2743
- if (converterContext.getTemplateType() === TemplateType.ObjectPage) {
2744
- if (converterContext.getManifestWrapper().useIconTabBar()) {
2745
- multiSelectMode = !!tableSettings.selectAll ? "Default" : "ClearAll";
2746
- } else {
2747
- multiSelectMode = tableSettings.selectAll === false ? "ClearAll" : "Default";
2748
- }
2749
- }
2750
- }
2751
- enablePaste = converterContext.getTemplateType() === "ObjectPage" && tableSettings.enablePaste !== false;
2752
- enableExport =
2753
- tableSettings.enableExport !== undefined
2754
- ? tableSettings.enableExport
2755
- : converterContext.getTemplateType() !== "ObjectPage" || enablePaste;
2756
- }
2757
- return {
2758
- filters: filters,
2759
- type: tableType,
2760
- enableFullScreen: enableFullScreen,
2761
- headerVisible: !(quickSelectionVariant && hideTableTitle),
2762
- enableExport: enableExport,
2763
- creationMode: creationMode,
2764
- createAtEnd: createAtEnd,
2765
- disableAddRowButtonForEmptyData: disableAddRowButtonForEmptyData,
2693
+ const tableType: TableType = _getTableType(tableSettings, aggregationHelper, converterContext);
2694
+ const oConfiguration = {
2695
+ createAtEnd: tableSettings.creationMode?.createAtEnd !== undefined ? tableSettings.creationMode?.createAtEnd : true,
2696
+ creationMode: tableSettings.creationMode?.name || creationMode,
2766
2697
  customValidationFunction: customValidationFunction,
2767
- useCondensedTableLayout: condensedTableLayout && isCondensedTableLayoutCompliant,
2768
- selectionLimit: selectionLimit,
2769
- multiSelectMode: multiSelectMode,
2698
+ dataStateIndicatorFilter: dataStateIndicatorFilter,
2699
+ // if a custom validation function is provided, disableAddRowButtonForEmptyData should not be considered, i.e. set to false
2700
+ disableAddRowButtonForEmptyData: !customValidationFunction ? !!tableSettings.creationMode?.disableAddRowButtonForEmptyData : false,
2701
+ enableAutoColumnWidth: enableAutoColumnWidth,
2702
+ enableExport: _getEnableExport(tableSettings, converterContext, enablePaste),
2703
+ enableFullScreen: _getFullScreenBasedOnDevice(tableSettings, converterContext, converterContext.getManifestWrapper().isPhone()),
2704
+ enableMassEdit: tableSettings?.enableMassEdit,
2770
2705
  enablePaste: enablePaste,
2706
+ headerVisible: true,
2707
+ multiSelectMode: _getMultiSelectMode(tableSettings, tableType, converterContext),
2708
+ selectionLimit: tableSettings.selectAll === true || tableSettings.selectionLimit === 0 ? 0 : tableSettings.selectionLimit || 200,
2709
+
2771
2710
  showRowCount:
2772
2711
  !tableSettings?.quickVariantSelection?.showCounts && !converterContext.getManifestWrapper().getViewConfiguration()?.showCounts,
2773
- enableMassEdit: tableSettings?.enableMassEdit,
2774
- enableAutoColumnWidth: enableAutoColumnWidth
2712
+ type: tableType,
2713
+ useCondensedTableLayout: condensedTableLayout && isCondensedTableLayoutCompliant
2714
+ };
2715
+
2716
+ return { ...oConfiguration, ...oFilterConfiguration };
2717
+ }
2718
+
2719
+ export type configTypeConstraints = {
2720
+ scale?: number;
2721
+ precision?: number;
2722
+ maxLength?: number;
2723
+ nullable?: boolean;
2724
+ minimum?: string;
2725
+ maximum?: string;
2726
+ isDigitSequence?: boolean;
2727
+ };
2728
+
2729
+ export type configTypeformatOptions = {
2730
+ parseAsString?: boolean;
2731
+ emptyString?: string;
2732
+ parseKeepsEmptyString?: boolean;
2733
+ };
2734
+
2735
+ export type configType = {
2736
+ type: string;
2737
+ constraints: configTypeConstraints;
2738
+ formatOptions: configTypeformatOptions;
2739
+ };
2740
+
2741
+ export function getTypeConfig(oProperty: Property | DataFieldAbstractTypes, dataType: string | undefined): any {
2742
+ let oTargetMapping = EDM_TYPE_MAPPING[(oProperty as Property)?.type] || (dataType ? EDM_TYPE_MAPPING[dataType] : undefined);
2743
+ if (!oTargetMapping && (oProperty as Property)?.targetType && (oProperty as Property).targetType?._type === "TypeDefinition") {
2744
+ oTargetMapping = EDM_TYPE_MAPPING[((oProperty as Property).targetType as TypeDefinition).underlyingType];
2745
+ }
2746
+ const propertyTypeConfig: configType = {
2747
+ type: oTargetMapping?.type,
2748
+ constraints: {},
2749
+ formatOptions: {}
2750
+ };
2751
+ if (isProperty(oProperty)) {
2752
+ propertyTypeConfig.constraints = {
2753
+ scale: oTargetMapping.constraints?.$Scale ? oProperty.scale : undefined,
2754
+ precision: oTargetMapping.constraints?.$Precision ? oProperty.precision : undefined,
2755
+ maxLength: oTargetMapping.constraints?.$MaxLength ? oProperty.maxLength : undefined,
2756
+ nullable: oTargetMapping.constraints?.$Nullable ? oProperty.nullable : undefined,
2757
+ minimum:
2758
+ oTargetMapping.constraints?.["@Org.OData.Validation.V1.Minimum/$Decimal"] &&
2759
+ !isNaN(oProperty.annotations?.Validation?.Minimum)
2760
+ ? `${oProperty.annotations?.Validation?.Minimum}`
2761
+ : undefined,
2762
+ maximum:
2763
+ oTargetMapping.constraints?.["@Org.OData.Validation.V1.Maximum/$Decimal"] &&
2764
+ !isNaN(oProperty.annotations?.Validation?.Maximum)
2765
+ ? `${oProperty.annotations?.Validation?.Maximum}`
2766
+ : undefined,
2767
+ isDigitSequence:
2768
+ propertyTypeConfig.type === "sap.ui.model.odata.type.String" &&
2769
+ oTargetMapping.constraints?.["@com.sap.vocabularies.Common.v1.IsDigitSequence"] &&
2770
+ (oProperty as Property).annotations?.Common?.IsDigitSequence
2771
+ ? true
2772
+ : undefined
2773
+ };
2774
+ }
2775
+ propertyTypeConfig.formatOptions = {
2776
+ parseAsString:
2777
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Int") === 0 ||
2778
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Double") === 0
2779
+ ? false
2780
+ : undefined,
2781
+ emptyString:
2782
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Int") === 0 ||
2783
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Double") === 0
2784
+ ? ""
2785
+ : undefined,
2786
+ parseKeepsEmptyString: propertyTypeConfig.type === "sap.ui.model.odata.type.String" ? true : undefined
2775
2787
  };
2788
+ return propertyTypeConfig;
2776
2789
  }