@sapui5/sap.fe.core 1.93.3 → 1.97.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 (193) hide show
  1. package/package.json +6 -6
  2. package/src/sap/fe/core/.library +1 -1
  3. package/src/sap/fe/core/AppComponent.js +8 -40
  4. package/src/sap/fe/core/BusyLocker.js +12 -0
  5. package/src/sap/fe/core/CommonUtils.js +224 -48
  6. package/src/sap/fe/core/ExtensionAPI.js +1 -1
  7. package/src/sap/fe/core/PageController.js +13 -2
  8. package/src/sap/fe/core/RouterProxy.js +52 -64
  9. package/src/sap/fe/core/TemplateComponent.js +8 -2
  10. package/src/sap/fe/core/TransactionHelper.js +210 -180
  11. package/src/sap/fe/core/actions/draft.js +13 -1
  12. package/src/sap/fe/core/actions/messageHandling.js +80 -4
  13. package/src/sap/fe/core/actions/operations.js +207 -68
  14. package/src/sap/fe/core/controllerextensions/EditFlow.js +82 -55
  15. package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +13 -6
  16. package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +132 -23
  17. package/src/sap/fe/core/controllerextensions/InternalRouting.js +203 -214
  18. package/src/sap/fe/core/controllerextensions/KPIManagement.js +834 -170
  19. package/src/sap/fe/core/controllerextensions/KPIManagement.ts +890 -189
  20. package/src/sap/fe/core/controllerextensions/MessageHandler.js +222 -102
  21. package/src/sap/fe/core/controllerextensions/PageReady.js +48 -33
  22. package/src/sap/fe/core/controllerextensions/PageReady.ts +49 -14
  23. package/src/sap/fe/core/controllerextensions/Paginator.js +150 -0
  24. package/src/sap/fe/core/controllerextensions/Placeholder.js +133 -270
  25. package/src/sap/fe/core/controllerextensions/Share.js +12 -9
  26. package/src/sap/fe/core/controllerextensions/SideEffects.js +5 -6
  27. package/src/sap/fe/core/controllerextensions/SideEffects.ts +13 -12
  28. package/src/sap/fe/core/controllerextensions/ViewState.js +202 -8
  29. package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +39 -34
  30. package/src/sap/fe/core/controls/ActionParameterDialogValueHelp.fragment.xml +35 -0
  31. package/src/sap/fe/core/controls/ActionPartial.fragment.xml +1 -1
  32. package/src/sap/fe/core/controls/CustomQuickViewPage.js +109 -108
  33. package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +45 -0
  34. package/src/sap/fe/core/controls/filterbar/FilterContainer.js +15 -4
  35. package/src/sap/fe/core/controls/filterbar/VisualFilter.js +250 -94
  36. package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +129 -135
  37. package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +325 -0
  38. package/src/sap/fe/core/controls/filterbar.d.js +8 -0
  39. package/src/sap/fe/core/controls/filterbar.d.ts +0 -0
  40. package/src/sap/fe/core/converters/ConverterContext.js +19 -5
  41. package/src/sap/fe/core/converters/ConverterContext.ts +13 -3
  42. package/src/sap/fe/core/converters/ManifestSettings.js +2 -1
  43. package/src/sap/fe/core/converters/ManifestSettings.ts +13 -3
  44. package/src/sap/fe/core/converters/ManifestWrapper.js +9 -9
  45. package/src/sap/fe/core/converters/MetaModelConverter.js +867 -871
  46. package/src/sap/fe/core/converters/MetaModelConverter.ts +772 -827
  47. package/src/sap/fe/core/converters/TemplateConverter.js +4 -4
  48. package/src/sap/fe/core/converters/annotations/DataField.js +57 -7
  49. package/src/sap/fe/core/converters/annotations/DataField.ts +52 -2
  50. package/src/sap/fe/core/converters/common/AnnotationConverter.js +146 -85
  51. package/src/sap/fe/core/converters/controls/Common/Action.js +61 -56
  52. package/src/sap/fe/core/converters/controls/Common/Action.ts +54 -39
  53. package/src/sap/fe/core/converters/controls/Common/Chart.js +101 -9
  54. package/src/sap/fe/core/converters/controls/Common/Chart.ts +100 -5
  55. package/src/sap/fe/core/converters/controls/Common/Criticality.js +1 -1
  56. package/src/sap/fe/core/converters/controls/Common/DataVisualization.js +15 -16
  57. package/src/sap/fe/core/converters/controls/Common/DataVisualization.ts +16 -30
  58. package/src/sap/fe/core/converters/controls/Common/Form.js +77 -29
  59. package/src/sap/fe/core/converters/controls/Common/Form.ts +79 -21
  60. package/src/sap/fe/core/converters/controls/Common/KPI.js +287 -109
  61. package/src/sap/fe/core/converters/controls/Common/KPI.ts +314 -139
  62. package/src/sap/fe/core/converters/controls/Common/Table.js +521 -166
  63. package/src/sap/fe/core/converters/controls/Common/Table.ts +519 -115
  64. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +487 -0
  65. package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +541 -0
  66. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +364 -0
  67. package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +338 -0
  68. package/src/sap/fe/core/converters/controls/ObjectPage/Avatar.js +74 -0
  69. package/src/sap/fe/core/converters/controls/ObjectPage/Avatar.ts +50 -0
  70. package/src/sap/fe/core/converters/controls/ObjectPage/HeaderFacet.js +11 -11
  71. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +47 -35
  72. package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +45 -29
  73. package/src/sap/fe/core/converters/helpers/Aggregation.js +31 -32
  74. package/src/sap/fe/core/converters/helpers/Aggregation.ts +26 -27
  75. package/src/sap/fe/core/converters/helpers/BindingHelper.js +27 -2
  76. package/src/sap/fe/core/converters/helpers/BindingHelper.ts +22 -2
  77. package/src/sap/fe/core/converters/helpers/ConfigurableObject.js +1 -1
  78. package/src/sap/fe/core/converters/helpers/ID.js +9 -3
  79. package/src/sap/fe/core/converters/helpers/ID.ts +6 -3
  80. package/src/sap/fe/core/converters/helpers/IssueManager.js +5 -4
  81. package/src/sap/fe/core/converters/helpers/IssueManager.ts +4 -3
  82. package/src/sap/fe/core/converters/helpers/Key.js +3 -3
  83. package/src/sap/fe/core/converters/helpers/SelectionVariantHelper.js +11 -6
  84. package/src/sap/fe/core/converters/helpers/SelectionVariantHelper.ts +9 -5
  85. package/src/sap/fe/core/converters/objectPage/FormMenuActions.js +18 -5
  86. package/src/sap/fe/core/converters/objectPage/FormMenuActions.ts +14 -14
  87. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +91 -20
  88. package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +77 -5
  89. package/src/sap/fe/core/converters/templates/ListReportConverter.js +87 -714
  90. package/src/sap/fe/core/converters/templates/ListReportConverter.ts +85 -812
  91. package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +106 -17
  92. package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +121 -16
  93. package/src/sap/fe/core/designtime/AppComponent.designtime.js +2 -1
  94. package/src/sap/fe/core/formatters/CriticalityFormatter.js +1 -1
  95. package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
  96. package/src/sap/fe/core/formatters/FPMFormatter.ts +8 -3
  97. package/src/sap/fe/core/formatters/KPIFormatter.js +1 -1
  98. package/src/sap/fe/core/formatters/TableFormatter.js +27 -4
  99. package/src/sap/fe/core/formatters/TableFormatter.ts +20 -3
  100. package/src/sap/fe/core/formatters/TableFormatterTypes.js +1 -1
  101. package/src/sap/fe/core/formatters/ValueFormatter.js +1 -1
  102. package/src/sap/fe/core/fpm/Component.js +1 -1
  103. package/src/sap/fe/core/helpers/AnnotationEnum.js +3 -3
  104. package/src/sap/fe/core/helpers/BindingExpression.js +6 -6
  105. package/src/sap/fe/core/helpers/ClassSupport.js +4 -4
  106. package/src/sap/fe/core/helpers/ExcelFormatHelper.js +0 -2
  107. package/src/sap/fe/core/helpers/KeepAliveHelper.js +211 -0
  108. package/src/sap/fe/core/helpers/KeepAliveHelper.ts +202 -0
  109. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.js +32 -0
  110. package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.ts +36 -0
  111. package/src/sap/fe/core/helpers/ModelHelper.js +78 -0
  112. package/src/sap/fe/core/helpers/PasteHelper.js +6 -0
  113. package/src/sap/fe/core/helpers/SemanticKeyHelper.js +2 -2
  114. package/src/sap/fe/core/helpers/StableIdHelper.js +1 -1
  115. package/src/sap/fe/core/helpers/StableIdHelper.ts +1 -1
  116. package/src/sap/fe/core/jsx-runtime/jsx.js +2 -2
  117. package/src/sap/fe/core/jsx-runtime/jsxs.js +1 -1
  118. package/src/sap/fe/core/library.js +1 -1
  119. package/src/sap/fe/core/messagebundle.properties +45 -2
  120. package/src/sap/fe/core/messagebundle_ar.properties +53 -1
  121. package/src/sap/fe/core/messagebundle_bg.properties +52 -0
  122. package/src/sap/fe/core/messagebundle_ca.properties +54 -2
  123. package/src/sap/fe/core/messagebundle_cs.properties +52 -0
  124. package/src/sap/fe/core/messagebundle_cy.properties +52 -0
  125. package/src/sap/fe/core/messagebundle_da.properties +53 -1
  126. package/src/sap/fe/core/messagebundle_de.properties +55 -3
  127. package/src/sap/fe/core/messagebundle_el.properties +53 -1
  128. package/src/sap/fe/core/messagebundle_en.properties +52 -0
  129. package/src/sap/fe/core/messagebundle_en_GB.properties +53 -1
  130. package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +49 -1
  131. package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +53 -1
  132. package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +53 -1
  133. package/src/sap/fe/core/messagebundle_es.properties +60 -8
  134. package/src/sap/fe/core/messagebundle_es_MX.properties +55 -3
  135. package/src/sap/fe/core/messagebundle_et.properties +52 -0
  136. package/src/sap/fe/core/messagebundle_fi.properties +52 -0
  137. package/src/sap/fe/core/messagebundle_fr.properties +61 -9
  138. package/src/sap/fe/core/messagebundle_fr_CA.properties +52 -0
  139. package/src/sap/fe/core/messagebundle_hi.properties +53 -1
  140. package/src/sap/fe/core/messagebundle_hr.properties +53 -1
  141. package/src/sap/fe/core/messagebundle_hu.properties +52 -0
  142. package/src/sap/fe/core/messagebundle_id.properties +54 -2
  143. package/src/sap/fe/core/messagebundle_it.properties +53 -1
  144. package/src/sap/fe/core/messagebundle_iw.properties +54 -2
  145. package/src/sap/fe/core/messagebundle_ja.properties +62 -10
  146. package/src/sap/fe/core/messagebundle_kk.properties +53 -1
  147. package/src/sap/fe/core/messagebundle_ko.properties +53 -1
  148. package/src/sap/fe/core/messagebundle_lt.properties +53 -1
  149. package/src/sap/fe/core/messagebundle_lv.properties +53 -1
  150. package/src/sap/fe/core/messagebundle_ms.properties +53 -1
  151. package/src/sap/fe/core/messagebundle_nl.properties +57 -5
  152. package/src/sap/fe/core/messagebundle_no.properties +54 -2
  153. package/src/sap/fe/core/messagebundle_pl.properties +53 -1
  154. package/src/sap/fe/core/messagebundle_pt.properties +54 -2
  155. package/src/sap/fe/core/messagebundle_pt_PT.properties +53 -1
  156. package/src/sap/fe/core/messagebundle_ro.properties +53 -1
  157. package/src/sap/fe/core/messagebundle_ru.properties +53 -1
  158. package/src/sap/fe/core/messagebundle_sh.properties +53 -1
  159. package/src/sap/fe/core/messagebundle_sk.properties +52 -0
  160. package/src/sap/fe/core/messagebundle_sl.properties +53 -1
  161. package/src/sap/fe/core/messagebundle_sv.properties +53 -1
  162. package/src/sap/fe/core/messagebundle_th.properties +52 -0
  163. package/src/sap/fe/core/messagebundle_tr.properties +52 -0
  164. package/src/sap/fe/core/messagebundle_uk.properties +52 -0
  165. package/src/sap/fe/core/messagebundle_vi.properties +53 -1
  166. package/src/sap/fe/core/messagebundle_zh_CN.properties +53 -1
  167. package/src/sap/fe/core/messagebundle_zh_TW.properties +53 -1
  168. package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +5 -5
  169. package/src/sap/fe/core/services/EnvironmentServiceFactory.js +5 -5
  170. package/src/sap/fe/core/services/RoutingServiceFactory.js +154 -78
  171. package/src/sap/fe/core/services/ShellServicesFactory.js +9 -9
  172. package/src/sap/fe/core/services/SideEffectsServiceFactory.js +11 -12
  173. package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +12 -2
  174. package/src/sap/fe/core/support/AnnotationIssue.support.js +2 -4
  175. package/src/sap/fe/core/support/CollectionFacetMissingID.support.js +2 -4
  176. package/src/sap/fe/core/support/CollectionFacetUnsupportedLevel.support.js +2 -4
  177. package/src/sap/fe/core/support/CommonHelper.js +2 -4
  178. package/src/sap/fe/core/support/Diagnostics.js +1 -1
  179. package/src/sap/fe/core/templating/CriticalityFormatters.js +4 -4
  180. package/src/sap/fe/core/templating/DataFieldFormatters.js +1 -1
  181. package/src/sap/fe/core/templating/DataModelPathHelper.js +54 -6
  182. package/src/sap/fe/core/templating/DataModelPathHelper.ts +54 -4
  183. package/src/sap/fe/core/templating/EntitySetHelper.js +86 -3
  184. package/src/sap/fe/core/templating/EntitySetHelper.ts +44 -0
  185. package/src/sap/fe/core/templating/FieldControlHelper.js +1 -1
  186. package/src/sap/fe/core/templating/FilterHelper.js +23 -5
  187. package/src/sap/fe/core/templating/FilterHelper.ts +15 -1
  188. package/src/sap/fe/core/templating/FilterTemplating.js +1 -1
  189. package/src/sap/fe/core/templating/PropertyFormatters.js +1 -1
  190. package/src/sap/fe/core/templating/PropertyHelper.js +8 -8
  191. package/src/sap/fe/core/templating/UIFormatters.js +72 -4
  192. package/src/sap/fe/core/templating/UIFormatters.ts +98 -3
  193. package/src/sap/fe/core/type/Email.js +1 -1
