@sapui5/sap.fe.core 1.95.0 → 1.98.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 (207) hide show
  1. package/package.json +5 -5
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AnnotationHelper.js +3 -3
  4. package/src/sap/fe/core/AppComponent.js +9 -44
  5. package/src/sap/fe/core/AppStateHandler.js +2 -2
  6. package/src/sap/fe/core/BaseController.js +1 -1
  7. package/src/sap/fe/core/BusyLocker.js +13 -1
  8. package/src/sap/fe/core/CommonUtils.js +129 -219
  9. package/src/sap/fe/core/ExtensionAPI.js +14 -6
  10. package/src/sap/fe/core/PageController.js +9 -35
  11. package/src/sap/fe/core/RouterProxy.js +79 -75
  12. package/src/sap/fe/core/Synchronization.js +1 -1
  13. package/src/sap/fe/core/TemplateComponent.js +16 -7
  14. package/src/sap/fe/core/TemplateModel.js +1 -1
  15. package/src/sap/fe/core/TransactionHelper.js +183 -65
  16. package/src/sap/fe/core/actions/draft.js +50 -23
  17. package/src/sap/fe/core/actions/messageHandling.js +86 -7
  18. package/src/sap/fe/core/actions/nonDraft.js +1 -1
  19. package/src/sap/fe/core/actions/operations.js +75 -33
  20. package/src/sap/fe/core/actions/sticky.js +1 -1
  21. package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +1 -1
  22. package/src/sap/fe/core/controllerextensions/EditFlow.js +276 -122
  23. package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +1 -1
  24. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +14 -6
  25. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +90 -46
  26. package/src/sap/fe/core/controllerextensions/InternalRouting.js +234 -232
  27. package/src/sap/fe/core/controllerextensions/KPIManagement.js +539 -209
  28. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +550 -213
  29. package/src/sap/fe/core/controllerextensions/MassEdit.js +79 -0
  30. package/src/sap/fe/core/controllerextensions/MessageHandler.js +227 -103
  31. package/src/sap/fe/core/controllerextensions/PageReady.js +2 -2
  32. package/src/sap/fe/core/controllerextensions/PageReady.ts +3 -7
  33. package/src/sap/fe/core/controllerextensions/Paginator.js +38 -12
  34. package/src/sap/fe/core/controllerextensions/Placeholder.js +16 -19
  35. package/src/sap/fe/core/controllerextensions/Routing.js +17 -2
  36. package/src/sap/fe/core/controllerextensions/RoutingListener.js +1 -1
  37. package/src/sap/fe/core/controllerextensions/Share.js +20 -7
  38. package/src/sap/fe/core/controllerextensions/SideEffects.js +8 -9
  39. package/src/sap/fe/core/controllerextensions/SideEffects.ts +19 -17
  40. package/src/sap/fe/core/controllerextensions/ViewState.js +54 -9
  41. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +40 -34
  42. package/src/sap/fe/core/controls/ActionParameterDialogValueHelp.fragment.xml +35 -0
  43. package/src/sap/fe/core/controls/CommandExecution.js +1 -1
  44. package/src/sap/fe/core/controls/ConditionalWrapper.js +1 -1
  45. package/src/sap/fe/core/controls/CustomQuickViewPage.js +110 -109
  46. package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +7 -4
  47. package/src/sap/fe/core/controls/FieldWrapper.js +10 -4
  48. package/src/sap/fe/core/controls/FilterBar.js +1 -1
  49. package/src/sap/fe/core/controls/FormElementWrapper.js +1 -6
  50. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +45 -0
  51. package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +1 -1
  52. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +1 -1
  53. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +1 -1
  54. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +1 -1
  55. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +1 -1
  56. package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
  57. package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +78 -0
  58. package/src/sap/fe/core/converters/ConverterContext.js +13 -1
  59. package/src/sap/fe/core/converters/ConverterContext.ts +10 -0
  60. package/src/sap/fe/core/converters/ManifestSettings.js +2 -1
  61. package/src/sap/fe/core/converters/ManifestSettings.ts +7 -1
  62. package/src/sap/fe/core/converters/ManifestWrapper.js +18 -7
  63. package/src/sap/fe/core/converters/ManifestWrapper.ts +15 -6
  64. package/src/sap/fe/core/converters/MetaModelConverter.js +920 -882
  65. package/src/sap/fe/core/converters/MetaModelConverter.ts +829 -853
  66. package/src/sap/fe/core/converters/annotations/DataField.js +54 -4
  67. package/src/sap/fe/core/converters/annotations/DataField.ts +53 -3
  68. package/src/sap/fe/core/converters/common/AnnotationConverter.js +83 -48
  69. package/src/sap/fe/core/converters/controls/Common/Action.js +15 -3
  70. package/src/sap/fe/core/converters/controls/Common/Action.ts +12 -3
  71. package/src/sap/fe/core/converters/controls/Common/Chart.js +1 -3
  72. package/src/sap/fe/core/converters/controls/Common/Chart.ts +0 -2
  73. package/src/sap/fe/core/converters/controls/Common/Form.js +68 -21
  74. package/src/sap/fe/core/converters/controls/Common/Form.ts +60 -16
  75. package/src/sap/fe/core/converters/controls/Common/KPI.js +331 -248
  76. package/src/sap/fe/core/converters/controls/Common/KPI.ts +355 -287
  77. package/src/sap/fe/core/converters/controls/Common/Table.js +426 -332
  78. package/src/sap/fe/core/converters/controls/Common/Table.ts +516 -383
  79. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +468 -0
  80. package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +609 -0
  81. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +30 -13
  82. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +31 -12
  83. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
  84. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
  85. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +15 -7
  86. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +27 -6
  87. package/src/sap/fe/core/converters/helpers/Aggregation.js +8 -1
  88. package/src/sap/fe/core/converters/helpers/Aggregation.ts +9 -1
  89. package/src/sap/fe/core/converters/helpers/BindingHelper.js +3 -2
  90. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +2 -2
  91. package/src/sap/fe/core/converters/helpers/ID.js +9 -1
  92. package/src/sap/fe/core/converters/helpers/ID.ts +6 -2
  93. package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -5
  94. package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -4
  95. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +2 -2
  96. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +1 -1
  97. package/src/sap/fe/core/converters/templates/ListReportConverter.js +34 -4
  98. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +36 -7
  99. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +2 -5
  100. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +1 -2
  101. package/src/sap/fe/core/designtime/AppComponent.designtime.js +11 -2
  102. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  103. package/src/sap/fe/core/formatters/FPMFormatter.ts +8 -3
  104. package/src/sap/fe/core/formatters/TableFormatter.js +27 -4
  105. package/src/sap/fe/core/formatters/TableFormatter.ts +20 -3
  106. package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
  107. package/src/sap/fe/core/formatters/ValueFormatter.ts +25 -3
  108. package/src/sap/fe/core/fpm/Component.js +2 -2
  109. package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
  110. package/src/sap/fe/core/helpers/AppStartupHelper.ts +388 -0
  111. package/src/sap/fe/core/helpers/BindingExpression.js +199 -111
  112. package/src/sap/fe/core/helpers/BindingExpression.ts +193 -102
  113. package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +1 -1
  114. package/src/sap/fe/core/helpers/EditState.js +1 -1
  115. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +1 -3
  116. package/src/sap/fe/core/helpers/FPMHelper.js +1 -1
  117. package/src/sap/fe/core/helpers/KeepAliveHelper.js +211 -0
  118. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +202 -0
  119. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.js +32 -0
  120. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.ts +36 -0
  121. package/src/sap/fe/core/helpers/MassEditHelper.js +678 -0
  122. package/src/sap/fe/core/helpers/ModelHelper.js +64 -1
  123. package/src/sap/fe/core/helpers/PasteHelper.js +7 -1
  124. package/src/sap/fe/core/helpers/SemanticDateOperators.js +1 -1
  125. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +1 -1
  126. package/src/sap/fe/core/helpers/StableIdHelper.js +2 -2
  127. package/src/sap/fe/core/helpers/StableIdHelper.ts +1 -1
  128. package/src/sap/fe/core/library.js +28 -2
  129. package/src/sap/fe/core/library.support.js +10 -4
  130. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
  131. package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
  132. package/src/sap/fe/core/messagebundle.properties +67 -3
  133. package/src/sap/fe/core/messagebundle_ar.properties +40 -3
  134. package/src/sap/fe/core/messagebundle_bg.properties +40 -3
  135. package/src/sap/fe/core/messagebundle_ca.properties +41 -4
  136. package/src/sap/fe/core/messagebundle_cs.properties +41 -4
  137. package/src/sap/fe/core/messagebundle_cy.properties +40 -3
  138. package/src/sap/fe/core/messagebundle_da.properties +40 -3
  139. package/src/sap/fe/core/messagebundle_de.properties +40 -3
  140. package/src/sap/fe/core/messagebundle_el.properties +40 -3
  141. package/src/sap/fe/core/messagebundle_en.properties +37 -0
  142. package/src/sap/fe/core/messagebundle_en_GB.properties +37 -0
  143. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +37 -0
  144. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +46 -2
  145. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +44 -0
  146. package/src/sap/fe/core/messagebundle_es.properties +40 -3
  147. package/src/sap/fe/core/messagebundle_es_MX.properties +41 -4
  148. package/src/sap/fe/core/messagebundle_et.properties +40 -3
  149. package/src/sap/fe/core/messagebundle_fi.properties +40 -3
  150. package/src/sap/fe/core/messagebundle_fr.properties +41 -4
  151. package/src/sap/fe/core/messagebundle_fr_CA.properties +40 -3
  152. package/src/sap/fe/core/messagebundle_hi.properties +40 -3
  153. package/src/sap/fe/core/messagebundle_hr.properties +40 -3
  154. package/src/sap/fe/core/messagebundle_hu.properties +41 -4
  155. package/src/sap/fe/core/messagebundle_id.properties +42 -5
  156. package/src/sap/fe/core/messagebundle_it.properties +40 -3
  157. package/src/sap/fe/core/messagebundle_iw.properties +40 -3
  158. package/src/sap/fe/core/messagebundle_ja.properties +49 -12
  159. package/src/sap/fe/core/messagebundle_kk.properties +40 -3
  160. package/src/sap/fe/core/messagebundle_ko.properties +40 -3
  161. package/src/sap/fe/core/messagebundle_lt.properties +40 -3
  162. package/src/sap/fe/core/messagebundle_lv.properties +40 -3
  163. package/src/sap/fe/core/messagebundle_ms.properties +40 -3
  164. package/src/sap/fe/core/messagebundle_nl.properties +40 -3
  165. package/src/sap/fe/core/messagebundle_no.properties +40 -3
  166. package/src/sap/fe/core/messagebundle_pl.properties +40 -3
  167. package/src/sap/fe/core/messagebundle_pt.properties +42 -5
  168. package/src/sap/fe/core/messagebundle_pt_PT.properties +40 -3
  169. package/src/sap/fe/core/messagebundle_ro.properties +40 -3
  170. package/src/sap/fe/core/messagebundle_ru.properties +40 -3
  171. package/src/sap/fe/core/messagebundle_sh.properties +40 -3
  172. package/src/sap/fe/core/messagebundle_sk.properties +40 -3
  173. package/src/sap/fe/core/messagebundle_sl.properties +40 -3
  174. package/src/sap/fe/core/messagebundle_sv.properties +41 -4
  175. package/src/sap/fe/core/messagebundle_th.properties +40 -3
  176. package/src/sap/fe/core/messagebundle_tr.properties +40 -3
  177. package/src/sap/fe/core/messagebundle_uk.properties +40 -3
  178. package/src/sap/fe/core/messagebundle_vi.properties +40 -3
  179. package/src/sap/fe/core/messagebundle_zh_CN.properties +40 -3
  180. package/src/sap/fe/core/messagebundle_zh_TW.properties +40 -3
  181. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +1 -1
  182. package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +1 -1
  183. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
  184. package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +3 -0
  185. package/src/sap/fe/core/services/NavigationServiceFactory.js +1 -1
  186. package/src/sap/fe/core/services/ResourceModelServiceFactory.js +1 -1
  187. package/src/sap/fe/core/services/RoutingServiceFactory.js +98 -328
  188. package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
  189. package/src/sap/fe/core/services/ShellServicesFactory.ts +30 -1
  190. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +8 -5
  191. package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +11 -6
  192. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +14 -5
  193. package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +1 -1
  194. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
  195. package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
  196. package/src/sap/fe/core/templating/DataModelPathHelper.js +8 -37
  197. package/src/sap/fe/core/templating/DataModelPathHelper.ts +13 -33
  198. package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
  199. package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
  200. package/src/sap/fe/core/templating/EntitySetHelper.js +86 -3
  201. package/src/sap/fe/core/templating/EntitySetHelper.ts +44 -0
  202. package/src/sap/fe/core/templating/FilterHelper.js +10 -7
  203. package/src/sap/fe/core/templating/FilterHelper.ts +8 -6
  204. package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
  205. package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
  206. package/src/sap/fe/core/templating/UIFormatters.js +47 -107
  207. package/src/sap/fe/core/templating/UIFormatters.ts +76 -72