@@ -3,11 +3,21 @@ import { Property } from "@sap-ux/annotation-converter";
3
3
  import {
4
4
  AnnotationTerm,
5
5
  UIAnnotationTerms,
6
+ UIAnnotationTypes,
6
7
  PathAnnotationExpression,
7
8
  CriticalityType,
8
9
  ImprovementDirectionType
9
10
  } from "@sap-ux/vocabularies-types";
10
- import { KPIType } from "@sap-ux/vocabularies-types/dist/generated/UI";
11
+ import {
12
+ KPIType,
13
+ SelectionPresentationVariantType,
14
+ PresentationVariant,
15
+ SelectionVariant,
16
+ DataPoint,
17
+ Chart,
18
+ TrendType
19
+ } from "@sap-ux/vocabularies-types/dist/generated/UI";
20
+ import { PropertyPath } from "@sap-ux/vocabularies-types/dist/Edm";
11
21
  import ConverterContext from "sap/fe/core/converters/ConverterContext";
12
22
  import { KPIID } from "../../helpers/ID";
13
23
  import { isPathExpression } from "sap/fe/core/templating/PropertyHelper";
@@ -17,6 +27,14 @@ import { IssueCategory, IssueSeverity, IssueType } from "sap/fe/core/converters/
17
27
  import { getMessageTypeFromCriticalityType } from "./Criticality";
18
28
  import { getFilterDefinitionsFromSelectionVariant, FilterDefinition } from "sap/fe/core/converters/helpers/SelectionVariantHelper";
19
29
 
30
+ export type KPIChartDefinition = {
31
+ chartType: string;
32
+ dimensions: { name: string; label: string; role?: string }[];
33
+ measures: { name: string; label: string; role?: string }[];
34
+ sortOrder?: { name: string; descending: boolean }[];
35
+ maxItems?: number;
36
+ };
37
+
20
38
  export type KPIDefinition = {
21
39
  id: string;
22
40
  entitySet: string;
@@ -32,171 +50,328 @@ export type KPIDefinition = {
32
50
  criticalityValue?: MessageType;
33
51
  criticalityCalculationMode?: ImprovementDirectionType;
34
52
  criticalityCalculationThresholds?: (number | undefined | null)[];
53
+ title?: string;
54
+ description?: string;
55
+ trendPath?: string;
56
+ trendValue?: string;
57
+ trendCalculationReferenceValue?: number;
58
+ trendCalculationReferencePath?: string;
59
+ trendCalculationTresholds?: (number | undefined | null)[];
60
+ trendCalculationIsRelative?: boolean;
61
+ targetValue?: number;
62
+ targetPath?: string;
35
63
  };
64
+ chart: KPIChartDefinition;
36
65
  selectionVariantFilterDefinitions?: FilterDefinition[];
37
66
  };