@@ -7,11 +7,11 @@ import {
7
7
  DataFieldForIntentBasedNavigation,
8
8
  DataFieldTypes,
9
9
  DataPoint,
10
+ DataPointTypeTypes,
10
11
  EnumValue,
11
12
  LineItem,
12
13
  PathAnnotationExpression,
13
14
  PresentationVariantTypeTypes,
14
- PropertyAnnotationValue,
15
15
  PropertyPath,
16
16
  SelectionVariantType,
17
17
  SelectOptionType,
@@ -34,7 +34,7 @@ import {
34
34
  ViewPathConfiguration,
35
35
  VisualizationType
36
36
  } from "../../ManifestSettings";
37
- import { EntityType, Property } from "@sap-ux/annotation-converter";
37
+ import { EntityType, Property, TypeDefinition } from "@sap-ux/annotation-converter";
38
38
  import { TableID } from "../../helpers/ID";
39
39
  import {
40
40
  AnnotationAction,
@@ -49,6 +49,7 @@ import {
49
49
  collectRelatedProperties,
50
50
  collectRelatedPropertiesRecursively,
51
51
  ComplexPropertyInfo,
52
+ getDataFieldDataType,
52
53
  getSemanticObjectPath,
53
54
  isDataFieldAlwaysHidden,
54
55
  isDataFieldForActionAbstract,
@@ -67,13 +68,12 @@ import {
67
68
  ExpressionOrPrimitive,
68
69
  formatResult,
69
70
  ifElse,
70
- isBinding,
71
71
  isConstant,
72
72
  not,
73
73
  or,
74
74
  resolveBindingString
75
75
  } from "sap/fe/core/helpers/BindingExpression";
76
- import { Draft, bindingContextPathVisitor, singletonPathVisitor, UI } from "sap/fe/core/converters/helpers/BindingHelper";
76
+ import { Draft, bindingContextPathVisitor, UI } from "sap/fe/core/converters/helpers/BindingHelper";
77
77
  import { KeyHelper } from "sap/fe/core/converters/helpers/Key";
78
78
  import tableFormatters from "sap/fe/core/formatters/TableFormatter";
79
79
  import { MessageType } from "sap/fe/core/formatters/TableFormatterTypes";
@@ -82,12 +82,10 @@ import {
82
82
  getTargetObjectPath,
83
83
  isPathDeletable,
84
84
  isPathSearchable,
85
- isPathInsertable,
86
85
  isPathUpdatable
87
86
  } from "sap/fe/core/templating/DataModelPathHelper";
88
87
  import { replaceSpecialChars } from "sap/fe/core/helpers/StableIdHelper";
89
- import { IssueCategory, IssueSeverity, IssueType } from "sap/fe/core/converters/helpers/IssueManager";
90
- import * as Edm from "@sap-ux/vocabularies-types/dist/Edm";
88
+ import { IssueCategory, IssueSeverity, IssueType, IssueCategoryType } from "sap/fe/core/converters/helpers/IssueManager";
91
89
 
92
90
  import ManifestWrapper from "../../ManifestWrapper";
93
91
  import ConverterContext from "../../ConverterContext";
@@ -98,11 +96,23 @@ import {
98
96
  isPathExpression,
99
97
  getTargetValueOnDataPoint
100
98
  } from "sap/fe/core/templating/PropertyHelper";
101
-
102
99
  import { AggregationHelper } from "../../helpers/Aggregation";
103
- import { DisplayMode, getDisplayMode } from "sap/fe/core/templating/UIFormatters";
100
+ import { DisplayMode, EDM_TYPE_MAPPING, getDisplayMode } from "sap/fe/core/templating/DisplayModeFormatter";
104
101
  import { getMessageTypeFromCriticalityType } from "./Criticality";
105
102
  import { FilterFunctions } from "@sap-ux/vocabularies-types/dist/generated/Capabilities";
103
+ import { getNonSortablePropertiesRestrictions } from "sap/fe/core/templating/EntitySetHelper";
104
+ import {
105
+ generateStandardActionsContext,
106
+ isExternalCreateConfigured,
107
+ StandardActionConfigType,
108
+ getDeleteVisibility,
109
+ getStandardActionCreate,
110
+ getStandardActionDelete,
111
+ getStandardActionPaste,
112
+ getStandardActionMassEdit,
113
+ isDraftOrStickySupported,
114
+ getInsertUpdateActionsTemplating
115
+ } from "./table/StandardActions";
106
116
 
107
117
  export type TableAnnotationConfiguration = {
108
118
  autoBindOnInit: boolean;
@@ -119,11 +129,9 @@ export type TableAnnotationConfiguration = {
119
129
  rowNavigated: BindingExpression<boolean>;
120
130
  };
121
131
  selectionMode: string | undefined;
122
- show?: {
123
- create?: string | boolean;
124
- delete?: string | boolean;
125
- paste?: BindingExpression<boolean>;
126
- massEdit?: { visible: boolean | string; enabled: boolean | string };
132
+ standardActions: {
133
+ actions: Record<string, StandardActionConfigType>;
134
+ isInsertUpdateTemplated: boolean;
127
135
  };
128
136
  displayMode?: boolean;
129
137
  threshold: number;
@@ -134,7 +142,6 @@ export type TableAnnotationConfiguration = {
134
142
 
135
143
  /** Create new entries */
136
144
  create: CreateBehaviour | CreateBehaviourExternal;
137
- parentEntityDeleteEnabled?: BindingExpression<boolean>;
138
145
  title: string;
139
146
  searchable: boolean;
140
147
  };
@@ -196,6 +203,7 @@ export type TableControlConfiguration = {
196
203
  enableFullScreen: boolean;
197
204
  showRowCount: boolean;
198
205
  enableMassEdit: boolean | undefined;
206
+ enableAutoColumnWidth: boolean;
199
207
  };
200
208
 
201
209
  export type TableType = "GridTable" | "ResponsiveTable" | "AnalyticalTable";
@@ -231,9 +239,12 @@ export type AnnotationTableColumn = BaseTableColumn & {
231
239
  annotationPath: string;
232
240
  relativePath: string;
233
241
  label?: string;
242
+ tooltip?: string;
234
243
  groupLabel?: string;
235
244
  group?: string;
236
245
  isGroupable?: boolean;
246
+ FieldGroupHiddenExpressions?: BindingExpression<string>;
247
+ showDataFieldsLabel?: boolean;
237
248
  isKey?: boolean;
238
249
  unit?: string;
239
250
  exportSettings?: {
@@ -241,6 +252,13 @@ export type AnnotationTableColumn = BaseTableColumn & {
241
252
  label?: string;
242
253
  fieldLabel?: string;
243
254
  wrap?: boolean;
255
+ type?: string;
256
+ inputFormat?: string;
257
+ format?: string;
258
+ scale?: number;
259
+ delimiter?: boolean;
260
+ trueValue?: boolean;
261
+ falseValue?: boolean;
244
262
  };
245
263
  isDataPointFakeTargetProperty?: boolean;
246
264
  textArrangement?: {
@@ -249,6 +267,23 @@ export type AnnotationTableColumn = BaseTableColumn & {
249
267
  };
250
268
  exportContactProperty?: string;
251
269
  additionalPropertyInfos?: string[];
270
+ visualSettings?: VisualSettings;
271
+ typeConfig?: object;
272
+ };
273
+
274
+ export type VisualSettings = {
275
+ widthCalculation?: WidthCalculation;
276
+ };
277
+
278
+ export type WidthCalculation = null | {
279
+ minWidth?: number;
280
+ maxWidth?: number;
281
+ defaultWidth?: number;
282
+ includeLabel?: boolean;
283
+ gap?: number;
284
+ // only relevant for complex types
285
+ excludeProperties?: string | string[];
286
+ verticalArrangement?: boolean;
252
287
  };
253
288
 
254
289
  export type TableColumn = CustomTableColumn | AnnotationTableColumn;
@@ -270,6 +305,7 @@ export type TableVisualization = {
270
305
  actions: BaseAction[];
271
306
  aggregates?: Record<string, AggregateData>;
272
307
  enableAnalytics?: boolean;
308
+ enableAnalyticsSearch?: boolean;
273
309
  enableDataStateFilter: boolean;
274
310
  operationAvailableMap: string;
275
311
  operationAvailableProperties: string;
@@ -462,6 +498,10 @@ function updateTableVisualizationForAnalytics(
462
498
  tableVisualization.enableAnalytics = true;
463
499
  tableVisualization.aggregates = aggregatesDefinitions;
464
500
 
501
+ const aggregationHelper = new AggregationHelper(entityType, converterContext);
502
+ const allowedTransformations = aggregationHelper.getAllowedTransformations();
503
+ tableVisualization.enableAnalyticsSearch = allowedTransformations ? allowedTransformations.indexOf("search") >= 0 : true;
504
+
465
505
  // Add group and sort conditions from the presentation variant
466
506
  tableVisualization.annotation.groupConditions = getGroupConditions(presentationVariantAnnotation, tableVisualization.columns);
467
507
  tableVisualization.annotation.aggregateConditions = getAggregateConditions(
@@ -881,7 +921,8 @@ export function getSelectionMode(
881
921
  visualizationPath: string,
882
922
  converterContext: ConverterContext,
883
923
  isEntitySet: boolean,
884
- targetCapabilities: TableCapabilityRestriction
924
+ targetCapabilities: TableCapabilityRestriction,
925
+ isDeleteButtonVisible?: Expression<boolean>
885
926
  ): string | undefined {
886
927
  if (!lineItemAnnotation) {
887
928
  return SelectionMode.None;
@@ -902,25 +943,10 @@ export function getSelectionMode(
902
943
  isParentDeletable = isPathDeletable(converterContext.getDataModelObjectPath(), undefined);
903
944
  parentEntitySetDeletable = isParentDeletable ? compileBinding(isParentDeletable, true) : isParentDeletable;
904
945
  }
905
- if (selectionMode && selectionMode === SelectionMode.None) {
906
- if (!isEntitySet) {
907
- if (targetCapabilities.isDeletable || parentEntitySetDeletable !== "false") {
908
- selectionMode = SelectionMode.Multi;
909
- return compileBinding(
910
- ifElse(equal(bindingExpression("/editMode", "ui"), "Editable"), constant(selectionMode), constant("None"))
911
- );
912
- } else {
913
- selectionMode = SelectionMode.None;
914
- }
915
- } else if (isEntitySet) {
916
- if (targetCapabilities.isDeletable) {
917
- selectionMode = SelectionMode.Multi;
918
- return selectionMode;
919
- } else {
920
- selectionMode = SelectionMode.None;
921
- }
922
- }
923
- } else if (!selectionMode || selectionMode === SelectionMode.Auto) {
946
+ if (selectionMode && selectionMode === SelectionMode.None && isDeleteButtonVisible) {
947
+ return compileBinding(ifElse(isDeleteButtonVisible, constant("Multi"), constant("None")));
948
+ }
949
+ if (!selectionMode || selectionMode === SelectionMode.Auto) {
924
950
  selectionMode = SelectionMode.Multi;
925
951
  }
926
952
 
@@ -939,18 +965,22 @@ export function getSelectionMode(
939
965
  aVisibleBindingExpressions = getVisibleExpForCustomActionsRequiringContext(manifestActions);
940
966
 
941
967
  // No action requiring a context:
942
- if (aHiddenBindingExpressions.length === 0 && aVisibleBindingExpressions.length === 0) {
968
+ if (aHiddenBindingExpressions.length === 0 && aVisibleBindingExpressions.length === 0 && isDeleteButtonVisible) {
943
969
  if (!isEntitySet) {
944
970
  if (targetCapabilities.isDeletable || parentEntitySetDeletable !== "false") {
945
971
  return compileBinding(
946
- ifElse(equal(bindingExpression("/editMode", "ui"), "Editable"), constant(selectionMode), constant(SelectionMode.None))
972
+ ifElse(
973
+ and(equal(bindingExpression("/editMode", "ui"), "Editable"), isDeleteButtonVisible),
974
+ constant(selectionMode),
975
+ constant(SelectionMode.None)
976
+ )
947
977
  );
948
978
  } else {
949
979
  return SelectionMode.None;
950
980
  }
951
981
  // EntitySet deletable:
952
- } else if (targetCapabilities.isDeletable) {
953
- return selectionMode;
982
+ } else if (targetCapabilities.isDeletable && isDeleteButtonVisible) {
983
+ return compileBinding(ifElse(isDeleteButtonVisible, constant(selectionMode), constant("None")));
954
984
  // EntitySet not deletable:
955
985
  } else {
956
986
  return SelectionMode.None;
@@ -1111,10 +1141,10 @@ function _getCreationBehaviour(
1111
1141
  const navigation = navigationSettings?.create || navigationSettings?.detail;
1112
1142
 
1113
1143
  // cross-app
1114
- if (navigation?.outbound && navigation.outboundDetail && navigationSettings?.create) {
1144
+ if (isExternalCreateConfigured(navigationSettings) && navigation) {
1115
1145
  return {
1116
1146
  mode: "External",
1117
- outbound: navigation.outbound,
1147
+ outbound: navigation.outbound as string,
1118
1148
  outboundDetail: navigation.outboundDetail,
1119
1149
  navigationSettings: navigationSettings
1120
1150
  };
@@ -1320,12 +1350,31 @@ const getColumnDefinitionFromProperty = function(
1320
1350
  const groupPath: string | undefined = property.name ? _sliceAtSlash(property.name, true, false) : undefined;
1321
1351
  const isGroup: boolean = groupPath != property.name;
1322
1352
  const isDataPointFakeProperty: boolean = name.indexOf("@com.sap.vocabularies.UI.v1.DataPoint") > -1;
1353
+ const exportType: string = _getExportDataType(property.type);
1354
+ const sDateInputFormat: string | undefined = property.type === "Edm.Date" ? "YYYY-MM-DD" : undefined;
1355
+ const dataType: string | undefined = getDataFieldDataType(property);
1356
+ const propertyTypeConfig = !isDataPointFakeProperty ? getTypeConfig(property, dataType) : undefined;
1357
+ const oTypeConfig = !isDataPointFakeProperty
1358
+ ? {
1359
+ className: property.type || dataType,
1360
+ oFormatOptions: propertyTypeConfig.formatOptions,
1361
+ oConstraints: propertyTypeConfig.constraints
1362
+ }
1363
+ : undefined;
1323
1364
  const exportSettings = isDataPointFakeProperty
1324
1365
  ? {
1325
1366
  template: getTargetValueOnDataPoint(property)
1326
1367
  }
1327
- : undefined;
1328
- return {
1368
+ : {
1369
+ type: exportType,
1370
+ inputFormat: sDateInputFormat,
1371
+ scale: property.scale,
1372
+ delimiter: property.type === "Edm.Int64" ? true : false,
1373
+ trueValue: property.type === "Edm.Boolean" ? "Yes" : undefined,
1374
+ falseValue: property.type === "Edm.Boolean" ? "No" : undefined
1375
+ };
1376
+
1377
+ const oColumn: any = {
1329
1378
  key: key,
1330
1379
  isGroupable: !isDataPointFakeProperty && !isHidden ? aggregationHelper.isPropertyGroupable(property) : false,
1331
1380
  type: ColumnType.Annotation,
@@ -1345,8 +1394,16 @@ const getColumnDefinitionFromProperty = function(
1345
1394
  isKey: property.isKey,
1346
1395
  isDataPointFakeTargetProperty: isDataPointFakeProperty,
1347
1396
  exportSettings: exportSettings,
1348
- caseSensitive: isFilteringCaseSensitive(converterContext)
1349
- } as AnnotationTableColumn;
1397
+ caseSensitive: isFilteringCaseSensitive(converterContext),
1398
+ typeConfig: oTypeConfig,
1399
+ visualSettings: isDataPointFakeProperty ? { widthCalculation: null } : undefined
1400
+ };
1401
+ const sTooltip = _getTooltip(property);
1402
+ if (sTooltip) {
1403
+ oColumn.tooltip = sTooltip;
1404
+ }
1405
+
1406
+ return oColumn as AnnotationTableColumn;
1350
1407
  };
1351
1408
 
1352
1409
  /**
@@ -1376,8 +1433,91 @@ const _isValidColumn = function(dataField: DataFieldAbstractTypes) {
1376
1433
  };
1377
1434
 
1378
1435
  /**
1379
- * Returns label for property and dataField.
1380
- * @param {DataFieldAbstractTypes | Property} property Entity type property or DataField defined in the annotations
1436
+ * Returns the binding expression to evaluate the visibility of a DataField or DataPoint annotation.
1437
+ *
1438
+ * SAP Fiori elements will evaluate either the UI.Hidden annotation defined on the annotation itself or on the target property.
1439
+ *
1440
+ * @param {DataModelObjectPath} dataFieldModelPath The metapath referring to the annotation that is evaluated by SAP Fiori elements.
1441
+ * @param {FieldFormatOptions} [formatOptions] FormatOptions is optional, used to check if the analytic table has GroupHeader expanded.
1442
+ * @param {boolean} [returnExpression] ReturnExpression optional.
1443
+ * @returns {BindingExpression<string>} An expression that you can bind to the UI.
1444
+ */
1445
+ export const _getVisibleExpression = function(
1446
+ dataFieldModelPath: DataModelObjectPath,
1447
+ formatOptions?: any,
1448
+ returnExpression?: Boolean
1449
+ ): BindingExpression<string> {
1450
+ const targetObject: DataFieldAbstractTypes | DataPointTypeTypes = dataFieldModelPath.targetObject;
1451
+ let propertyValue;
1452
+ if (targetObject) {
1453
+ switch (targetObject.$Type) {
1454
+ case UIAnnotationTypes.DataField:
1455
+ case UIAnnotationTypes.DataFieldWithUrl:
1456
+ case UIAnnotationTypes.DataFieldWithNavigationPath:
1457
+ case UIAnnotationTypes.DataFieldWithIntentBasedNavigation:
1458
+ case UIAnnotationTypes.DataFieldWithAction:
1459
+ case UIAnnotationTypes.DataPointType:
1460
+ propertyValue = targetObject.Value.$target;
1461
+ break;
1462
+ case UIAnnotationTypes.DataFieldForAnnotation:
1463
+ // if it is a DataFieldForAnnotation pointing to a DataPoint we look at the dataPoint's value
1464
+ if (targetObject?.Target?.$target?.$Type === UIAnnotationTypes.DataPointType) {
1465
+ propertyValue = targetObject.Target.$target?.Value.$target;
1466
+ }
1467
+ break;
1468
+ case UIAnnotationTypes.DataFieldForIntentBasedNavigation:
1469
+ case UIAnnotationTypes.DataFieldForAction:
1470
+ default:
1471
+ propertyValue = undefined;
1472
+ }
1473
+ }
1474
+ const isAnalyticalGroupHeaderExpanded = formatOptions?.isAnalytics ? UI.IsExpanded : constant(false);
1475
+ const isAnalyticalLeaf = formatOptions?.isAnalytics ? equal(UI.NodeLevel, 0) : constant(false);
1476
+
1477
+ // A data field is visible if:
1478
+ // - the UI.Hidden expression in the original annotation does not evaluate to 'true'
1479
+ // - the UI.Hidden expression in the target property does not evaluate to 'true'
1480
+ // - in case of Analytics it's not visible for an expanded GroupHeader
1481
+ const expression = and(
1482
+ ...[
1483
+ not(equal(annotationExpression(targetObject?.annotations?.UI?.Hidden), true)),
1484
+ ifElse(!!propertyValue, propertyValue && not(equal(annotationExpression(propertyValue.annotations?.UI?.Hidden), true)), true),
1485
+ or(not(isAnalyticalGroupHeaderExpanded), isAnalyticalLeaf)
1486
+ ]
1487
+ );
1488
+ return returnExpression ? (expression as BindingExpression<string>) : compileBinding(expression);
1489
+ };
1490
+
1491
+ /**
1492
+ * Returns hidden binding expressions for a field group.
1493
+ * @param {DataFieldAbstractTypes} dataFieldGroup DataField defined in the annotations
1494
+ * @param {FieldFormatOptions} [fieldFormatOptions] FormatOptions is optional, used to check if the analytic table has GroupHeader expanded.
1495
+ * @returns {BindingExpression<string>} Compile binding of field group expressions.
1496
+ * @private
1497
+ */
1498
+ const _getFieldGroupHiddenExpressions = function(
1499
+ dataFieldGroup: DataFieldAbstractTypes,
1500
+ fieldFormatOptions: any
1501
+ ): BindingExpression<string> {
1502
+ const aFieldGroupHiddenExpressions: BindingExpression<string>[] = [];
1503
+ if (
1504
+ dataFieldGroup.$Type === UIAnnotationTypes.DataFieldForAnnotation &&
1505
+ dataFieldGroup.Target?.$target?.$Type === UIAnnotationTypes.FieldGroupType
1506
+ ) {
1507
+ dataFieldGroup.Target.$target.Data?.forEach((innerDataField: DataFieldAbstractTypes | DataPointTypeTypes) => {
1508
+ aFieldGroupHiddenExpressions.push(
1509
+ _getVisibleExpression({ targetObject: innerDataField } as DataModelObjectPath, fieldFormatOptions, true)
1510
+ );
1511
+ });
1512
+ return compileBinding(
1513
+ ifElse(or(...(aFieldGroupHiddenExpressions as ExpressionOrPrimitive<boolean>[])), constant(true), constant(false))
1514
+ );
1515
+ }
1516
+ };
1517
+
1518
+ /**
1519
+ * Returns the label for the property and dataField.
1520
+ * @param {DataFieldAbstractTypes | Property} [property] Property or DataField defined in the annotations
1381
1521
  * @param isGroup
1382
1522
  * @returns {string} Label of the property or DataField
1383
1523
  * @private
@@ -1412,6 +1552,29 @@ const _getLabel = function(property: DataFieldAbstractTypes | Property, isGroup:
1412
1552
  }
1413
1553
  };
1414
1554
 
1555
+ const _getTooltip = function(source: DataFieldAbstractTypes | Property): string | undefined {
1556
+ if (!source) {
1557
+ return undefined;
1558
+ }
1559
+
1560
+ if (isProperty(source)) {
1561
+ return source.annotations.Common?.QuickInfo
1562
+ ? compileBinding(annotationExpression(source.annotations.Common.QuickInfo.valueOf()))
1563
+ : undefined;
1564
+ } else if (isDataFieldTypes(source)) {
1565
+ return source.Value?.$target?.annotations?.Common?.QuickInfo
1566
+ ? compileBinding(annotationExpression(source.Value.$target.annotations.Common.QuickInfo.valueOf()))
1567
+ : undefined;
1568
+ } else if (source.$Type === UIAnnotationTypes.DataFieldForAnnotation) {
1569
+ const datapointTarget = source.Target?.$target as DataPoint;
1570
+ return datapointTarget?.Value?.$target?.annotations?.Common?.QuickInfo
1571
+ ? compileBinding(annotationExpression(datapointTarget.Value.$target.annotations.Common.QuickInfo.valueOf()))
1572
+ : undefined;
1573
+ } else {
1574
+ return undefined;
1575
+ }
1576
+ };
1577
+
1415
1578
  /**
1416
1579
  * Creates a PropertyInfo for each identified property consumed by a LineItem.
1417
1580
  *
@@ -1517,6 +1680,25 @@ const _getAnnotationColumnName = function(dataField: DataFieldAbstractTypes) {
1517
1680
  }
1518
1681
  };
1519
1682
 
1683
+ /**
1684
+ * Determines if the data field labels have to be displayed in the table.
1685
+ * @param {string} fieldGroupName The `DataField` name being processed.
1686
+ * @param {string} visualizationPath
1687
+ * @param {ConverterContext} converterContext
1688
+ * @returns {boolean} `showDataFieldsLabel` value from the manifest
1689
+ * @private
1690
+ */
1691
+ const _getShowDataFieldsLabel = function(fieldGroupName: string, visualizationPath: string, converterContext: ConverterContext): boolean {
1692
+ const oColumns = converterContext.getManifestControlConfiguration(visualizationPath)?.columns;
1693
+ const aColumnKeys = oColumns && Object.keys(oColumns);
1694
+ return (
1695
+ aColumnKeys &&
1696
+ !!aColumnKeys.find(function(key: string) {
1697
+ return key === fieldGroupName && oColumns[key].showDataFieldsLabel;
1698
+ })
1699
+ );
1700
+ };
1701
+
1520
1702
  /**
1521
1703
  * Determines the relative path of the property with respect to the root entity.
1522
1704
  * @param dataField The `DataField` being processed.
@@ -1650,16 +1832,13 @@ const getColumnsFromAnnotations = function(
1650
1832
  const entityType = converterContext.getAnnotationEntityType(lineItemAnnotation),
1651
1833
  annotationColumns: AnnotationTableColumn[] = [],
1652
1834
  columnsToBeCreated: Record<string, Property> = {},
1653
- nonSortableColumns: string[] =
1654
- (converterContext.getEntitySet()?.annotations?.Capabilities?.SortRestrictions
1655
- ?.NonSortableProperties as Edm.PropertyPath[])?.map((property: PropertyPath) => property.value) ?? [],
1835
+ nonSortableColumns: string[] = getNonSortablePropertiesRestrictions(converterContext.getEntitySet()),
1656
1836
  tableManifestSettings: TableManifestConfiguration = converterContext.getManifestControlConfiguration(visualizationPath),
1657
1837
  tableType: TableType = tableManifestSettings?.tableSettings?.type || "ResponsiveTable";
1658
1838
  const semanticKeys = converterContext.getAnnotationsByTerm("Common", "com.sap.vocabularies.Common.v1.SemanticKey", [
1659
1839
  converterContext.getEntityType()
1660
1840
  ])[0];
1661
1841
  if (lineItemAnnotation) {
1662
- // Get columns from the LineItem Annotation
1663
1842
  lineItemAnnotation.forEach(lineItem => {
1664
1843
  if (!_isValidColumn(lineItem)) {
1665
1844
  return;
@@ -1677,33 +1856,98 @@ const getColumnsFromAnnotations = function(
1677
1856
  const isGroup: boolean = groupPath != relativePath;
1678
1857
  const sLabel: string | undefined = _getLabel(lineItem, isGroup);
1679
1858
  const name = _getAnnotationColumnName(lineItem);
1680
- annotationColumns.push({
1859
+ const isFieldGroupColumn: boolean = groupPath.indexOf("@com.sap.vocabularies.UI.v1.FieldGroup") > -1;
1860
+ const showDataFieldsLabel: boolean = isFieldGroupColumn
1861
+ ? _getShowDataFieldsLabel(name, visualizationPath, converterContext)
1862
+ : false;
1863
+ const dataType: string | undefined = getDataFieldDataType(lineItem);
1864
+ const sDateInputFormat: string | undefined = dataType === "Edm.Date" ? "YYYY-MM-DD" : undefined;
1865
+ const formatOptions = {
1866
+ ...getDefaultFormatOptionsForTable(),
1867
+ ...getDefaultDraftIndicatorForColumn(name, semanticKeys)
1868
+ };
1869
+ let fieldGroupHiddenExpressions: BindingExpression<string>;
1870
+ if (
1871
+ lineItem.$Type === UIAnnotationTypes.DataFieldForAnnotation &&
1872
+ lineItem.Target?.$target?.$Type === UIAnnotationTypes.FieldGroupType
1873
+ ) {
1874
+ fieldGroupHiddenExpressions = _getFieldGroupHiddenExpressions(lineItem, formatOptions);
1875
+ }
1876
+ const exportSettings = {
1877
+ template: relatedPropertiesInfo.exportSettingsTemplate,
1878
+ wrap: relatedPropertiesInfo.exportSettingsWrapping,
1879
+ type: dataType ? _getExportDataType(dataType, relatedPropertyNames.length > 1) : undefined,
1880
+ inputFormat: sDateInputFormat,
1881
+ delimiter: dataType === "Edm.Int64" ? true : false,
1882
+ trueValue: dataType === "Edm.Boolean" ? "Yes" : undefined,
1883
+ falseValue: dataType === "Edm.Boolean" ? "No" : undefined
1884
+ };
1885
+ const propertyTypeConfig = dataType && getTypeConfig(lineItem, dataType);
1886
+ const oTypeConfig = propertyTypeConfig
1887
+ ? {
1888
+ className: dataType,
1889
+ oFormatOptions: {
1890
+ ...formatOptions,
1891
+ ...propertyTypeConfig.formatOptions
1892
+ },
1893
+ oConstraints: propertyTypeConfig.constraints
1894
+ }
1895
+ : undefined;
1896
+ let visualSettings: VisualSettings = {};
1897
+ if (relatedPropertiesInfo.visualSettingsToBeExcluded) {
1898
+ // In case of text arrangement annotation with display mode as text only, exclude text property from the width calculation
1899
+ visualSettings = {
1900
+ widthCalculation: {
1901
+ excludeProperties: "Property::" + relatedPropertiesInfo.visualSettingsToBeExcluded
1902
+ }
1903
+ };
1904
+ } else if (!dataType || !oTypeConfig) {
1905
+ // for charts
1906
+ visualSettings.widthCalculation = null;
1907
+ }
1908
+
1909
+ // TODO: For situation POC - increase width of the column with the situations indicator - works for the situations demo app only!
1910
+ // Might be a good idea to move the complete column width determination to the converter, that would allow us to widen the columns as needed. This workaround only deals with Date columns.
1911
+ const { hasDraftIndicator } = getDefaultDraftIndicatorForColumn(name, semanticKeys);
1912
+ const widthOverride =
1913
+ (converterContext.getEntityType().annotations as any).FE?.Situations &&
1914
+ hasDraftIndicator &&
1915
+ lineItem.$Type === UIAnnotationTypes.DataField &&
1916
+ lineItem.Value.$target.type === "Edm.Date"
1917
+ ? "11em"
1918
+ : undefined;
1919
+
1920
+ const oColumn: any = {
1681
1921
  key: KeyHelper.generateKeyFromDataField(lineItem),
1682
1922
  type: ColumnType.Annotation,
1683
1923
  label: sLabel,
1684
1924
  groupLabel: isGroup ? _getLabel(lineItem) : null,
1685
1925
  group: isGroup ? groupPath : null,
1926
+ FieldGroupHiddenExpressions: fieldGroupHiddenExpressions,
1686
1927
  annotationPath: converterContext.getEntitySetBasedAnnotationPath(lineItem.fullyQualifiedName),
1687
1928
  semanticObjectPath: semanticObjectAnnotationPath,
1688
1929
  availability: isDataFieldAlwaysHidden(lineItem) ? AvailabilityType.Hidden : AvailabilityType.Default,
1689
1930
  name: name,
1931
+ showDataFieldsLabel: showDataFieldsLabel,
1690
1932
  relativePath: relativePath,
1691
1933
  sortable: _isColumnSortable(lineItem, relativePath, nonSortableColumns),
1692
1934
  propertyInfos: relatedPropertyNames.length > 0 ? relatedPropertyNames : undefined,
1693
1935
  additionalPropertyInfos: additionalPropertyNames.length > 0 ? additionalPropertyNames : undefined,
1694
- exportSettings: {
1695
- template: relatedPropertiesInfo.exportSettingsTemplate,
1696
- wrap: relatedPropertiesInfo.exportSettingsWrapping
1697
- },
1698
- width: lineItem.annotations?.HTML5?.CssDefaults?.width || undefined,
1936
+ exportSettings: exportSettings,
1937
+ width: lineItem.annotations?.HTML5?.CssDefaults?.width || widthOverride || undefined,
1699
1938
  isNavigable: true,
1700
- formatOptions: {
1701
- ...getDefaultFormatOptionsForTable(),
1702
- ...getDefaultDraftIndicatorForColumn(name, semanticKeys)
1703
- },
1939
+ formatOptions: formatOptions,
1704
1940
  exportContactProperty: relatedPropertiesInfo.exportSettingsContactProperty,
1705
- caseSensitive: isFilteringCaseSensitive(converterContext)
1706
- } as AnnotationTableColumn);
1941
+ caseSensitive: isFilteringCaseSensitive(converterContext),
1942
+ typeConfig: oTypeConfig,
1943
+ visualSettings: visualSettings
1944
+ };
1945
+ const sTooltip = _getTooltip(lineItem);
1946
+ if (sTooltip) {
1947
+ oColumn.tooltip = sTooltip;
1948
+ }
1949
+
1950
+ annotationColumns.push(oColumn as AnnotationTableColumn);
1707
1951
 
1708
1952
  // Collect information of related columns to be created.
1709
1953
  relatedPropertyNames.forEach(name => {
@@ -1834,36 +2078,48 @@ const getColumnsFromManifest = function(
1834
2078
  converterContext,
1835
2079
  entityType
1836
2080
  );
1837
-
1838
- internalColumns[key] = {
1839
- key: key,
1840
- id: "CustomColumn::" + key,
1841
- name: "CustomColumn::" + key,
1842
- header: manifestColumn.header,
1843
- width: manifestColumn.width || undefined,
1844
- horizontalAlign: _getManifestOrDefaultValue(manifestColumn?.horizontalAlign, HorizontalAlign.Begin, isAnnotationColumn),
1845
- type: manifestColumn.type === "Slot" ? ColumnType.Slot : ColumnType.Default,
1846
- availability: _getManifestOrDefaultValue(manifestColumn?.availability, AvailabilityType.Default, isAnnotationColumn),
1847
- template: manifestColumn.template || "undefined",
1848
- position: {
1849
- anchor: manifestColumn.position?.anchor,
1850
- placement: manifestColumn.position === undefined ? Placement.After : manifestColumn.position.placement
1851
- },
1852
- isNavigable: isAnnotationColumn ? undefined : isActionNavigable(manifestColumn, navigationSettings, true),
1853
- settings: manifestColumn.settings,
1854
- sortable: false,
1855
- propertyInfos: propertyInfos,
1856
- formatOptions: {
1857
- ...getDefaultFormatOptionsForTable(),
1858
- ...manifestColumn.formatOptions
1859
- },
1860
- exportSettings: {
1861
- template: propertyInfos ? _appendCustomTemplate(propertyInfos) : undefined,
1862
- fieldLabel: propertyInfos ? manifestColumn.header : undefined,
1863
- wrap: propertyInfos && propertyInfos.length > 1 ? true : false
1864
- },
1865
- caseSensitive: isFilteringCaseSensitive(converterContext)
1866
- };
2081
+ if (!manifestColumn?.template && !isAnnotationColumn) {
2082
+ const Message = "The annotation column '" + key + "' referenced in the manifest is not found";
2083
+ converterContext
2084
+ .getDiagnostics()
2085
+ .addIssue(
2086
+ IssueCategory.Manifest,
2087
+ IssueSeverity.Low,
2088
+ Message,
2089
+ IssueCategoryType,
2090
+ IssueCategoryType?.AnnotationColumns?.InvalidKey
2091
+ );
2092
+ } else {
2093
+ internalColumns[key] = {
2094
+ key: key,
2095
+ id: "CustomColumn::" + key,
2096
+ name: "CustomColumn::" + key,
2097
+ header: manifestColumn.header,
2098
+ width: manifestColumn.width || undefined,
2099
+ horizontalAlign: _getManifestOrDefaultValue(manifestColumn?.horizontalAlign, HorizontalAlign.Begin, isAnnotationColumn),
2100
+ type: manifestColumn.type === "Slot" ? ColumnType.Slot : ColumnType.Default,
2101
+ availability: _getManifestOrDefaultValue(manifestColumn?.availability, AvailabilityType.Default, isAnnotationColumn),
2102
+ template: manifestColumn.template || "undefined",
2103
+ position: {
2104
+ anchor: manifestColumn.position?.anchor,
2105
+ placement: manifestColumn.position === undefined ? Placement.After : manifestColumn.position.placement
2106
+ },
2107
+ isNavigable: isAnnotationColumn ? undefined : isActionNavigable(manifestColumn, navigationSettings, true),
2108
+ settings: manifestColumn.settings,
2109
+ sortable: false,
2110
+ propertyInfos: propertyInfos,
2111
+ formatOptions: {
2112
+ ...getDefaultFormatOptionsForTable(),
2113
+ ...manifestColumn.formatOptions
2114
+ },
2115
+ exportSettings: {
2116
+ template: propertyInfos ? _appendCustomTemplate(propertyInfos) : undefined,
2117
+ fieldLabel: propertyInfos ? manifestColumn.header : undefined,
2118
+ wrap: propertyInfos && propertyInfos.length > 1 ? true : false
2119
+ },
2120
+ caseSensitive: isFilteringCaseSensitive(converterContext)
2121
+ };
2122
+ }
1867
2123
  }
1868
2124
  return internalColumns;
1869
2125
  };
@@ -1922,249 +2178,20 @@ export function getP13nMode(
1922
2178
  }
1923
2179
 
1924
2180
  /**
1925
- * Function to determine the visibility of the Delete button.
1926
- *
1927
- * @param converterContext The instance of the converter context
1928
- * @param navigationPath Path to the navigation entity
1929
- * @param isTargetDeletable Flag which determines whether a target is deletable
1930
- * @param viewConfiguration The instance of the configuration for the view path
1931
- * @returns {BindingExpression<boolean>} The binding expression for the Delete button
1932
- */
1933
- export function getDeleteVisible(
1934
- converterContext: ConverterContext,
1935
- navigationPath: string,
1936
- isTargetDeletable: boolean,
1937
- viewConfiguration?: ViewPathConfiguration
1938
- ): BindingExpression<boolean> {
1939
- const currentEntitySet = converterContext.getEntitySet();
1940
- const dataModelObjectPath = converterContext.getDataModelObjectPath();
1941
- const visitedNavigationPaths = dataModelObjectPath.navigationProperties.map(navProp => navProp.name);
1942
- const isDeleteHiddenExpression = currentEntitySet
1943
- ? annotationExpression(
1944
- (currentEntitySet?.annotations.UI?.DeleteHidden as PropertyAnnotationValue<boolean>) || false,
1945
- visitedNavigationPaths,
1946
- undefined,
1947
- (path: string) => singletonPathVisitor(path, converterContext, visitedNavigationPaths)
1948
- )
1949
- : constant(false);
1950
- const isDeleteHidden: any = compileBinding(isDeleteHiddenExpression);
1951
- let isParentDeletable, parentEntitySetDeletable;
1952
- if (converterContext.getTemplateType() === TemplateType.ObjectPage) {
1953
- isParentDeletable = isPathDeletable(converterContext.getDataModelObjectPath(), navigationPath);
1954
- parentEntitySetDeletable = isParentDeletable ? compileBinding(isParentDeletable) : isParentDeletable;
1955
- }
1956
- //do not show case the delete button if parentEntitySetDeletable is false
1957
- if (parentEntitySetDeletable === "false") {
1958
- return false;
1959
- } else if (parentEntitySetDeletable && isDeleteHidden !== "true") {
1960
- //Delete Hidden in case of true and path based
1961
- if (isDeleteHidden && isDeleteHidden !== "false") {
1962
- return "{= !$" + isDeleteHidden + " && ${ui>/editMode} === 'Editable'}";
1963
- } else {
1964
- return "{= ${ui>/editMode} === 'Editable'}";
1965
- }
1966
- } else if (
1967
- isDeleteHidden === "true" ||
1968
- !isTargetDeletable ||
1969
- (viewConfiguration && converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration)) ||
1970
- converterContext.getTemplateType() === TemplateType.AnalyticalListPage
1971
- ) {
1972
- return false;
1973
- } else if (converterContext.getTemplateType() !== TemplateType.ListReport) {
1974
- if (isDeleteHidden && isDeleteHidden === "false") {
1975
- return "{= !$" + isDeleteHidden + " && ${ui>/editMode} === 'Editable'}";
1976
- } else {
1977
- return "{= ${ui>/editMode} === 'Editable'}";
1978
- }
1979
- } else if (isBinding(isDeleteHiddenExpression)) {
1980
- // UI.DeleteHidden annotation points to a path
1981
- return compileBinding(not(isDeleteHiddenExpression));
1982
- } else {
1983
- return true;
1984
- }
1985
- }
1986
-
1987
- /**
1988
- * Returns the enablement for the 'Mass Edit' button
1989
- *
1990
- * @param converterContext The converterContext
1991
- * @param bMassEditVisible The visibility of the 'Mass Edit' button
1992
- * @returns {*} Expression or Boolean value for the enablement of the 'Mass Edit' button
1993
- */
1994
-
1995
- export function getEnablementMassEdit(
1996
- converterContext: ConverterContext,
1997
- bMassEditVisible: string | boolean | undefined
1998
- ): string | boolean {
1999
- if (bMassEditVisible) {
2000
- const isParentUpdatable: any = isPathUpdatable(converterContext.getDataModelObjectPath(), undefined, true);
2001
- //when updatable is path based and pointing to current entity set property, that case is handled in table helper and runtime
2002
- if (isParentUpdatable?.currentEntityRestriction) {
2003
- return false;
2004
- }
2005
- const oExpression: any = compileBinding(isParentUpdatable);
2006
- return isParentUpdatable
2007
- ? "{= %{internal>numberOfSelectedContexts} >= 2 && " + compileBinding(isParentUpdatable, oExpression) + "}"
2008
- : false;
2009
- }
2010
- return false;
2011
- }
2012
-
2013
- /**
2014
- * Returns the visibility for the 'Mass Edit' button
2015
- *
2016
- * @param converterContext The converterContext
2017
- * @param tableManifestConfiguration The manifest configuration for the table
2018
- * @param targetCapabilities The target capability restrictions for the table
2019
- * @param selectionMode The selection mode for the table
2020
- * @returns {*} Expression or Boolean value for the visibility of the 'Mass Edit' button
2021
- */
2022
-
2023
- export function getVisibilityMassEdit(
2024
- converterContext: ConverterContext,
2025
- tableManifestConfiguration: TableControlConfiguration,
2026
- targetCapabilities: TableCapabilityRestriction,
2027
- selectionMode: string | undefined
2028
- ): boolean | string | undefined {
2029
- const entitySet = converterContext.getEntitySet(),
2030
- bUpdateHidden: any = entitySet && entitySet?.annotations.UI?.UpdateHidden?.valueOf(),
2031
- bMassEditEnabled: boolean = tableManifestConfiguration?.enableMassEdit || false,
2032
- iSelectionLimit: number = tableManifestConfiguration?.selectionLimit;
2033
- let bMassEditVisible: boolean = true;
2034
- if ((selectionMode && selectionMode === "Single") || (iSelectionLimit && iSelectionLimit < 2)) {
2035
- bMassEditVisible = false;
2036
- } else if (selectionMode && (selectionMode === "Auto" || selectionMode === "None")) {
2037
- bMassEditVisible = true;
2038
- }
2039
- if (targetCapabilities?.isUpdatable !== false && bMassEditVisible && bMassEditEnabled) {
2040
- if (bUpdateHidden && typeof bUpdateHidden === "boolean") {
2041
- return !bUpdateHidden && converterContext.getTemplateType() === TemplateType.ObjectPage ? compileBinding(UI.IsEditable) : false;
2042
- } else if (bUpdateHidden && bUpdateHidden?.path) {
2043
- return converterContext.getTemplateType() === TemplateType.ObjectPage
2044
- ? compileBinding(and(equal(UI.IsEditable, true), equal(annotationExpression(bUpdateHidden), false)))
2045
- : false;
2046
- }
2047
- return converterContext.getTemplateType() === TemplateType.ObjectPage ? compileBinding(UI.IsEditable) : false;
2048
- }
2049
- return false;
2050
- }
2051
-
2052
- /**
2053
- * Function to determine the visibility of the Create button.
2054
- *
2055
- * @param converterContext The instance of the converter context
2056
- * @param creationMode The mode used for creation
2057
- * @param isInsertable Annotation expression of InsertRestrictions.Insertable
2058
- * @param viewConfiguration The instance of the configuration for the view path
2059
- * @returns {Expression<boolean>} Expression or Boolean value of the 'UI.CreateHidden' annotation
2060
- */
2061
- export function getCreateVisible(
2062
- converterContext: ConverterContext,
2063
- creationMode: CreationMode | "External",
2064
- isInsertable: Expression<boolean>,
2065
- viewConfiguration?: ViewPathConfiguration
2066
- ): Expression<boolean> {
2067
- const currentEntitySet = converterContext.getEntitySet();
2068
- const dataModelObjectPath = converterContext.getDataModelObjectPath();
2069
- const visitedNavigationPaths = dataModelObjectPath.navigationProperties.map(navProp => navProp.name);
2070
- const isCreateHidden: Expression<boolean> = currentEntitySet
2071
- ? annotationExpression(
2072
- (currentEntitySet?.annotations.UI?.CreateHidden as PropertyAnnotationValue<boolean>) || false,
2073
- visitedNavigationPaths,
2074
- undefined,
2075
- (path: string) => singletonPathVisitor(path, converterContext, visitedNavigationPaths)
2076
- )
2077
- : constant(false);
2078
-
2079
- // if there is a custom new action the create button will be bound against this new action (instead of a POST action).
2080
- // The visibility of the create button then depends on the new action's OperationAvailable annotation (instead of the insertRestrictions):
2081
- // OperationAvailable = true or undefined -> create is visible
2082
- // OperationAvailable = false -> create is not visible
2083
- const newActionName: BindingExpression<string> = currentEntitySet?.annotations.Common?.DraftRoot?.NewAction?.toString();
2084
- const showCreateForNewAction = newActionName
2085
- ? annotationExpression(
2086
- converterContext?.getEntityType().actions[newActionName].annotations?.Core?.OperationAvailable?.valueOf(),
2087
- [],
2088
- true,
2089
- (path: string) => singletonPathVisitor(path, converterContext, [])
2090
- )
2091
- : undefined;
2092
-
2093
- // - If it's statically not insertable -> create is not visible
2094
- // - If create is statically hidden -> create is not visible
2095
- // - If it's an ALP template -> create is not visible
2096
- // -
2097
- // - Otherwise
2098
- // - If the create mode is external -> create is visible
2099
- // - If we're on the list report ->
2100
- // - If UI.CreateHidden points to a property path -> provide a negated binding to this path
2101
- // - Otherwise, create is visible
2102
- // - Otherwise
2103
- // - This depends on the value of the the UI.IsEditable
2104
- return ifElse(
2105
- or(
2106
- or(
2107
- equal(showCreateForNewAction, false),
2108
- and(isConstant(isInsertable), equal(isInsertable, false), equal(showCreateForNewAction, undefined))
2109
- ),
2110
- isConstant(isCreateHidden) && equal(isCreateHidden, true),
2111
- or(
2112
- viewConfiguration ? converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration) : false,
2113
- converterContext.getTemplateType() === TemplateType.AnalyticalListPage
2114
- )
2115
- ),
2116
- false,
2117
- ifElse(
2118
- creationMode === "External",
2119
- true,
2120
- ifElse(
2121
- converterContext.getTemplateType() === TemplateType.ListReport,
2122
- ifElse(isBinding(isCreateHidden), not(isCreateHidden), true),
2123
- and(not(isCreateHidden), UI.IsEditable)
2124
- )
2125
- )
2126
- );
2127
- }
2128
-
2129
- /**
2130
- * Returns the visibility for the Paste button.
2181
+ * Returns a JSON string containing the sort conditions for the presentation variant.
2131
2182
  *
2132
2183
  * @param converterContext The instance of the converter context
2133
- * @param creationBehaviour The chosen behavior of creation
2134
- * @param isInsertable The expression which denotes insert restrictions
2135
- * @param pasteEnabledInManifest The flag which denotes the paste enablement status via manifest
2136
- * @param viewConfiguration The instance of the configuration for the view path
2137
- * @returns {Expression<boolean>} Expression or Boolean value of the UI.CreateHidden annotation
2138
- */
2139
- export function getPasteEnabled(
2140
- converterContext: ConverterContext,
2141
- creationBehaviour: TableAnnotationConfiguration["create"],
2142
- isInsertable: Expression<boolean>,
2143
- pasteEnabledInManifest: boolean,
2144
- viewConfiguration?: ViewPathConfiguration
2145
- ): Expression<boolean> {
2146
- // If create is not visible -> it's not enabled
2147
- // If create is visible ->
2148
- // If it's in the ListReport -> not enabled
2149
- // If it's insertable -> enabled
2150
- return ifElse(
2151
- pasteEnabledInManifest && equal(getCreateVisible(converterContext, creationBehaviour.mode, isInsertable, viewConfiguration), true),
2152
- converterContext.getTemplateType() === TemplateType.ObjectPage && isInsertable,
2153
- false
2154
- );
2155
- }
2156
-
2157
- /**
2158
- * Returns a JSON string containing Presentation Variant sort conditions.
2159
- *
2160
2184
  * @param {PresentationVariantTypeTypes | undefined} presentationVariantAnnotation Presentation variant annotation
2161
- * @param columns Converter processed table columns
2162
- * @returns {string | undefined} Sort conditions for a Presentation variant.
2185
+ * @param columns Table columns processed by the converter
2186
+ * @returns {string | undefined} Sort conditions for a presentation variant.
2163
2187
  */
2164
2188
  function getSortConditions(
2189
+ converterContext: ConverterContext,
2165
2190
  presentationVariantAnnotation: PresentationVariantTypeTypes | undefined,
2166
2191
  columns: TableColumn[]
2167
2192
  ): string | undefined {
2193
+ // Currently navigation property is not supported as sorter
2194
+ const nonSortableProperties = getNonSortablePropertiesRestrictions(converterContext.getEntitySet());
2168
2195
  let sortConditions: string | undefined;
2169
2196
  if (presentationVariantAnnotation?.SortOrder) {
2170
2197
  const sorters: SorterType[] = [];
@@ -2172,22 +2199,15 @@ function getSortConditions(
2172
2199
  sorters: sorters
2173
2200
  };
2174
2201
  presentationVariantAnnotation.SortOrder.forEach(condition => {
2175
- const propertyName = (condition.Property as PropertyPath)?.$target?.name;
2176
- const sortColumn = columns.find(column => column.name === propertyName) as AnnotationTableColumn;
2177
- sortColumn?.propertyInfos?.forEach(relatedPropertyName => {
2178
- // Complex PropertyInfo. Add each related property for sorting.
2179
- conditions.sorters.push({
2180
- name: relatedPropertyName,
2181
- descending: !!condition.Descending
2182
- });
2183
- });
2184
-
2185
- if (!sortColumn?.propertyInfos?.length) {
2186
- // Not a complex PropertyInfo. Consider the property itself for sorting.
2187
- conditions.sorters.push({
2188
- name: propertyName,
2189
- descending: !!condition.Descending
2190
- });
2202
+ const conditionProperty = condition.Property;
2203
+ if (conditionProperty && nonSortableProperties.indexOf(conditionProperty.$target?.name) === -1) {
2204
+ const infoName = convertPropertyPathsToInfoNames([conditionProperty], columns)[0];
2205
+ if (infoName) {
2206
+ conditions.sorters.push({
2207
+ name: infoName,
2208
+ descending: !!condition.Descending
2209
+ });
2210
+ }
2191
2211
  }
2192
2212
  });
2193
2213
  sortConditions = conditions.sorters.length ? JSON.stringify(conditions) : undefined;
@@ -2286,28 +2306,42 @@ export function getTableAnnotationConfiguration(
2286
2306
  p13nMode: string | undefined = getP13nMode(visualizationPath, converterContext, tableManifestConfiguration),
2287
2307
  id = navigationPropertyPath ? TableID(visualizationPath) : TableID(converterContext.getContextPath(), "LineItem");
2288
2308
  const targetCapabilities = getCapabilityRestriction(converterContext);
2289
- const selectionMode = getSelectionMode(lineItemAnnotation, visualizationPath, converterContext, hasAbsolutePath, targetCapabilities);
2309
+ const navigationTargetPath = getNavigationTargetPath(converterContext, navigationPropertyPath);
2310
+ const navigationSettings = pageManifestSettings.getNavigationConfiguration(navigationTargetPath);
2311
+ const standardActionsContext = generateStandardActionsContext(
2312
+ converterContext,
2313
+ navigationSettings,
2314
+ tableManifestConfiguration,
2315
+ viewConfiguration
2316
+ );
2317
+ const isDeleteButtonVisible = getDeleteVisibility(converterContext, standardActionsContext);
2318
+ const selectionMode = getSelectionMode(
2319
+ lineItemAnnotation,
2320
+ visualizationPath,
2321
+ converterContext,
2322
+ hasAbsolutePath,
2323
+ targetCapabilities,
2324
+ isDeleteButtonVisible
2325
+ );
2290
2326
  let threshold = navigationPropertyPath ? 10 : 30;
2291
2327
  if (presentationVariantAnnotation?.MaxItems) {
2292
2328
  threshold = presentationVariantAnnotation.MaxItems.valueOf() as number;
2293
2329
  }
2294
- const navigationTargetPath = getNavigationTargetPath(converterContext, navigationPropertyPath);
2295
- const navigationSettings = pageManifestSettings.getNavigationConfiguration(navigationTargetPath);
2330
+
2296
2331
  const creationBehaviour = _getCreationBehaviour(lineItemAnnotation, tableManifestConfiguration, converterContext, navigationSettings);
2297
- let isParentDeletable: any, parentEntitySetDeletable;
2298
- if (converterContext.getTemplateType() === TemplateType.ObjectPage) {
2299
- isParentDeletable = isPathDeletable(converterContext.getDataModelObjectPath(), undefined, true);
2300
- if (isParentDeletable?.currentEntityRestriction) {
2301
- parentEntitySetDeletable = undefined;
2302
- } else {
2303
- parentEntitySetDeletable = isParentDeletable ? compileBinding(isParentDeletable, true) : isParentDeletable;
2304
- }
2305
- }
2306
- const dataModelObjectPath = converterContext.getDataModelObjectPath();
2307
- const isInsertable: Expression<boolean> = isPathInsertable(dataModelObjectPath);
2308
2332
  const variantManagement: VariantManagementType = pageManifestSettings.getVariantManagement();
2309
- const bMassEditVisible: any = getVisibilityMassEdit(converterContext, tableManifestConfiguration, targetCapabilities, selectionMode);
2310
2333
  const isSearchable = isPathSearchable(converterContext.getDataModelObjectPath());
2334
+ const tableActions = {
2335
+ create: getStandardActionCreate(converterContext, standardActionsContext),
2336
+ "delete": getStandardActionDelete(converterContext, standardActionsContext),
2337
+ paste: getStandardActionPaste(converterContext, standardActionsContext),
2338
+ massEdit: getStandardActionMassEdit(converterContext, standardActionsContext, selectionMode)
2339
+ };
2340
+ const isInsertUpdateTemplated = getInsertUpdateActionsTemplating(
2341
+ standardActionsContext,
2342
+ isDraftOrStickySupported(converterContext),
2343
+ tableActions.create.visible === "false"
2344
+ );
2311
2345
 
2312
2346
  return {
2313
2347
  id: id,
@@ -2322,22 +2356,9 @@ export function getTableAnnotationConfiguration(
2322
2356
  navigationTargetPath
2323
2357
  ),
2324
2358
  p13nMode: p13nMode,
2325
- show: {
2326
- "delete": getDeleteVisible(converterContext, navigationPropertyPath, targetCapabilities.isDeletable, viewConfiguration),
2327
- create: compileBinding(getCreateVisible(converterContext, creationBehaviour?.mode, isInsertable)),
2328
- paste: compileBinding(
2329
- getPasteEnabled(
2330
- converterContext,
2331
- creationBehaviour,
2332
- isInsertable,
2333
- tableManifestConfiguration.enablePaste,
2334
- viewConfiguration
2335
- )
2336
- ),
2337
- massEdit: {
2338
- visible: bMassEditVisible,
2339
- enabled: getEnablementMassEdit(converterContext, bMassEditVisible)
2340
- }
2359
+ standardActions: {
2360
+ actions: tableActions,
2361
+ isInsertUpdateTemplated: isInsertUpdateTemplated
2341
2362
  },
2342
2363
  displayMode: isInDisplayMode(converterContext, viewConfiguration),
2343
2364
  create: creationBehaviour,
@@ -2348,13 +2369,45 @@ export function getTableAnnotationConfiguration(
2348
2369
  !(viewConfiguration && converterContext.getManifestWrapper().hasMultipleVisualizations(viewConfiguration)),
2349
2370
  variantManagement: variantManagement === "Control" && !p13nMode ? VariantManagementType.None : variantManagement,
2350
2371
  threshold: threshold,
2351
- sortConditions: getSortConditions(presentationVariantAnnotation, columns),
2352
- parentEntityDeleteEnabled: parentEntitySetDeletable,
2372
+ sortConditions: getSortConditions(converterContext, presentationVariantAnnotation, columns),
2353
2373
  title: title,
2354
2374
  searchable: tableManifestConfiguration.type !== "AnalyticalTable" && !(isConstant(isSearchable) && isSearchable.value === false)
2355
2375
  };
2356
2376
  }
2357
2377
 
2378
+ function _getExportDataType(dataType: string, isComplexProperty: boolean = false): string {
2379
+ let exportDataType: string = "String";
2380
+ if (isComplexProperty) {
2381
+ return exportDataType;
2382
+ } else {
2383
+ switch (dataType) {
2384
+ case "Edm.Decimal":
2385
+ case "Edm.Int32":
2386
+ case "Edm.Int64":
2387
+ case "Edm.Double":
2388
+ case "Edm.Byte":
2389
+ exportDataType = "Number";
2390
+ break;
2391
+ case "Edm.DateOfTime":
2392
+ case "Edm.Date":
2393
+ exportDataType = "Date";
2394
+ break;
2395
+ case "Edm.DateTimeOffset":
2396
+ exportDataType = "DateTime";
2397
+ break;
2398
+ case "Edm.TimeOfDay":
2399
+ exportDataType = "Time";
2400
+ break;
2401
+ case "Edm.Boolean":
2402
+ exportDataType = "Boolean";
2403
+ break;
2404
+ default:
2405
+ exportDataType = "String";
2406
+ }
2407
+ }
2408
+ return exportDataType;
2409
+ }
2410
+
2358
2411
  function isInDisplayMode(converterContext: ConverterContext, viewConfiguration?: ViewPathConfiguration): boolean {
2359
2412
  const templateType = converterContext.getTemplateType();
2360
2413
  if (
@@ -2374,7 +2427,7 @@ function isInDisplayMode(converterContext: ConverterContext, viewConfiguration?:
2374
2427
  * @param visualizationPath
2375
2428
  * @returns {object}
2376
2429
  */
2377
- function splitPath(visualizationPath: string) {
2430
+ export function splitPath(visualizationPath: string) {
2378
2431
  let [navigationPropertyPath, annotationPath] = visualizationPath.split("@");
2379
2432
 
2380
2433
  if (navigationPropertyPath.lastIndexOf("/") === navigationPropertyPath.length - 1) {
@@ -2430,7 +2483,9 @@ export function getTableManifestConfiguration(
2430
2483
  let enableFullScreen = false;
2431
2484
  let selectionLimit = 200;
2432
2485
  let multiSelectMode;
2433
- let enablePaste = converterContext.getTemplateType() === "ObjectPage";
2486
+ const enableAutoColumnWidth = !converterContext.getManifestWrapper().isPhone();
2487
+ const enablePaste =
2488
+ tableSettings.enablePaste !== undefined ? tableSettings.enablePaste : converterContext.getTemplateType() === "ObjectPage"; // Paste is disabled by default excepted for OP
2434
2489
  const isCondensedTableLayoutCompliant = checkCondensedLayout && converterContext.getManifestWrapper().isCondensedLayoutCompliant();
2435
2490
  const entityType = converterContext.getEntityType();
2436
2491
  const aggregationHelper = new AggregationHelper(entityType, converterContext);
@@ -2473,8 +2528,14 @@ export function getTableManifestConfiguration(
2473
2528
  }
2474
2529
  }
2475
2530
  }
2476
- enableFullScreen = tableSettings.enableFullScreen || false;
2477
- if (enableFullScreen === true && converterContext.getTemplateType() === TemplateType.ListReport) {
2531
+ // If enableFullScreen is not set, use as default true on phone and false otherwise
2532
+ enableFullScreen = tableSettings.enableFullScreen ?? converterContext.getManifestWrapper().isPhone();
2533
+ // Make sure that enableFullScreen is not set on ListReport for desktop or tablet
2534
+ if (
2535
+ !converterContext.getManifestWrapper().isPhone() &&
2536
+ enableFullScreen &&
2537
+ converterContext.getTemplateType() === TemplateType.ListReport
2538
+ ) {
2478
2539
  enableFullScreen = false;
2479
2540
  converterContext
2480
2541
  .getDiagnostics()
@@ -2496,7 +2557,6 @@ export function getTableManifestConfiguration(
2496
2557
  }
2497
2558
  }
2498
2559
  }
2499
- enablePaste = converterContext.getTemplateType() === "ObjectPage" && tableSettings.enablePaste !== false;
2500
2560
  enableExport =
2501
2561
  tableSettings.enableExport !== undefined
2502
2562
  ? tableSettings.enableExport
@@ -2518,6 +2578,79 @@ export function getTableManifestConfiguration(
2518
2578
  enablePaste: enablePaste,
2519
2579
  showRowCount:
2520
2580
  !tableSettings?.quickVariantSelection?.showCounts && !converterContext.getManifestWrapper().getViewConfiguration()?.showCounts,
2521
- enableMassEdit: tableSettings?.enableMassEdit
2581
+ enableMassEdit: tableSettings?.enableMassEdit,
2582
+ enableAutoColumnWidth: enableAutoColumnWidth
2583
+ };
2584
+ }
2585
+
2586
+ export type configTypeConstraints = {
2587
+ scale?: number;
2588
+ precision?: number;
2589
+ maxLength?: number;
2590
+ nullable?: boolean;
2591
+ minimum?: string;
2592
+ maximum?: string;
2593
+ isDigitSequence?: boolean;
2594
+ };
2595
+
2596
+ export type configTypeformatOptions = {
2597
+ parseAsString?: boolean;
2598
+ emptyString?: string;
2599
+ parseKeepsEmptyString?: boolean;
2600
+ };
2601
+
2602
+ export type configType = {
2603
+ type: string;
2604
+ constraints: configTypeConstraints;
2605
+ formatOptions: configTypeformatOptions;
2606
+ };
2607
+
2608
+ export function getTypeConfig(oProperty: Property | DataFieldAbstractTypes, dataType: string | undefined): any {
2609
+ let oTargetMapping = EDM_TYPE_MAPPING[(oProperty as Property)?.type] || (dataType ? EDM_TYPE_MAPPING[dataType] : undefined);
2610
+ if (!oTargetMapping && (oProperty as Property).targetType && (oProperty as Property).targetType?._type === "TypeDefinition") {
2611
+ oTargetMapping = EDM_TYPE_MAPPING[((oProperty as Property).targetType as TypeDefinition).underlyingType];
2612
+ }
2613
+ const propertyTypeConfig: configType = {
2614
+ type: oTargetMapping.type,
2615
+ constraints: {},
2616
+ formatOptions: {}
2617
+ };
2618
+ if (isProperty(oProperty)) {
2619
+ propertyTypeConfig.constraints = {
2620
+ scale: oTargetMapping.constraints?.$Scale ? oProperty.scale : undefined,
2621
+ precision: oTargetMapping.constraints?.$Precision ? oProperty.precision : undefined,
2622
+ maxLength: oTargetMapping.constraints?.$MaxLength ? oProperty.maxLength : undefined,
2623
+ nullable: oTargetMapping.constraints?.$Nullable ? oProperty.nullable : undefined,
2624
+ minimum:
2625
+ oTargetMapping.constraints?.["@Org.OData.Validation.V1.Minimum/$Decimal"] &&
2626
+ !isNaN(oProperty.annotations?.Validation?.Minimum)
2627
+ ? `${oProperty.annotations?.Validation?.Minimum}`
2628
+ : undefined,
2629
+ maximum:
2630
+ oTargetMapping.constraints?.["@Org.OData.Validation.V1.Maximum/$Decimal"] &&
2631
+ !isNaN(oProperty.annotations?.Validation?.Maximum)
2632
+ ? `${oProperty.annotations?.Validation?.Maximum}`
2633
+ : undefined,
2634
+ isDigitSequence:
2635
+ propertyTypeConfig.type === "sap.ui.model.odata.type.String" &&
2636
+ oTargetMapping.constraints?.["@com.sap.vocabularies.Common.v1.IsDigitSequence"] &&
2637
+ (oProperty as Property).annotations?.Common?.IsDigitSequence
2638
+ ? true
2639
+ : undefined
2640
+ };
2641
+ }
2642
+ propertyTypeConfig.formatOptions = {
2643
+ parseAsString:
2644
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Int") === 0 ||
2645
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Double") === 0
2646
+ ? false
2647
+ : undefined,
2648
+ emptyString:
2649
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Int") === 0 ||
2650
+ propertyTypeConfig?.type?.indexOf("sap.ui.model.odata.type.Double") === 0
2651
+ ? ""
2652
+ : undefined,
2653
+ parseKeepsEmptyString: propertyTypeConfig.type === "sap.ui.model.odata.type.String" ? true : undefined
2522
2654
  };
2655
+ return propertyTypeConfig;
2523
2656
  }