38
67
 
39
- function createKPIDefinition(kpiName: string, kpiConfig: KPIConfiguration, converterContext: ConverterContext): KPIDefinition | undefined {
40
- const kpiConverterContext = converterContext.getConverterContextFor("/" + kpiConfig.entitySet);
41
- const aKPIAnnotations = kpiConverterContext.getAnnotationsByTerm("UI", UIAnnotationTerms.KPI) as AnnotationTerm<KPIType>[];
42
- const targetKPI = aKPIAnnotations.find(kpi => {
43
- return kpi.qualifier === kpiConfig.qualifier;
44
- });
45
- const aggregationHelper = new AggregationHelper(kpiConverterContext.getEntityType(), kpiConverterContext);
68
+ const DeviationIndicatorFromTrendType: Record<string, string> = {
69
+ "UI.TrendType/StrongUp": "Up",
70
+ "UI.TrendType/Up": "Up",
71
+ "UI.TrendType/StrongDown": "Down",
72
+ "UI.TrendType/Down": "Down",
73
+ "UI.TrendType/Sideways": "None"
74
+ };
46
75
 
47
- if (targetKPI && targetKPI.Detail?.DefaultPresentationVariant && aggregationHelper.isAnalyticsSupported()) {
48
- const kpiID = KPIID(kpiName);
76
+ const KPIChartTypeFromUI: Record<string, string> = {
77
+ "UI.ChartType/ColumnStacked": "StackedColumn",
78
+ "UI.ChartType/BarStacked": "StackedBar",
79
+ "UI.ChartType/Donut": "Donut",
80
+ "UI.ChartType/Line": "Line",
81
+ "UI.ChartType/Bubble": "bubble",
82
+ "UI.ChartType/Column": "column",
83
+ "UI.ChartType/Bar": "bar",
84
+ "UI.ChartType/VerticalBullet": "vertical_bullet",
85
+ "UI.ChartType/Combination": "combination",
86
+ "UI.ChartType/Scatter": "scatter"
87
+ };
49
88
 
50
- // Datapoint
51
- const datapointAnnotation = targetKPI.DataPoint;
52
- const datapointProperty = datapointAnnotation.Value.$target as Property;
53
- if (!aggregationHelper.isPropertyAggregatable(datapointProperty)) {
54
- // The main property of the KPI is not aggregatable --> We can't calculate its value so we ignore the KPI
55
- converterContext
56
- .getDiagnostics()
57
- .addIssue(
58
- IssueCategory.Annotation,
59
- IssueSeverity.Medium,
60
- IssueType.KPI_ISSUES.MAIN_PROPERTY_NOT_AGGREGATABLE + kpiConfig.qualifier
61
- );
62
- return undefined;
63
- }
89
+ function convertKPIChart(chartAnnotation: Chart, presentationVariantAnnotation: PresentationVariant): KPIChartDefinition | undefined {
90
+ if (chartAnnotation.Measures === undefined) {
91
+ // We need at least 1 measure (but no dimension is allowed, e.g. for bubble chart)
92
+ return undefined;
93
+ }
64
94
 
65
- const kpiDef: KPIDefinition = {
66
- id: kpiID,
67
- entitySet: kpiConfig.entitySet,
68
- datapoint: {
69
- propertyPath: datapointAnnotation.Value.path,
70
- annotationPath: kpiConverterContext.getEntitySetBasedAnnotationPath(datapointAnnotation.fullyQualifiedName)
71
- },
72
- selectionVariantFilterDefinitions: targetKPI.SelectionVariant
73
- ? getFilterDefinitionsFromSelectionVariant(targetKPI.SelectionVariant)
74
- : undefined
95
+ const charDimensions = chartAnnotation.Dimensions
96
+ ? (chartAnnotation.Dimensions as PropertyPath[]).map(propertyPath => {
97
+ const dimAttribute = chartAnnotation.DimensionAttributes?.find(attribute => {
98
+ return attribute.Dimension?.value === propertyPath.value;
99
+ });
100
+ return {
101
+ name: propertyPath.value,
102
+ label: propertyPath.$target.annotations.Common?.Label?.toString() || propertyPath.value,
103
+ role: dimAttribute?.Role?.replace("UI.ChartDimensionRoleType/", "")
104
+ };
105
+ })
106
+ : [];
107
+
108
+ const chartMeasures = (chartAnnotation.Measures as PropertyPath[]).map(propertyPath => {
109
+ const measureAttribute = chartAnnotation.MeasureAttributes?.find(attribute => {
110
+ return attribute.Measure?.value === propertyPath.value;
111
+ });
112
+ return {
113
+ name: propertyPath.value,
114
+ label: propertyPath.$target.annotations.Common?.Label?.toString() || propertyPath.value,
115
+ role: measureAttribute?.Role?.replace("UI.ChartMeasureRoleType/", "")
75
116
  };
117
+ });
76
118
 
77
- // Unit or currency
78
- const targetValueProperty = datapointAnnotation.Value.$target as Property;
79
- if (targetValueProperty.annotations.Measures?.ISOCurrency) {
80
- const currency = targetValueProperty.annotations.Measures?.ISOCurrency;
81
- if (isPathExpression(currency)) {
82
- kpiDef.datapoint.unit = {
83
- value: ((currency.$target as unknown) as Property).name,
84
- isCurrency: true,
85
- isPath: true
86
- };
119
+ return {
120
+ chartType: KPIChartTypeFromUI[chartAnnotation.ChartType] || "Line",
121
+ dimensions: charDimensions,
122
+ measures: chartMeasures,
123
+ sortOrder: presentationVariantAnnotation?.SortOrder?.map(sortOrder => {
124
+ return { name: sortOrder.Property?.value || "", descending: !!sortOrder.Descending };
125
+ }),
126
+ maxItems: presentationVariantAnnotation?.MaxItems?.valueOf() as number
127
+ };
128
+ }
129
+
130
+ function updateCurrency(datapointAnnotation: DataPoint, kpiDef: KPIDefinition): void {
131
+ const targetValueProperty = datapointAnnotation.Value.$target as Property;
132
+ if (targetValueProperty.annotations.Measures?.ISOCurrency) {
133
+ const currency = targetValueProperty.annotations.Measures?.ISOCurrency;
134
+ if (isPathExpression(currency)) {
135
+ kpiDef.datapoint.unit = {
136
+ value: ((currency.$target as unknown) as Property).name,
137
+ isCurrency: true,
138
+ isPath: true
139
+ };
140
+ } else {
141
+ kpiDef.datapoint.unit = {
142
+ value: currency.toString(),
143
+ isCurrency: true,
144
+ isPath: false
145
+ };
146
+ }
147
+ } else if (targetValueProperty.annotations.Measures?.Unit) {
148
+ const unit = targetValueProperty.annotations.Measures?.Unit;
149
+ if (isPathExpression(unit)) {
150
+ kpiDef.datapoint.unit = {
151
+ value: ((unit.$target as unknown) as Property).name,
152
+ isCurrency: false,
153
+ isPath: true
154
+ };
155
+ } else {
156
+ kpiDef.datapoint.unit = {
157
+ value: unit.toString(),
158
+ isCurrency: false,
159
+ isPath: false
160
+ };
161
+ }
162
+ }
163
+ }
164
+
165
+ function updateCriticality(datapointAnnotation: DataPoint, aggregationHelper: AggregationHelper, kpiDef: KPIDefinition): void {
166
+ if (datapointAnnotation.Criticality) {
167
+ if (typeof datapointAnnotation.Criticality === "object") {
168
+ // Criticality is a path --> check if the corresponding property is aggregatable
169
+ const criticalityProperty = (datapointAnnotation.Criticality as PathAnnotationExpression<CriticalityType>).$target as Property;
170
+ if (aggregationHelper.isPropertyAggregatable(criticalityProperty)) {
171
+ kpiDef.datapoint.criticalityPath = (datapointAnnotation.Criticality as PathAnnotationExpression<CriticalityType>).path;
87
172
  } else {
88
- kpiDef.datapoint.unit = {
89
- value: currency.toString(),
90
- isCurrency: true,
91
- isPath: false
92
- };
173
+ // The property isn't aggregatable --> we ignore it
174
+ kpiDef.datapoint.criticalityValue = MessageType.None;
93
175
  }
94
- } else if (targetValueProperty.annotations.Measures?.Unit) {
95
- const unit = targetValueProperty.annotations.Measures?.Unit;
96
- if (isPathExpression(unit)) {
97
- kpiDef.datapoint.unit = {
98
- value: ((unit.$target as unknown) as Property).name,
99
- isCurrency: false,
100
- isPath: true
101
- };
176
+ } else {
177
+ // Criticality is an enum Value --> get the corresponding static value
178
+ kpiDef.datapoint.criticalityValue = getMessageTypeFromCriticalityType(datapointAnnotation.Criticality);
179
+ }
180
+ } else if (datapointAnnotation.CriticalityCalculation) {
181
+ kpiDef.datapoint.criticalityCalculationMode = datapointAnnotation.CriticalityCalculation.ImprovementDirection;
182
+ kpiDef.datapoint.criticalityCalculationThresholds = [];
183
+ switch (kpiDef.datapoint.criticalityCalculationMode) {
184
+ case "UI.ImprovementDirectionType/Target":
185
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue);
186
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue);
187
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue);
188
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue);
189
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue);
190
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue);
191
+ break;
192
+
193
+ case "UI.ImprovementDirectionType/Minimize":
194
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue);
195
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue);
196
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue);
197
+ break;
198
+
199
+ case "UI.ImprovementDirectionType/Maximize":
200
+ default:
201
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue);
202
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue);
203
+ kpiDef.datapoint.criticalityCalculationThresholds.push(datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue);
204
+ }
205
+ } else {
206
+ kpiDef.datapoint.criticalityValue = MessageType.None;
207
+ }
208
+ }
209
+
210
+ function updateTrend(datapointAnnotation: DataPoint, aggregationHelper: AggregationHelper, kpiDef: KPIDefinition): void {
211
+ if (datapointAnnotation.Trend) {
212
+ if (typeof datapointAnnotation.Trend === "object") {
213
+ // Trend is a path --> check if the corresponding property is aggregatable
214
+ const trendProperty = (datapointAnnotation.Trend as PathAnnotationExpression<TrendType>).$target as Property;
215
+ if (aggregationHelper.isPropertyAggregatable(trendProperty)) {
216
+ kpiDef.datapoint.trendPath = (datapointAnnotation.Trend as PathAnnotationExpression<TrendType>).path;
102
217
  } else {
103
- kpiDef.datapoint.unit = {
104
- value: unit.toString(),
105
- isCurrency: false,
106
- isPath: false
107
- };
218
+ // The property isn't aggregatable --> we ignore it
219
+ kpiDef.datapoint.trendValue = "None";
108
220
  }
221
+ } else {
222
+ // Trend is an enum Value --> get the corresponding static value
223
+ kpiDef.datapoint.trendValue = DeviationIndicatorFromTrendType[datapointAnnotation.Trend] || "None";
109
224
  }
110
-
111
- // Criticality
112
- if (datapointAnnotation.Criticality) {
113
- if (typeof datapointAnnotation.Criticality === "object") {
114
- // Criticality is a path --> check if the corresponding property is aggregatable
115
- const criticalityProperty = (datapointAnnotation.Criticality as PathAnnotationExpression<CriticalityType>)
116
- .$target as Property;
117
- if (aggregationHelper.isPropertyAggregatable(criticalityProperty)) {
118
- kpiDef.datapoint.criticalityPath = (datapointAnnotation.Criticality as PathAnnotationExpression<CriticalityType>).path;
119
- } else {
120
- // The property isn't aggregatable --> we ignore it
121
- kpiDef.datapoint.criticalityValue = MessageType.None;
122
- }
225
+ } else if (datapointAnnotation.TrendCalculation) {
226
+ kpiDef.datapoint.trendCalculationIsRelative = datapointAnnotation.TrendCalculation.IsRelativeDifference ? true : false;
227
+ if (datapointAnnotation.TrendCalculation.ReferenceValue.$target) {
228
+ // Reference value is a path --> check if the corresponding property is aggregatable
229
+ const referenceProperty = datapointAnnotation.TrendCalculation.ReferenceValue.$target as Property;
230
+ if (aggregationHelper.isPropertyAggregatable(referenceProperty)) {
231
+ kpiDef.datapoint.trendCalculationReferencePath = datapointAnnotation.TrendCalculation.ReferenceValue.path;
123
232
  } else {
124
- // Criticality is an enum Value --> get the corresponding static value
125
- kpiDef.datapoint.criticalityValue = getMessageTypeFromCriticalityType(datapointAnnotation.Criticality);
233
+ // The property isn't aggregatable --> we ignore it and switch back to trend 'None'
234
+ kpiDef.datapoint.trendValue = "None";
126
235
  }
127
- } else if (datapointAnnotation.CriticalityCalculation) {
128
- kpiDef.datapoint.criticalityCalculationMode = datapointAnnotation.CriticalityCalculation.ImprovementDirection;
129
- kpiDef.datapoint.criticalityCalculationThresholds = [];
130
- switch (kpiDef.datapoint.criticalityCalculationMode) {
131
- case "UI.ImprovementDirectionType/Target":
132
- kpiDef.datapoint.criticalityCalculationThresholds.push(
133
- datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue
134
- );
135
- kpiDef.datapoint.criticalityCalculationThresholds.push(
136
- datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue
137
- );
138
- kpiDef.datapoint.criticalityCalculationThresholds.push(
139
- datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue
140
- );
141
- kpiDef.datapoint.criticalityCalculationThresholds.push(
142
- datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue
143
- );
144
- kpiDef.datapoint.criticalityCalculationThresholds.push(
145
- datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue
146
- );
147
- kpiDef.datapoint.criticalityCalculationThresholds.push(
148
- datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue
149
- );
150
- break;
151
-
152
- case "UI.ImprovementDirectionType/Minimize":
153
- kpiDef.datapoint.criticalityCalculationThresholds.push(
154
- datapointAnnotation.CriticalityCalculation.AcceptanceRangeHighValue
155
- );
156
- kpiDef.datapoint.criticalityCalculationThresholds.push(
157
- datapointAnnotation.CriticalityCalculation.ToleranceRangeHighValue
158
- );
159
- kpiDef.datapoint.criticalityCalculationThresholds.push(
160
- datapointAnnotation.CriticalityCalculation.DeviationRangeHighValue
161
- );
162
- break;
163
-
164
- case "UI.ImprovementDirectionType/Maximize":
165
- default:
166
- kpiDef.datapoint.criticalityCalculationThresholds.push(
167
- datapointAnnotation.CriticalityCalculation.DeviationRangeLowValue
168
- );
169
- kpiDef.datapoint.criticalityCalculationThresholds.push(
170
- datapointAnnotation.CriticalityCalculation.ToleranceRangeLowValue
171
- );
172
- kpiDef.datapoint.criticalityCalculationThresholds.push(
173
- datapointAnnotation.CriticalityCalculation.AcceptanceRangeLowValue
174
- );
236
+ } else {
237
+ // Reference value is a static value
238
+ kpiDef.datapoint.trendCalculationReferenceValue = datapointAnnotation.TrendCalculation.ReferenceValue;
239
+ }
240
+ if (kpiDef.datapoint.trendCalculationReferencePath !== undefined || kpiDef.datapoint.trendCalculationReferenceValue !== undefined) {
241
+ kpiDef.datapoint.trendCalculationTresholds = [
242
+ datapointAnnotation.TrendCalculation.StrongDownDifference.valueOf() as number,
243
+ datapointAnnotation.TrendCalculation.DownDifference.valueOf() as number,
244
+ datapointAnnotation.TrendCalculation.UpDifference.valueOf() as number,
245
+ datapointAnnotation.TrendCalculation.StrongUpDifference.valueOf() as number
246
+ ];
247
+ }
248
+ } else {
249
+ kpiDef.datapoint.trendValue = "None";
250
+ }
251
+ }
252
+
253
+ function updateTarget(datapointAnnotation: DataPoint, aggregationHelper: AggregationHelper, kpiDef: KPIDefinition): void {
254
+ if (datapointAnnotation.TargetValue) {
255
+ if (datapointAnnotation.TargetValue.$target) {
256
+ // Target value is a path --> check if the corresponding property is aggregatable (otherwise ignore)
257
+ const targetProperty = datapointAnnotation.TargetValue.$target as Property;
258
+ if (aggregationHelper.isPropertyAggregatable(targetProperty)) {
259
+ kpiDef.datapoint.targetPath = datapointAnnotation.TargetValue.path;
175
260
  }
176
261
  } else {
177
- kpiDef.datapoint.criticalityValue = MessageType.None;
262
+ // Target value is a static value
263
+ kpiDef.datapoint.targetValue = datapointAnnotation.TargetValue;
178
264
  }
265
+ }
266
+ }
267
+
268
+ function createKPIDefinition(kpiName: string, kpiConfig: KPIConfiguration, converterContext: ConverterContext): KPIDefinition | undefined {
269
+ const kpiConverterContext = converterContext.getConverterContextFor("/" + kpiConfig.entitySet);
270
+ const aggregationHelper = new AggregationHelper(kpiConverterContext.getEntityType(), kpiConverterContext);
179
271
 
180
- return kpiDef;
272
+ if (!aggregationHelper.isAnalyticsSupported()) {
273
+ // The entity doesn't support analytical queries
274
+ converterContext
275
+ .getDiagnostics()
276
+ .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.NO_ANALYTICS + kpiConfig.entitySet);
277
+
278
+ return undefined;
279
+ }
280
+
281
+ let selectionVariantAnnotation: SelectionVariant | undefined;
282
+ let datapointAnnotation: DataPoint | undefined;
283
+ let presentationVariantAnnotation: PresentationVariant | undefined;
284
+ let chartAnnotation: Chart | undefined;
285
+
286
+ // Search for a KPI with the qualifier frmo the manifest
287
+ const aKPIAnnotations = kpiConverterContext.getAnnotationsByTerm("UI", UIAnnotationTerms.KPI) as AnnotationTerm<KPIType>[];
288
+ const targetKPI = aKPIAnnotations.find(kpi => {
289
+ return kpi.qualifier === kpiConfig.qualifier;
290
+ });
291
+ if (targetKPI) {
292
+ datapointAnnotation = targetKPI.DataPoint;
293
+ selectionVariantAnnotation = targetKPI.SelectionVariant;
294
+ presentationVariantAnnotation = targetKPI.Detail?.DefaultPresentationVariant;
295
+ chartAnnotation = presentationVariantAnnotation?.Visualizations?.find((viz: any) => {
296
+ return viz.$target.$Type === UIAnnotationTypes.ChartDefinitionType;
297
+ })?.$target as Chart;
181
298
  } else {
182
- if (!targetKPI) {
183
- // Couldn't find a KPI with the qualifier specified in the manifest
184
- converterContext
185
- .getDiagnostics()
186
- .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_NOT_FOUND + kpiConfig.qualifier);
187
- } else if (!targetKPI.Detail?.DefaultPresentationVariant) {
188
- // No KPI detail/default presentation variant
189
- converterContext
190
- .getDiagnostics()
191
- .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_DETAIL_NOT_FOUND + kpiConfig.qualifier);
299
+ // Fallback: try to find a SPV with the same qualifier
300
+ const aSPVAnnotations = kpiConverterContext.getAnnotationsByTerm(
301
+ "UI",
302
+ UIAnnotationTerms.SelectionPresentationVariant
303
+ ) as AnnotationTerm<SelectionPresentationVariantType>[];
304
+ const targetSPV = aSPVAnnotations.find(spv => {
305
+ return spv.qualifier === kpiConfig.qualifier;
306
+ });
307
+ if (targetSPV) {
308
+ selectionVariantAnnotation = targetSPV.SelectionVariant;
309
+ presentationVariantAnnotation = targetSPV.PresentationVariant;
310
+ datapointAnnotation = presentationVariantAnnotation?.Visualizations?.find((viz: any) => {
311
+ return viz.$target.$Type === UIAnnotationTypes.DataPointType;
312
+ })?.$target as DataPoint;
313
+ chartAnnotation = presentationVariantAnnotation?.Visualizations?.find((viz: any) => {
314
+ return viz.$target.$Type === UIAnnotationTypes.ChartDefinitionType;
315
+ })?.$target as Chart;
192
316
  } else {
193
- // Entity doesn't support analytics
317
+ // Couldn't find a KPI or a SPV annotation with the qualifier from the manifest
194
318
  converterContext
195
319
  .getDiagnostics()
196
- .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.NO_ANALYTICS + kpiConfig.entitySet);
320
+ .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_NOT_FOUND + kpiConfig.qualifier);
321
+
322
+ return undefined;
197
323
  }
324
+ }
325
+
326
+ if (!presentationVariantAnnotation || !datapointAnnotation || !chartAnnotation) {
327
+ // Couldn't find a chart or datapoint definition
328
+ converterContext
329
+ .getDiagnostics()
330
+ .addIssue(IssueCategory.Annotation, IssueSeverity.Medium, IssueType.KPI_ISSUES.KPI_DETAIL_NOT_FOUND + kpiConfig.qualifier);
331
+
332
+ return undefined;
333
+ }
334
+
335
+ const datapointProperty = datapointAnnotation.Value.$target as Property;
336
+ if (!aggregationHelper.isPropertyAggregatable(datapointProperty)) {
337
+ // The main property of the KPI is not aggregatable --> We can't calculate its value so we ignore the KPI
338
+ converterContext
339
+ .getDiagnostics()
340
+ .addIssue(
341
+ IssueCategory.Annotation,
342
+ IssueSeverity.Medium,
343
+ IssueType.KPI_ISSUES.MAIN_PROPERTY_NOT_AGGREGATABLE + kpiConfig.qualifier
344
+ );
198
345
  return undefined;
199
346
  }
347
+
348
+ // Chart definition
349
+ const chartDef = convertKPIChart(chartAnnotation, presentationVariantAnnotation);
350
+ if (!chartDef) {
351
+ return undefined;
352
+ }
353
+
354
+ const kpiDef: KPIDefinition = {
355
+ id: KPIID(kpiName),
356
+ entitySet: kpiConfig.entitySet,
357
+ datapoint: {
358
+ propertyPath: datapointAnnotation.Value.path,
359
+ annotationPath: kpiConverterContext.getEntitySetBasedAnnotationPath(datapointAnnotation.fullyQualifiedName),
360
+ title: datapointAnnotation.Title?.toString(),
361
+ description: datapointAnnotation.Description?.toString()
362
+ },
363
+ selectionVariantFilterDefinitions: selectionVariantAnnotation
364
+ ? getFilterDefinitionsFromSelectionVariant(selectionVariantAnnotation)
365
+ : undefined,
366
+ chart: chartDef
367
+ };
368
+
369
+ updateCurrency(datapointAnnotation, kpiDef);
370
+ updateCriticality(datapointAnnotation, aggregationHelper, kpiDef);
371
+ updateTrend(datapointAnnotation, aggregationHelper, kpiDef);
372
+ updateTarget(datapointAnnotation, aggregationHelper, kpiDef);
373
+
374
+ return kpiDef;
200
375
  }
201
376
 
202
377
  /**