@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.
- package/package.json +5 -5
- package/src/sap/fe/core/.library +1 -1
- package/src/sap/fe/core/AnnotationHelper.js +3 -3
- package/src/sap/fe/core/AppComponent.js +9 -44
- package/src/sap/fe/core/AppStateHandler.js +2 -2
- package/src/sap/fe/core/BaseController.js +1 -1
- package/src/sap/fe/core/BusyLocker.js +13 -1
- package/src/sap/fe/core/CommonUtils.js +129 -219
- package/src/sap/fe/core/ExtensionAPI.js +14 -6
- package/src/sap/fe/core/PageController.js +9 -35
- package/src/sap/fe/core/RouterProxy.js +79 -75
- package/src/sap/fe/core/Synchronization.js +1 -1
- package/src/sap/fe/core/TemplateComponent.js +16 -7
- package/src/sap/fe/core/TemplateModel.js +1 -1
- package/src/sap/fe/core/TransactionHelper.js +183 -65
- package/src/sap/fe/core/actions/draft.js +50 -23
- package/src/sap/fe/core/actions/messageHandling.js +86 -7
- package/src/sap/fe/core/actions/nonDraft.js +1 -1
- package/src/sap/fe/core/actions/operations.js +75 -33
- package/src/sap/fe/core/actions/sticky.js +1 -1
- package/src/sap/fe/core/controllerextensions/ControllerExtensionMetadata.js +1 -1
- package/src/sap/fe/core/controllerextensions/EditFlow.js +276 -122
- package/src/sap/fe/core/controllerextensions/IntentBasedNavigation.js +1 -1
- package/src/sap/fe/core/controllerextensions/InternalEditFlow.js +14 -6
- package/src/sap/fe/core/controllerextensions/InternalIntentBasedNavigation.js +90 -46
- package/src/sap/fe/core/controllerextensions/InternalRouting.js +234 -232
- package/src/sap/fe/core/controllerextensions/KPIManagement.js +539 -209
- package/src/sap/fe/core/controllerextensions/KPIManagement.ts +550 -213
- package/src/sap/fe/core/controllerextensions/MassEdit.js +79 -0
- package/src/sap/fe/core/controllerextensions/MessageHandler.js +227 -103
- package/src/sap/fe/core/controllerextensions/PageReady.js +2 -2
- package/src/sap/fe/core/controllerextensions/PageReady.ts +3 -7
- package/src/sap/fe/core/controllerextensions/Paginator.js +38 -12
- package/src/sap/fe/core/controllerextensions/Placeholder.js +16 -19
- package/src/sap/fe/core/controllerextensions/Routing.js +17 -2
- package/src/sap/fe/core/controllerextensions/RoutingListener.js +1 -1
- package/src/sap/fe/core/controllerextensions/Share.js +20 -7
- package/src/sap/fe/core/controllerextensions/SideEffects.js +8 -9
- package/src/sap/fe/core/controllerextensions/SideEffects.ts +19 -17
- package/src/sap/fe/core/controllerextensions/ViewState.js +54 -9
- package/src/sap/fe/core/controls/ActionParameterDialog.fragment.xml +40 -34
- package/src/sap/fe/core/controls/ActionParameterDialogValueHelp.fragment.xml +35 -0
- package/src/sap/fe/core/controls/CommandExecution.js +1 -1
- package/src/sap/fe/core/controls/ConditionalWrapper.js +1 -1
- package/src/sap/fe/core/controls/CustomQuickViewPage.js +110 -109
- package/src/sap/fe/core/controls/DataLossOrDraftDiscard/DataLossOrDraftDiscardHandler.js +7 -4
- package/src/sap/fe/core/controls/FieldWrapper.js +10 -4
- package/src/sap/fe/core/controls/FilterBar.js +1 -1
- package/src/sap/fe/core/controls/FormElementWrapper.js +1 -6
- package/src/sap/fe/core/controls/MultiValueParameterDelegate.js +45 -0
- package/src/sap/fe/core/controls/NonComputedVisibleKeyFieldsDialog.fragment.xml +1 -1
- package/src/sap/fe/core/controls/filterbar/FilterContainer.js +1 -1
- package/src/sap/fe/core/controls/filterbar/VisualFilter.js +1 -1
- package/src/sap/fe/core/controls/filterbar/VisualFilterContainer.js +1 -1
- package/src/sap/fe/core/controls/filterbar/utils/VisualFilterUtils.js +1 -1
- package/src/sap/fe/core/controls/massEdit/MassEditDialog.fragment.xml +106 -0
- package/src/sap/fe/core/controls/massEdit/MassEditHandlers.js +78 -0
- package/src/sap/fe/core/converters/ConverterContext.js +13 -1
- package/src/sap/fe/core/converters/ConverterContext.ts +10 -0
- package/src/sap/fe/core/converters/ManifestSettings.js +2 -1
- package/src/sap/fe/core/converters/ManifestSettings.ts +7 -1
- package/src/sap/fe/core/converters/ManifestWrapper.js +18 -7
- package/src/sap/fe/core/converters/ManifestWrapper.ts +15 -6
- package/src/sap/fe/core/converters/MetaModelConverter.js +920 -882
- package/src/sap/fe/core/converters/MetaModelConverter.ts +829 -853
- package/src/sap/fe/core/converters/annotations/DataField.js +54 -4
- package/src/sap/fe/core/converters/annotations/DataField.ts +53 -3
- package/src/sap/fe/core/converters/common/AnnotationConverter.js +83 -48
- package/src/sap/fe/core/converters/controls/Common/Action.js +15 -3
- package/src/sap/fe/core/converters/controls/Common/Action.ts +12 -3
- package/src/sap/fe/core/converters/controls/Common/Chart.js +1 -3
- package/src/sap/fe/core/converters/controls/Common/Chart.ts +0 -2
- package/src/sap/fe/core/converters/controls/Common/Form.js +68 -21
- package/src/sap/fe/core/converters/controls/Common/Form.ts +60 -16
- package/src/sap/fe/core/converters/controls/Common/KPI.js +331 -248
- package/src/sap/fe/core/converters/controls/Common/KPI.ts +355 -287
- package/src/sap/fe/core/converters/controls/Common/Table.js +426 -332
- package/src/sap/fe/core/converters/controls/Common/Table.ts +516 -383
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.js +468 -0
- package/src/sap/fe/core/converters/controls/Common/table/StandardActions.ts +609 -0
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.js +30 -13
- package/src/sap/fe/core/converters/controls/ListReport/FilterBar.ts +31 -12
- package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.js +2 -2
- package/src/sap/fe/core/converters/controls/ListReport/VisualFilters.ts +1 -1
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.js +15 -7
- package/src/sap/fe/core/converters/controls/ObjectPage/SubSection.ts +27 -6
- package/src/sap/fe/core/converters/helpers/Aggregation.js +8 -1
- package/src/sap/fe/core/converters/helpers/Aggregation.ts +9 -1
- package/src/sap/fe/core/converters/helpers/BindingHelper.js +3 -2
- package/src/sap/fe/core/converters/helpers/BindingHelper.ts +2 -2
- package/src/sap/fe/core/converters/helpers/ID.js +9 -1
- package/src/sap/fe/core/converters/helpers/ID.ts +6 -2
- package/src/sap/fe/core/converters/helpers/IssueManager.js +7 -5
- package/src/sap/fe/core/converters/helpers/IssueManager.ts +6 -4
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.js +2 -2
- package/src/sap/fe/core/converters/objectPage/HeaderAndFooterAction.ts +1 -1
- package/src/sap/fe/core/converters/templates/ListReportConverter.js +34 -4
- package/src/sap/fe/core/converters/templates/ListReportConverter.ts +36 -7
- package/src/sap/fe/core/converters/templates/ObjectPageConverter.js +2 -5
- package/src/sap/fe/core/converters/templates/ObjectPageConverter.ts +1 -2
- package/src/sap/fe/core/designtime/AppComponent.designtime.js +11 -2
- package/src/sap/fe/core/formatters/FPMFormatter.js +1 -1
- package/src/sap/fe/core/formatters/FPMFormatter.ts +8 -3
- package/src/sap/fe/core/formatters/TableFormatter.js +27 -4
- package/src/sap/fe/core/formatters/TableFormatter.ts +20 -3
- package/src/sap/fe/core/formatters/ValueFormatter.js +30 -5
- package/src/sap/fe/core/formatters/ValueFormatter.ts +25 -3
- package/src/sap/fe/core/fpm/Component.js +2 -2
- package/src/sap/fe/core/helpers/AppStartupHelper.js +359 -0
- package/src/sap/fe/core/helpers/AppStartupHelper.ts +388 -0
- package/src/sap/fe/core/helpers/BindingExpression.js +199 -111
- package/src/sap/fe/core/helpers/BindingExpression.ts +193 -102
- package/src/sap/fe/core/helpers/DynamicAnnotationPathHelper.js +1 -1
- package/src/sap/fe/core/helpers/EditState.js +1 -1
- package/src/sap/fe/core/helpers/ExcelFormatHelper.js +1 -3
- package/src/sap/fe/core/helpers/FPMHelper.js +1 -1
- package/src/sap/fe/core/helpers/KeepAliveHelper.js +211 -0
- package/src/sap/fe/core/helpers/KeepAliveHelper.ts +202 -0
- package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.js +32 -0
- package/src/sap/fe/core/helpers/KeepAliveRefreshTypes.ts +36 -0
- package/src/sap/fe/core/helpers/MassEditHelper.js +678 -0
- package/src/sap/fe/core/helpers/ModelHelper.js +64 -1
- package/src/sap/fe/core/helpers/PasteHelper.js +7 -1
- package/src/sap/fe/core/helpers/SemanticDateOperators.js +1 -1
- package/src/sap/fe/core/helpers/SemanticKeyHelper.js +1 -1
- package/src/sap/fe/core/helpers/StableIdHelper.js +2 -2
- package/src/sap/fe/core/helpers/StableIdHelper.ts +1 -1
- package/src/sap/fe/core/library.js +28 -2
- package/src/sap/fe/core/library.support.js +10 -4
- package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.js +62 -0
- package/src/sap/fe/core/manifestMerger/ChangePageConfiguration.ts +66 -0
- package/src/sap/fe/core/messagebundle.properties +67 -3
- package/src/sap/fe/core/messagebundle_ar.properties +40 -3
- package/src/sap/fe/core/messagebundle_bg.properties +40 -3
- package/src/sap/fe/core/messagebundle_ca.properties +41 -4
- package/src/sap/fe/core/messagebundle_cs.properties +41 -4
- package/src/sap/fe/core/messagebundle_cy.properties +40 -3
- package/src/sap/fe/core/messagebundle_da.properties +40 -3
- package/src/sap/fe/core/messagebundle_de.properties +40 -3
- package/src/sap/fe/core/messagebundle_el.properties +40 -3
- package/src/sap/fe/core/messagebundle_en.properties +37 -0
- package/src/sap/fe/core/messagebundle_en_GB.properties +37 -0
- package/src/sap/fe/core/messagebundle_en_US_sappsd.properties +37 -0
- package/src/sap/fe/core/messagebundle_en_US_saprigi.properties +46 -2
- package/src/sap/fe/core/messagebundle_en_US_saptrc.properties +44 -0
- package/src/sap/fe/core/messagebundle_es.properties +40 -3
- package/src/sap/fe/core/messagebundle_es_MX.properties +41 -4
- package/src/sap/fe/core/messagebundle_et.properties +40 -3
- package/src/sap/fe/core/messagebundle_fi.properties +40 -3
- package/src/sap/fe/core/messagebundle_fr.properties +41 -4
- package/src/sap/fe/core/messagebundle_fr_CA.properties +40 -3
- package/src/sap/fe/core/messagebundle_hi.properties +40 -3
- package/src/sap/fe/core/messagebundle_hr.properties +40 -3
- package/src/sap/fe/core/messagebundle_hu.properties +41 -4
- package/src/sap/fe/core/messagebundle_id.properties +42 -5
- package/src/sap/fe/core/messagebundle_it.properties +40 -3
- package/src/sap/fe/core/messagebundle_iw.properties +40 -3
- package/src/sap/fe/core/messagebundle_ja.properties +49 -12
- package/src/sap/fe/core/messagebundle_kk.properties +40 -3
- package/src/sap/fe/core/messagebundle_ko.properties +40 -3
- package/src/sap/fe/core/messagebundle_lt.properties +40 -3
- package/src/sap/fe/core/messagebundle_lv.properties +40 -3
- package/src/sap/fe/core/messagebundle_ms.properties +40 -3
- package/src/sap/fe/core/messagebundle_nl.properties +40 -3
- package/src/sap/fe/core/messagebundle_no.properties +40 -3
- package/src/sap/fe/core/messagebundle_pl.properties +40 -3
- package/src/sap/fe/core/messagebundle_pt.properties +42 -5
- package/src/sap/fe/core/messagebundle_pt_PT.properties +40 -3
- package/src/sap/fe/core/messagebundle_ro.properties +40 -3
- package/src/sap/fe/core/messagebundle_ru.properties +40 -3
- package/src/sap/fe/core/messagebundle_sh.properties +40 -3
- package/src/sap/fe/core/messagebundle_sk.properties +40 -3
- package/src/sap/fe/core/messagebundle_sl.properties +40 -3
- package/src/sap/fe/core/messagebundle_sv.properties +41 -4
- package/src/sap/fe/core/messagebundle_th.properties +40 -3
- package/src/sap/fe/core/messagebundle_tr.properties +40 -3
- package/src/sap/fe/core/messagebundle_uk.properties +40 -3
- package/src/sap/fe/core/messagebundle_vi.properties +40 -3
- package/src/sap/fe/core/messagebundle_zh_CN.properties +40 -3
- package/src/sap/fe/core/messagebundle_zh_TW.properties +40 -3
- package/src/sap/fe/core/services/AsyncComponentServiceFactory.js +1 -1
- package/src/sap/fe/core/services/CacheHandlerServiceFactory.js +1 -1
- package/src/sap/fe/core/services/EnvironmentServiceFactory.js +4 -3
- package/src/sap/fe/core/services/EnvironmentServiceFactory.ts +3 -0
- package/src/sap/fe/core/services/NavigationServiceFactory.js +1 -1
- package/src/sap/fe/core/services/ResourceModelServiceFactory.js +1 -1
- package/src/sap/fe/core/services/RoutingServiceFactory.js +98 -328
- package/src/sap/fe/core/services/ShellServicesFactory.js +31 -2
- package/src/sap/fe/core/services/ShellServicesFactory.ts +30 -1
- package/src/sap/fe/core/services/SideEffectsServiceFactory.js +8 -5
- package/src/sap/fe/core/services/SideEffectsServiceFactory.ts +11 -6
- package/src/sap/fe/core/services/TemplatedViewServiceFactory.js +14 -5
- package/src/sap/fe/core/services/view/TemplatingErrorPage.controller.js +1 -1
- package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.js +38 -0
- package/src/sap/fe/core/support/InvalidAnnotationColumnKey.support.ts +18 -0
- package/src/sap/fe/core/templating/DataModelPathHelper.js +8 -37
- package/src/sap/fe/core/templating/DataModelPathHelper.ts +13 -33
- package/src/sap/fe/core/templating/DisplayModeFormatter.js +114 -0
- package/src/sap/fe/core/templating/DisplayModeFormatter.ts +86 -0
- package/src/sap/fe/core/templating/EntitySetHelper.js +86 -3
- package/src/sap/fe/core/templating/EntitySetHelper.ts +44 -0
- package/src/sap/fe/core/templating/FilterHelper.js +10 -7
- package/src/sap/fe/core/templating/FilterHelper.ts +8 -6
- package/src/sap/fe/core/templating/PropertyHelper.js +2 -2
- package/src/sap/fe/core/templating/PropertyHelper.ts +1 -1
- package/src/sap/fe/core/templating/UIFormatters.js +47 -107
- package/src/sap/fe/core/templating/UIFormatters.ts +76 -72
|
@@ -2,53 +2,34 @@ import { ControllerExtension } from "sap/ui/core/mvc";
|
|
|
2
2
|
import { ControllerExtensionMetadata } from "sap/fe/core/controllerextensions";
|
|
3
3
|
import { UI5Class, Override, Public } from "../helpers/ClassSupport";
|
|
4
4
|
import { JSONModel } from "sap/ui/model/json";
|
|
5
|
+
import { ODataModel, Context } from "sap/ui/model/odata/v4";
|
|
5
6
|
import { Log } from "sap/base";
|
|
6
|
-
import { KPIDefinition } from "sap/fe/core/converters/controls/Common/KPI";
|
|
7
|
-
import {
|
|
8
|
-
import { Context } from "sap/ui/model/odata/v4";
|
|
7
|
+
import { KPIChartDefinition, KPIDefinition, NavigationInfo } from "sap/fe/core/converters/controls/Common/KPI";
|
|
8
|
+
import { BaseController } from "sap/fe/core";
|
|
9
9
|
import { MessageType } from "sap/fe/core/formatters/TableFormatterTypes";
|
|
10
10
|
import { FilterDefinition, RangeDefinition } from "sap/fe/core/converters/helpers/SelectionVariantHelper";
|
|
11
11
|
import { NumberFormat, DateFormat } from "sap/ui/core/format";
|
|
12
12
|
import { Locale } from "sap/ui/core";
|
|
13
|
-
import { Filter, FilterOperator } from "sap/ui/model";
|
|
13
|
+
import { Filter, FilterOperator, Sorter } from "sap/ui/model";
|
|
14
14
|
import { GenericTag, Popover } from "sap/m";
|
|
15
|
-
import { Card } from "sap/ui/integration/widgets";
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
case 2:
|
|
32
|
-
case "2":
|
|
33
|
-
criticalityProperty = MessageType.Warning;
|
|
34
|
-
break;
|
|
35
|
-
case 3:
|
|
36
|
-
case "3":
|
|
37
|
-
criticalityProperty = MessageType.Success;
|
|
38
|
-
break;
|
|
39
|
-
case 5:
|
|
40
|
-
case "5":
|
|
41
|
-
criticalityProperty = MessageType.Information;
|
|
42
|
-
break;
|
|
43
|
-
default:
|
|
44
|
-
criticalityProperty = MessageType.None;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return criticalityProperty;
|
|
48
|
-
}
|
|
16
|
+
const MessageTypeFromCriticality: Record<string, MessageType> = {
|
|
17
|
+
"1": MessageType.Error,
|
|
18
|
+
"2": MessageType.Warning,
|
|
19
|
+
"3": MessageType.Success,
|
|
20
|
+
"5": MessageType.Information
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const ValueColorFromMessageType: Record<MessageType, string> = {
|
|
24
|
+
Error: "Error",
|
|
25
|
+
Warning: "Critical",
|
|
26
|
+
Success: "Good",
|
|
27
|
+
Information: "None",
|
|
28
|
+
None: "None"
|
|
29
|
+
};
|
|
49
30
|
|
|
50
31
|
/**
|
|
51
|
-
* Function to
|
|
32
|
+
* Function to get a message state from a calculated criticality of type 'Target'.
|
|
52
33
|
*
|
|
53
34
|
* @param {number} kpiValue The value of the KPI to be tested against.
|
|
54
35
|
* @param {number[]} aThresholds Thresholds to be used [DeviationRangeLowValue,ToleranceRangeLowValue,AcceptanceRangeLowValue,AcceptanceRangeHighValue,ToleranceRangeHighValue,DeviationRangeHighValue].
|
|
@@ -77,7 +58,7 @@ function messageTypeFromTargetCalculation(kpiValue: number, aThresholds: (number
|
|
|
77
58
|
}
|
|
78
59
|
|
|
79
60
|
/**
|
|
80
|
-
* Function to
|
|
61
|
+
* Function to get a message state from a calculated criticality of type 'Minimize'.
|
|
81
62
|
*
|
|
82
63
|
* @param {number} kpiValue The value of the KPI to be tested against.
|
|
83
64
|
* @param {number[]} aThresholds Thresholds to be used [AcceptanceRangeHighValue,ToleranceRangeHighValue,DeviationRangeHighValue].
|
|
@@ -100,29 +81,7 @@ function messageTypeFromMinimizeCalculation(kpiValue: number, aThresholds: (numb
|
|
|
100
81
|
}
|
|
101
82
|
|
|
102
83
|
/**
|
|
103
|
-
* Function to
|
|
104
|
-
*
|
|
105
|
-
* @param messageType The message type
|
|
106
|
-
* @returns The ValueColor
|
|
107
|
-
*/
|
|
108
|
-
function valueColorFromMessageType(messageType: MessageType): string {
|
|
109
|
-
switch (messageType) {
|
|
110
|
-
case MessageType.Error:
|
|
111
|
-
return "Error";
|
|
112
|
-
|
|
113
|
-
case MessageType.Warning:
|
|
114
|
-
return "Critical";
|
|
115
|
-
|
|
116
|
-
case MessageType.Success:
|
|
117
|
-
return "Good";
|
|
118
|
-
|
|
119
|
-
default:
|
|
120
|
-
return "None";
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Function to calculate the message state for a criticality calculation of type 'Maximize'.
|
|
84
|
+
* Function to get a message state from a calculated criticality of type 'Maximize'.
|
|
126
85
|
*
|
|
127
86
|
* @param {number} kpiValue The value of the KPI to be tested against.
|
|
128
87
|
* @param {number[]} aThresholds Thresholds to be used [DeviationRangeLowValue,ToleranceRangeLowValue,AcceptanceRangeLowValue].
|
|
@@ -303,8 +262,299 @@ function getFilterStringFromDefinition(filterDefinition: FilterDefinition): stri
|
|
|
303
262
|
}
|
|
304
263
|
}
|
|
305
264
|
|
|
265
|
+
function formatChartTitle(kpiDef: KPIDefinition): string {
|
|
266
|
+
const resBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core");
|
|
267
|
+
|
|
268
|
+
function formatList(items: { name: string; label: string }[]) {
|
|
269
|
+
if (items.length === 0) {
|
|
270
|
+
return "";
|
|
271
|
+
} else if (items.length === 1) {
|
|
272
|
+
return items[0].label;
|
|
273
|
+
} else {
|
|
274
|
+
let res = items[0].label;
|
|
275
|
+
for (let I = 1; I < items.length - 1; I++) {
|
|
276
|
+
res += ", " + items[I].label;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return resBundle.getText("C_KPICARD_ITEMSLIST", [res, items[items.length - 1].label]);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return resBundle.getText("C_KPICARD_CHARTTITLE", [formatList(kpiDef.chart.measures), formatList(kpiDef.chart.dimensions)]);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function updateChartLabelSettings(chartDefinition: KPIChartDefinition, oChartProperties: any): void {
|
|
287
|
+
switch (chartDefinition.chartType) {
|
|
288
|
+
case "Donut":
|
|
289
|
+
// Show data labels, do not show axis titles
|
|
290
|
+
oChartProperties.categoryAxis = {
|
|
291
|
+
title: {
|
|
292
|
+
visible: false
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
oChartProperties.valueAxis = {
|
|
296
|
+
title: {
|
|
297
|
+
visible: false
|
|
298
|
+
},
|
|
299
|
+
label: {
|
|
300
|
+
formatString: "ShortFloat"
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
oChartProperties.plotArea.dataLabel = {
|
|
304
|
+
visible: true,
|
|
305
|
+
type: "value",
|
|
306
|
+
formatString: "ShortFloat_MFD2"
|
|
307
|
+
};
|
|
308
|
+
break;
|
|
309
|
+
|
|
310
|
+
case "bubble":
|
|
311
|
+
// Show axis title, bubble size legend, do not show data labels
|
|
312
|
+
oChartProperties.valueAxis = {
|
|
313
|
+
title: {
|
|
314
|
+
visible: true
|
|
315
|
+
},
|
|
316
|
+
label: {
|
|
317
|
+
formatString: "ShortFloat"
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
oChartProperties.valueAxis2 = {
|
|
321
|
+
title: {
|
|
322
|
+
visible: true
|
|
323
|
+
},
|
|
324
|
+
label: {
|
|
325
|
+
formatString: "ShortFloat"
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
oChartProperties.legendGroup = {
|
|
329
|
+
layout: {
|
|
330
|
+
position: "bottom",
|
|
331
|
+
alignment: "topLeft"
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
oChartProperties.sizeLegend = {
|
|
335
|
+
visible: true
|
|
336
|
+
};
|
|
337
|
+
oChartProperties.plotArea.dataLabel = { visible: false };
|
|
338
|
+
break;
|
|
339
|
+
|
|
340
|
+
case "scatter":
|
|
341
|
+
// Do not show data labels and axis titles
|
|
342
|
+
oChartProperties.valueAxis = {
|
|
343
|
+
title: {
|
|
344
|
+
visible: false
|
|
345
|
+
},
|
|
346
|
+
label: {
|
|
347
|
+
formatString: "ShortFloat"
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
oChartProperties.valueAxis2 = {
|
|
351
|
+
title: {
|
|
352
|
+
visible: false
|
|
353
|
+
},
|
|
354
|
+
label: {
|
|
355
|
+
formatString: "ShortFloat"
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
oChartProperties.plotArea.dataLabel = { visible: false };
|
|
359
|
+
break;
|
|
360
|
+
|
|
361
|
+
default:
|
|
362
|
+
// Do not show data labels and axis titles
|
|
363
|
+
oChartProperties.categoryAxis = {
|
|
364
|
+
title: {
|
|
365
|
+
visible: false
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
oChartProperties.valueAxis = {
|
|
369
|
+
title: {
|
|
370
|
+
visible: false
|
|
371
|
+
},
|
|
372
|
+
label: {
|
|
373
|
+
formatString: "ShortFloat"
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
oChartProperties.plotArea.dataLabel = { visible: false };
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function filterMap(aObjects: { name: string; label: string; role?: string }[], aRoles?: (string | undefined)[]): string[] {
|
|
380
|
+
if (aRoles && aRoles.length) {
|
|
381
|
+
return aObjects
|
|
382
|
+
.filter(dimension => {
|
|
383
|
+
return aRoles.indexOf(dimension.role) >= 0;
|
|
384
|
+
})
|
|
385
|
+
.map(dimension => {
|
|
386
|
+
return dimension.label;
|
|
387
|
+
});
|
|
388
|
+
} else {
|
|
389
|
+
return aObjects.map(dimension => {
|
|
390
|
+
return dimension.label;
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function getScatterBubbleChartFeeds(chartDefinition: KPIChartDefinition): { uid: string; type: string; values: string[] }[] {
|
|
396
|
+
const axis1Measures = filterMap(chartDefinition.measures, ["Axis1"]);
|
|
397
|
+
const axis2Measures = filterMap(chartDefinition.measures, ["Axis2"]);
|
|
398
|
+
const axis3Measures = filterMap(chartDefinition.measures, ["Axis3"]);
|
|
399
|
+
const otherMeasures = filterMap(chartDefinition.measures, [undefined]);
|
|
400
|
+
const seriesDimensions = filterMap(chartDefinition.dimensions, ["Series"]);
|
|
401
|
+
|
|
402
|
+
// Get the first dimension with role "Category" for the shape
|
|
403
|
+
const shapeDimension = chartDefinition.dimensions.find(dimension => {
|
|
404
|
+
return dimension.role === "Category";
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
// Measure for the x-Axis : first measure for Axis1, or for Axis2 if not found, or for Axis3 if not found
|
|
408
|
+
const xMeasure = axis1Measures.shift() || axis2Measures.shift() || axis3Measures.shift() || otherMeasures.shift() || "";
|
|
409
|
+
// Measure for the y-Axis : first measure for Axis2, or second measure for Axis1 if not found, or first measure for Axis3 if not found
|
|
410
|
+
const yMeasure = axis2Measures.shift() || axis1Measures.shift() || axis3Measures.shift() || otherMeasures.shift() || "";
|
|
411
|
+
const res = [
|
|
412
|
+
{
|
|
413
|
+
"uid": "valueAxis",
|
|
414
|
+
"type": "Measure",
|
|
415
|
+
"values": [xMeasure]
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
"uid": "valueAxis2",
|
|
419
|
+
"type": "Measure",
|
|
420
|
+
"values": [yMeasure]
|
|
421
|
+
}
|
|
422
|
+
];
|
|
423
|
+
|
|
424
|
+
if (chartDefinition.chartType === "bubble") {
|
|
425
|
+
// Measure for the size of the bubble: first measure for Axis3, or remaining measure for Axis1/Axis2 if not found
|
|
426
|
+
const sizeMeasure = axis3Measures.shift() || axis1Measures.shift() || axis2Measures.shift() || otherMeasures.shift() || "";
|
|
427
|
+
res.push({
|
|
428
|
+
"uid": "bubbleWidth",
|
|
429
|
+
"type": "Measure",
|
|
430
|
+
"values": [sizeMeasure]
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Color (optional)
|
|
435
|
+
if (seriesDimensions.length) {
|
|
436
|
+
res.push({
|
|
437
|
+
"uid": "color",
|
|
438
|
+
"type": "Dimension",
|
|
439
|
+
"values": seriesDimensions
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
// Shape (optional)
|
|
443
|
+
if (shapeDimension) {
|
|
444
|
+
res.push({
|
|
445
|
+
"uid": "shape",
|
|
446
|
+
"type": "Dimension",
|
|
447
|
+
"values": [shapeDimension.label]
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
return res;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function getChartFeeds(chartDefinition: KPIChartDefinition): { uid: string; type: string; values: string[] }[] {
|
|
454
|
+
let res: { uid: string; type: string; values: string[] }[];
|
|
455
|
+
|
|
456
|
+
switch (chartDefinition.chartType) {
|
|
457
|
+
case "Donut":
|
|
458
|
+
res = [
|
|
459
|
+
{
|
|
460
|
+
"uid": "size",
|
|
461
|
+
"type": "Measure",
|
|
462
|
+
"values": filterMap(chartDefinition.measures)
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"uid": "color",
|
|
466
|
+
"type": "Dimension",
|
|
467
|
+
"values": filterMap(chartDefinition.dimensions)
|
|
468
|
+
}
|
|
469
|
+
];
|
|
470
|
+
break;
|
|
471
|
+
|
|
472
|
+
case "bubble":
|
|
473
|
+
case "scatter":
|
|
474
|
+
res = getScatterBubbleChartFeeds(chartDefinition);
|
|
475
|
+
break;
|
|
476
|
+
|
|
477
|
+
case "vertical_bullet":
|
|
478
|
+
res = [
|
|
479
|
+
{
|
|
480
|
+
"uid": "actualValues",
|
|
481
|
+
"type": "Measure",
|
|
482
|
+
"values": filterMap(chartDefinition.measures, [undefined, "Axis1"])
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
"uid": "targetValues",
|
|
486
|
+
"type": "Measure",
|
|
487
|
+
"values": filterMap(chartDefinition.measures, ["Axis2"])
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"uid": "categoryAxis",
|
|
491
|
+
"type": "Dimension",
|
|
492
|
+
"values": filterMap(chartDefinition.dimensions, [undefined, "Category"])
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
"uid": "color",
|
|
496
|
+
"type": "Dimension",
|
|
497
|
+
"values": filterMap(chartDefinition.dimensions, ["Series"])
|
|
498
|
+
}
|
|
499
|
+
];
|
|
500
|
+
break;
|
|
501
|
+
|
|
502
|
+
default:
|
|
503
|
+
res = [
|
|
504
|
+
{
|
|
505
|
+
"uid": "valueAxis",
|
|
506
|
+
"type": "Measure",
|
|
507
|
+
"values": filterMap(chartDefinition.measures)
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
"uid": "categoryAxis",
|
|
511
|
+
"type": "Dimension",
|
|
512
|
+
"values": filterMap(chartDefinition.dimensions, [undefined, "Category"])
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"uid": "color",
|
|
516
|
+
"type": "Dimension",
|
|
517
|
+
"values": filterMap(chartDefinition.dimensions, ["Series"])
|
|
518
|
+
}
|
|
519
|
+
];
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return res;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function getNavigationParameters(
|
|
526
|
+
navInfo: NavigationInfo,
|
|
527
|
+
oShellService: any
|
|
528
|
+
): Promise<{ semanticObject?: string; action?: string; outbound?: string } | undefined> {
|
|
529
|
+
if (navInfo.semanticObject) {
|
|
530
|
+
if (navInfo.action) {
|
|
531
|
+
// Action is already specified: check if it's available in the shell
|
|
532
|
+
return oShellService.getLinks({ semanticObject: navInfo.semanticObject, action: navInfo.action }).then((aLinks: any[]) => {
|
|
533
|
+
return aLinks.length ? { semanticObject: navInfo.semanticObject, action: navInfo.action } : undefined;
|
|
534
|
+
});
|
|
535
|
+
} else {
|
|
536
|
+
// We get the primary intent from the shell
|
|
537
|
+
return oShellService.getPrimaryIntent(navInfo.semanticObject).then((oLink: any) => {
|
|
538
|
+
if (!oLink) {
|
|
539
|
+
// No primary intent...
|
|
540
|
+
return undefined;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Check that the primary intent is not part of the unavailable actions
|
|
544
|
+
const oInfo = oShellService.parseShellHash(oLink.intent);
|
|
545
|
+
return navInfo.unavailableActions && navInfo.unavailableActions.indexOf(oInfo.action) >= 0
|
|
546
|
+
? undefined
|
|
547
|
+
: { semanticObject: oInfo.semanticObject, action: oInfo.action };
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
} else {
|
|
551
|
+
// Outbound navigation specified in the manifest
|
|
552
|
+
return navInfo.outboundNavigation ? Promise.resolve({ outbound: navInfo.outboundNavigation }) : Promise.resolve(undefined);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
306
556
|
/**
|
|
307
|
-
* @class A controller extension for managing
|
|
557
|
+
* @class A controller extension for managing the KPIs in an analytical list page
|
|
308
558
|
*
|
|
309
559
|
* @name sap.fe.core.controllerextensions.KPIManagement
|
|
310
560
|
* @hideconstructor
|
|
@@ -315,17 +565,131 @@ function getFilterStringFromDefinition(filterDefinition: FilterDefinition): stri
|
|
|
315
565
|
@UI5Class("sap.fe.core.controllerextensions.KPIManagement", ControllerExtensionMetadata)
|
|
316
566
|
class KPIManagementControllerExtension extends ControllerExtension {
|
|
317
567
|
protected aKPIDefinitions?: KPIDefinition[];
|
|
318
|
-
protected
|
|
319
|
-
protected oCard!: Card;
|
|
568
|
+
protected oCard: any;
|
|
320
569
|
protected oPopover!: Popover;
|
|
321
570
|
|
|
571
|
+
/**
|
|
572
|
+
* Creates the card manifest for a KPI definition and stores it in a JSON model.
|
|
573
|
+
*
|
|
574
|
+
* @param kpiDefinition The KPI definition
|
|
575
|
+
* @param oKPIModel The JSON model in which the manifest will be stored
|
|
576
|
+
*/
|
|
577
|
+
protected initCardManifest(kpiDefinition: KPIDefinition, oKPIModel: JSONModel<any>): void {
|
|
578
|
+
const oCardManifest: any = {
|
|
579
|
+
"sap.app": {
|
|
580
|
+
id: "sap.fe",
|
|
581
|
+
type: "card"
|
|
582
|
+
},
|
|
583
|
+
"sap.ui": {
|
|
584
|
+
technology: "UI5"
|
|
585
|
+
},
|
|
586
|
+
"sap.card": {
|
|
587
|
+
type: "Analytical",
|
|
588
|
+
data: {
|
|
589
|
+
json: {}
|
|
590
|
+
},
|
|
591
|
+
header: {
|
|
592
|
+
type: "Numeric",
|
|
593
|
+
title: kpiDefinition.datapoint.title,
|
|
594
|
+
subTitle: kpiDefinition.datapoint.description,
|
|
595
|
+
unitOfMeasurement: "{mainUnit}",
|
|
596
|
+
mainIndicator: {
|
|
597
|
+
number: "{mainValueNoScale}",
|
|
598
|
+
unit: "{mainValueScale}",
|
|
599
|
+
state: "{mainState}",
|
|
600
|
+
trend: "{trend}"
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
content: {
|
|
604
|
+
minHeight: "25rem",
|
|
605
|
+
chartProperties: {
|
|
606
|
+
plotArea: {},
|
|
607
|
+
title: {
|
|
608
|
+
visible: true,
|
|
609
|
+
alignment: "left"
|
|
610
|
+
}
|
|
611
|
+
},
|
|
612
|
+
data: {
|
|
613
|
+
path: "/chartData"
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
// Add side indicators in the card header if a target is defined for the KPI
|
|
620
|
+
if (kpiDefinition.datapoint.targetPath || kpiDefinition.datapoint.targetValue !== undefined) {
|
|
621
|
+
const resBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core");
|
|
622
|
+
oCardManifest["sap.card"].header.sideIndicators = [
|
|
623
|
+
{
|
|
624
|
+
title: resBundle.getText("C_KPICARD_INDICATOR_TARGET"),
|
|
625
|
+
number: "{targetNumber}",
|
|
626
|
+
unit: "{targetUnit}"
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
title: resBundle.getText("C_KPICARD_INDICATOR_DEVIATION"),
|
|
630
|
+
number: "{deviationNumber}",
|
|
631
|
+
unit: "%"
|
|
632
|
+
}
|
|
633
|
+
];
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Details of the card: filter descriptions
|
|
637
|
+
if (kpiDefinition.selectionVariantFilterDefinitions?.length) {
|
|
638
|
+
const aDescriptions: string[] = [];
|
|
639
|
+
kpiDefinition.selectionVariantFilterDefinitions.forEach(filterDefinition => {
|
|
640
|
+
const desc = getFilterStringFromDefinition(filterDefinition);
|
|
641
|
+
if (desc) {
|
|
642
|
+
aDescriptions.push(desc);
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
if (aDescriptions.length) {
|
|
647
|
+
oCardManifest["sap.card"].header.details = aDescriptions.join(", ");
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Chart settings: type, title, dimensions and measures in the manifest
|
|
652
|
+
oCardManifest["sap.card"].content.chartType = kpiDefinition.chart.chartType;
|
|
653
|
+
updateChartLabelSettings(kpiDefinition.chart, oCardManifest["sap.card"].content.chartProperties);
|
|
654
|
+
oCardManifest["sap.card"].content.chartProperties.title.text = formatChartTitle(kpiDefinition);
|
|
655
|
+
oCardManifest["sap.card"].content.dimensions = kpiDefinition.chart.dimensions.map(dimension => {
|
|
656
|
+
return { label: dimension.label, value: "{" + dimension.name + "}" };
|
|
657
|
+
});
|
|
658
|
+
oCardManifest["sap.card"].content.measures = kpiDefinition.chart.measures.map(measure => {
|
|
659
|
+
return { label: measure.label, value: "{" + measure.name + "}" };
|
|
660
|
+
});
|
|
661
|
+
oCardManifest["sap.card"].content.feeds = getChartFeeds(kpiDefinition.chart);
|
|
662
|
+
|
|
663
|
+
oKPIModel.setProperty("/" + kpiDefinition.id, {
|
|
664
|
+
manifest: oCardManifest
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
protected initNavigationInfo(kpiDefinition: KPIDefinition, oKPIModel: JSONModel<any>, oShellService: any): Promise<void> {
|
|
669
|
+
// Add navigation
|
|
670
|
+
if (kpiDefinition.navigation) {
|
|
671
|
+
return getNavigationParameters(kpiDefinition.navigation, oShellService).then(oNavInfo => {
|
|
672
|
+
if (oNavInfo) {
|
|
673
|
+
oKPIModel.setProperty("/" + kpiDefinition.id + "/manifest/sap.card/header/actions", [
|
|
674
|
+
{
|
|
675
|
+
type: "Navigation",
|
|
676
|
+
parameters: oNavInfo
|
|
677
|
+
}
|
|
678
|
+
]);
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
} else {
|
|
682
|
+
return Promise.resolve();
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
322
686
|
@Override()
|
|
323
687
|
public onInit(): void {
|
|
324
688
|
this.aKPIDefinitions = this.getKPIData();
|
|
325
689
|
|
|
326
690
|
if (this.aKPIDefinitions && this.aKPIDefinitions.length) {
|
|
327
691
|
const oView = this.getView();
|
|
328
|
-
|
|
692
|
+
const oAppComponent = (oView.getController() as BaseController).getAppComponent() as any;
|
|
329
693
|
|
|
330
694
|
// Create a JSON model to store KPI data
|
|
331
695
|
const oKPIModel = new JSONModel();
|
|
@@ -333,101 +697,15 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
333
697
|
|
|
334
698
|
this.aKPIDefinitions.forEach(kpiDefinition => {
|
|
335
699
|
// Create the manifest for the KPI card and store it in the KPI model
|
|
336
|
-
|
|
337
|
-
"sap.app": {
|
|
338
|
-
id: "sap.fe",
|
|
339
|
-
type: "card"
|
|
340
|
-
},
|
|
341
|
-
"sap.ui": {
|
|
342
|
-
technology: "UI5"
|
|
343
|
-
},
|
|
344
|
-
"sap.card": {
|
|
345
|
-
type: "Analytical",
|
|
346
|
-
data: {
|
|
347
|
-
json: {}
|
|
348
|
-
},
|
|
349
|
-
header: {
|
|
350
|
-
type: "Numeric",
|
|
351
|
-
title: kpiDefinition.datapoint.title,
|
|
352
|
-
subTitle: kpiDefinition.datapoint.description,
|
|
353
|
-
unitOfMeasurement: "{mainUnit}",
|
|
354
|
-
mainIndicator: {
|
|
355
|
-
number: "{mainValueNoScale}",
|
|
356
|
-
unit: "{mainValueScale}",
|
|
357
|
-
state: "{mainState}",
|
|
358
|
-
trend: "{trend}"
|
|
359
|
-
}
|
|
360
|
-
},
|
|
361
|
-
content: {
|
|
362
|
-
plotArea: {
|
|
363
|
-
"dataLabel": {
|
|
364
|
-
"visible": false
|
|
365
|
-
},
|
|
366
|
-
"categoryAxisText": {
|
|
367
|
-
"visible": false
|
|
368
|
-
},
|
|
369
|
-
"valueAxisText": {
|
|
370
|
-
"visible": false
|
|
371
|
-
}
|
|
372
|
-
},
|
|
373
|
-
title: {
|
|
374
|
-
text: "{chartTitle}",
|
|
375
|
-
visible: true,
|
|
376
|
-
alignment: "Left"
|
|
377
|
-
},
|
|
378
|
-
measureAxis: "valueAxis",
|
|
379
|
-
dimensionAxis: "categoryAxis",
|
|
380
|
-
data: {
|
|
381
|
-
path: "/chartData"
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
// Add side indicators in the card header if a target is defined for the KPI
|
|
388
|
-
if (kpiDefinition.datapoint.targetPath || kpiDefinition.datapoint.targetValue !== undefined) {
|
|
389
|
-
const resBundle = sap.ui.getCore().getLibraryResourceBundle("sap.fe.core");
|
|
390
|
-
oCardManifest["sap.card"].header.sideIndicators = [
|
|
391
|
-
{
|
|
392
|
-
title: resBundle.getText("C_KPICARD_INDICATOR_TARGET"),
|
|
393
|
-
number: "{targetNumber}",
|
|
394
|
-
unit: "{targetUnit}"
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
title: resBundle.getText("C_KPICARD_INDICATOR_DEVIATION"),
|
|
398
|
-
number: "{deviationNumber}",
|
|
399
|
-
unit: "%"
|
|
400
|
-
}
|
|
401
|
-
];
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Details of the card: filter descriptions
|
|
405
|
-
if (kpiDefinition.selectionVariantFilterDefinitions?.length) {
|
|
406
|
-
const aDescriptions: string[] = [];
|
|
407
|
-
kpiDefinition.selectionVariantFilterDefinitions.forEach(filterDefinition => {
|
|
408
|
-
const desc = getFilterStringFromDefinition(filterDefinition);
|
|
409
|
-
if (desc) {
|
|
410
|
-
aDescriptions.push(desc);
|
|
411
|
-
}
|
|
412
|
-
});
|
|
700
|
+
this.initCardManifest(kpiDefinition, oKPIModel);
|
|
413
701
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Update card content in the manifest
|
|
420
|
-
oCardManifest["sap.card"].content = Object.assign(
|
|
421
|
-
oCardManifest["sap.card"].content,
|
|
422
|
-
kpiDefinition.card.cardContentManifest
|
|
423
|
-
);
|
|
424
|
-
|
|
425
|
-
oKPIModel.setProperty("/" + kpiDefinition.id, {
|
|
426
|
-
manifest: oCardManifest
|
|
702
|
+
// Set the navigation information in the manifest
|
|
703
|
+
this.initNavigationInfo(kpiDefinition, oKPIModel, oAppComponent.getShellServices()).catch(function(err: any) {
|
|
704
|
+
Log.error(err);
|
|
427
705
|
});
|
|
428
706
|
|
|
429
707
|
// Load tag data for the KPI
|
|
430
|
-
this.loadKPITagData(kpiDefinition).catch(function(err: any) {
|
|
708
|
+
this.loadKPITagData(kpiDefinition, oAppComponent.getModel() as ODataModel, oKPIModel).catch(function(err: any) {
|
|
431
709
|
Log.error(err);
|
|
432
710
|
});
|
|
433
711
|
});
|
|
@@ -436,7 +714,7 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
436
714
|
|
|
437
715
|
@Override()
|
|
438
716
|
public onExit(): void {
|
|
439
|
-
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel
|
|
717
|
+
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel<any>;
|
|
440
718
|
|
|
441
719
|
if (oKPIModel) {
|
|
442
720
|
oKPIModel.destroy();
|
|
@@ -459,7 +737,7 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
459
737
|
}
|
|
460
738
|
}
|
|
461
739
|
|
|
462
|
-
private updateDatapointValueAndCurrency(kpiDefinition: KPIDefinition, kpiContext: Context) {
|
|
740
|
+
private updateDatapointValueAndCurrency(kpiDefinition: KPIDefinition, kpiContext: Context, oKPIModel: JSONModel<any>) {
|
|
463
741
|
const currentLocale = new Locale(
|
|
464
742
|
sap.ui
|
|
465
743
|
.getCore()
|
|
@@ -471,7 +749,6 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
471
749
|
: kpiDefinition.datapoint.unit?.value;
|
|
472
750
|
|
|
473
751
|
const isPercentage = kpiDefinition.datapoint.unit?.isCurrency === false && rawUnit === "%";
|
|
474
|
-
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel;
|
|
475
752
|
|
|
476
753
|
// /////////////////////
|
|
477
754
|
// Main KPI value
|
|
@@ -537,9 +814,8 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
537
814
|
}
|
|
538
815
|
}
|
|
539
816
|
|
|
540
|
-
private updateDatapointCriticality(kpiDefinition: KPIDefinition, kpiContext: Context) {
|
|
817
|
+
private updateDatapointCriticality(kpiDefinition: KPIDefinition, kpiContext: Context, oKPIModel: JSONModel<any>) {
|
|
541
818
|
const rawValue = Number.parseFloat(kpiContext.getProperty(kpiDefinition.datapoint.propertyPath));
|
|
542
|
-
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel;
|
|
543
819
|
|
|
544
820
|
let criticalityValue = MessageType.None;
|
|
545
821
|
if (kpiDefinition.datapoint.criticalityValue) {
|
|
@@ -547,7 +823,8 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
547
823
|
criticalityValue = kpiDefinition.datapoint.criticalityValue;
|
|
548
824
|
} else if (kpiDefinition.datapoint.criticalityPath) {
|
|
549
825
|
// Criticality comes from another property (via a path)
|
|
550
|
-
criticalityValue =
|
|
826
|
+
criticalityValue =
|
|
827
|
+
MessageTypeFromCriticality[kpiContext.getProperty(kpiDefinition.datapoint.criticalityPath)] || MessageType.None;
|
|
551
828
|
} else if (kpiDefinition.datapoint.criticalityCalculationThresholds && kpiDefinition.datapoint.criticalityCalculationMode) {
|
|
552
829
|
// Criticality calculation
|
|
553
830
|
switch (kpiDefinition.datapoint.criticalityCalculationMode) {
|
|
@@ -575,13 +852,12 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
575
852
|
oKPIModel.setProperty("/" + kpiDefinition.id + "/manifest/sap.card/data/json/mainCriticality", criticalityValue);
|
|
576
853
|
oKPIModel.setProperty(
|
|
577
854
|
"/" + kpiDefinition.id + "/manifest/sap.card/data/json/mainState",
|
|
578
|
-
|
|
855
|
+
ValueColorFromMessageType[criticalityValue] || "None"
|
|
579
856
|
);
|
|
580
857
|
}
|
|
581
858
|
|
|
582
|
-
private updateDatapointTrend(kpiDefinition: KPIDefinition, kpiContext: Context) {
|
|
859
|
+
private updateDatapointTrend(kpiDefinition: KPIDefinition, kpiContext: Context, oKPIModel: JSONModel<any>) {
|
|
583
860
|
const rawValue = Number.parseFloat(kpiContext.getProperty(kpiDefinition.datapoint.propertyPath));
|
|
584
|
-
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel;
|
|
585
861
|
|
|
586
862
|
let trendValue = "None";
|
|
587
863
|
|
|
@@ -615,12 +891,11 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
615
891
|
oKPIModel.setProperty("/" + kpiDefinition.id + "/manifest/sap.card/data/json/trend", trendValue);
|
|
616
892
|
}
|
|
617
893
|
|
|
618
|
-
private updateTargetValue(kpiDefinition: KPIDefinition, kpiContext: Context) {
|
|
894
|
+
private updateTargetValue(kpiDefinition: KPIDefinition, kpiContext: Context, oKPIModel: JSONModel<any>) {
|
|
619
895
|
if (kpiDefinition.datapoint.targetValue === undefined && kpiDefinition.datapoint.targetPath === undefined) {
|
|
620
896
|
return; // No target set for the KPI
|
|
621
897
|
}
|
|
622
898
|
const rawValue = Number.parseFloat(kpiContext.getProperty(kpiDefinition.datapoint.propertyPath));
|
|
623
|
-
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel;
|
|
624
899
|
const currentLocale = new Locale(
|
|
625
900
|
sap.ui
|
|
626
901
|
.getCore()
|
|
@@ -678,13 +953,17 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
678
953
|
* Loads tag data for a KPI, and stores it in the JSON KPI model.
|
|
679
954
|
*
|
|
680
955
|
* @param {KPIDefinition} kpiDefinition The definition of the KPI.
|
|
956
|
+
* @param {ODataModel} oMainModel The model used to load the data.
|
|
957
|
+
* @param {JSONModel} oKPIModel The JSON model where the data will be stored
|
|
681
958
|
* @param loadFull If not true, loads only data for the KPI tag
|
|
682
|
-
* @returns {Promise} Returns the
|
|
959
|
+
* @returns {Promise} Returns the promise that is resolved when data is loaded.
|
|
683
960
|
*/
|
|
684
|
-
protected loadKPITagData(kpiDefinition: KPIDefinition, loadFull?: boolean): any {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
const oListBinding =
|
|
961
|
+
protected loadKPITagData(kpiDefinition: KPIDefinition, oMainModel: ODataModel, oKPIModel: JSONModel<any>, loadFull?: boolean): any {
|
|
962
|
+
// If loadFull=false, then we're just loading data for the tag and we use the "$auto.LongRunners" groupID
|
|
963
|
+
// If loadFull=true, we're loading data for the whole KPI (tag + card) and we use the default ("$auto") groupID
|
|
964
|
+
const oListBinding = loadFull
|
|
965
|
+
? oMainModel.bindList("/" + kpiDefinition.entitySet)
|
|
966
|
+
: oMainModel.bindList("/" + kpiDefinition.entitySet, undefined, undefined, undefined, { $$groupId: "$auto.LongRunners" });
|
|
688
967
|
const oAggregate: Record<string, { unit?: string }> = {};
|
|
689
968
|
|
|
690
969
|
// Main value + currency/unit
|
|
@@ -716,7 +995,9 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
716
995
|
|
|
717
996
|
// Manage SelectionVariant filters
|
|
718
997
|
if (kpiDefinition.selectionVariantFilterDefinitions?.length) {
|
|
719
|
-
const aFilters = kpiDefinition.selectionVariantFilterDefinitions.map(createFilterFromDefinition)
|
|
998
|
+
const aFilters = kpiDefinition.selectionVariantFilterDefinitions.map(createFilterFromDefinition).filter(filter => {
|
|
999
|
+
return filter !== undefined;
|
|
1000
|
+
}) as Filter[];
|
|
720
1001
|
oListBinding.filter(aFilters);
|
|
721
1002
|
}
|
|
722
1003
|
|
|
@@ -740,30 +1021,36 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
740
1021
|
oKPIModel.setProperty("/" + kpiDefinition.id + "/manifest/sap.card/data/json/targetUnit", undefined);
|
|
741
1022
|
oKPIModel.setProperty("/" + kpiDefinition.id + "/manifest/sap.card/data/json/deviationNumber", undefined);
|
|
742
1023
|
} else {
|
|
743
|
-
this.updateDatapointValueAndCurrency(kpiDefinition, aContexts[0]);
|
|
744
|
-
this.updateDatapointCriticality(kpiDefinition, aContexts[0]);
|
|
1024
|
+
this.updateDatapointValueAndCurrency(kpiDefinition, aContexts[0], oKPIModel);
|
|
1025
|
+
this.updateDatapointCriticality(kpiDefinition, aContexts[0], oKPIModel);
|
|
745
1026
|
|
|
746
1027
|
if (loadFull) {
|
|
747
|
-
this.updateDatapointTrend(kpiDefinition, aContexts[0]);
|
|
748
|
-
this.updateTargetValue(kpiDefinition, aContexts[0]);
|
|
1028
|
+
this.updateDatapointTrend(kpiDefinition, aContexts[0], oKPIModel);
|
|
1029
|
+
this.updateTargetValue(kpiDefinition, aContexts[0], oKPIModel);
|
|
749
1030
|
}
|
|
750
1031
|
}
|
|
751
1032
|
}
|
|
752
1033
|
});
|
|
753
1034
|
}
|
|
754
1035
|
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
1036
|
+
/**
|
|
1037
|
+
* Loads card data for a KPI, and stores it in the JSON KPI model.
|
|
1038
|
+
*
|
|
1039
|
+
* @param {KPIDefinition} kpiDefinition The definition of the KPI.
|
|
1040
|
+
* @param {ODataModel} oMainModel The model used to load the data.
|
|
1041
|
+
* @param {JSONModel} oKPIModel The JSON model where the data will be stored
|
|
1042
|
+
* @returns {Promise} Returns the promise that is resolved when data is loaded.
|
|
1043
|
+
*/
|
|
1044
|
+
protected loadKPICardData(kpiDefinition: KPIDefinition, oMainModel: ODataModel, oKPIModel: JSONModel<any>): any {
|
|
1045
|
+
const oListBinding = oMainModel.bindList("/" + kpiDefinition.entitySet);
|
|
758
1046
|
const oGroup: Record<string, Object> = {};
|
|
759
1047
|
const oAggregate: Record<string, Object> = {};
|
|
760
|
-
const oKPIModel = this.getView().getModel("kpiModel") as JSONModel;
|
|
761
1048
|
|
|
762
|
-
kpiDefinition.
|
|
763
|
-
oGroup[
|
|
1049
|
+
kpiDefinition.chart.dimensions.forEach(dimension => {
|
|
1050
|
+
oGroup[dimension.name] = {};
|
|
764
1051
|
});
|
|
765
|
-
kpiDefinition.
|
|
766
|
-
oAggregate[
|
|
1052
|
+
kpiDefinition.chart.measures.forEach(measure => {
|
|
1053
|
+
oAggregate[measure.name] = {};
|
|
767
1054
|
});
|
|
768
1055
|
oListBinding.setAggregation({
|
|
769
1056
|
group: oGroup,
|
|
@@ -772,18 +1059,29 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
772
1059
|
|
|
773
1060
|
// Manage SelectionVariant filters
|
|
774
1061
|
if (kpiDefinition.selectionVariantFilterDefinitions?.length) {
|
|
775
|
-
const aFilters = kpiDefinition.selectionVariantFilterDefinitions.map(createFilterFromDefinition)
|
|
1062
|
+
const aFilters = kpiDefinition.selectionVariantFilterDefinitions.map(createFilterFromDefinition).filter(filter => {
|
|
1063
|
+
return filter !== undefined;
|
|
1064
|
+
}) as Filter[];
|
|
776
1065
|
oListBinding.filter(aFilters);
|
|
777
1066
|
}
|
|
778
1067
|
|
|
779
|
-
|
|
1068
|
+
// Sorting
|
|
1069
|
+
if (kpiDefinition.chart.sortOrder) {
|
|
1070
|
+
oListBinding.sort(
|
|
1071
|
+
kpiDefinition.chart.sortOrder.map(sortInfo => {
|
|
1072
|
+
return new Sorter(sortInfo.name, sortInfo.descending);
|
|
1073
|
+
})
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
return oListBinding.requestContexts(0, kpiDefinition.chart.maxItems).then((aContexts: Context[]) => {
|
|
780
1078
|
const chartData = aContexts.map(function(oContext) {
|
|
781
1079
|
const oData: Record<string, any> = {};
|
|
782
|
-
kpiDefinition.
|
|
783
|
-
oData[
|
|
1080
|
+
kpiDefinition.chart.dimensions.forEach(dimension => {
|
|
1081
|
+
oData[dimension.name] = oContext.getProperty(dimension.name);
|
|
784
1082
|
});
|
|
785
|
-
kpiDefinition.
|
|
786
|
-
oData[
|
|
1083
|
+
kpiDefinition.chart.measures.forEach(measure => {
|
|
1084
|
+
oData[measure.name] = oContext.getProperty(measure.name);
|
|
787
1085
|
});
|
|
788
1086
|
|
|
789
1087
|
return oData;
|
|
@@ -796,34 +1094,67 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
796
1094
|
/**
|
|
797
1095
|
* Gets the popover to display the KPI card
|
|
798
1096
|
* The popover and the contained card for the KPIs are created if necessary.
|
|
799
|
-
* The popover is shared between all KPIs, so
|
|
1097
|
+
* The popover is shared between all KPIs, so it's created only once.
|
|
800
1098
|
*
|
|
801
|
-
* @param oKPITag The
|
|
802
|
-
* @returns The shared popover.
|
|
1099
|
+
* @param oKPITag The tag that triggered the popover opening.
|
|
1100
|
+
* @returns The shared popover as a promise.
|
|
803
1101
|
*/
|
|
804
|
-
protected getPopover(oKPITag: GenericTag): Popover {
|
|
1102
|
+
protected getPopover(oKPITag: GenericTag): Promise<Popover> {
|
|
805
1103
|
if (!this.oPopover) {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1104
|
+
return new Promise((resolve, reject) => {
|
|
1105
|
+
sap.ui
|
|
1106
|
+
.getCore()
|
|
1107
|
+
.loadLibrary("sap/ui/integration", { async: true })
|
|
1108
|
+
.then(() => {
|
|
1109
|
+
sap.ui.require(["sap/ui/integration/widgets/Card", "sap/ui/integration/Host"], (Card: any, Host: any) => {
|
|
1110
|
+
const oHost = new Host();
|
|
1111
|
+
|
|
1112
|
+
oHost.attachAction((oEvent: any) => {
|
|
1113
|
+
const sType = oEvent.getParameter("type");
|
|
1114
|
+
const oParams = oEvent.getParameter("parameters");
|
|
1115
|
+
|
|
1116
|
+
if (sType === "Navigation") {
|
|
1117
|
+
if (oParams.semanticObject) {
|
|
1118
|
+
(this.getView().getController() as any)._intentBasedNavigation.navigate(
|
|
1119
|
+
oParams.semanticObject,
|
|
1120
|
+
oParams.action
|
|
1121
|
+
);
|
|
1122
|
+
} else {
|
|
1123
|
+
(this.getView().getController() as any)._intentBasedNavigation.navigateOutbound(oParams.outbound);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
810
1127
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
});
|
|
1128
|
+
this.oCard = new Card({
|
|
1129
|
+
width: "25rem",
|
|
1130
|
+
height: "auto"
|
|
1131
|
+
});
|
|
1132
|
+
this.oCard.setHost(oHost as any);
|
|
817
1133
|
|
|
818
|
-
|
|
819
|
-
|
|
1134
|
+
this.oPopover = new Popover({
|
|
1135
|
+
id: "kpi-Popover",
|
|
1136
|
+
showHeader: false,
|
|
1137
|
+
placement: "Auto",
|
|
1138
|
+
content: [this.oCard]
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1141
|
+
oKPITag.addDependent(this.oPopover); // The first clicked tag gets the popover as dependent
|
|
820
1142
|
|
|
821
|
-
|
|
1143
|
+
resolve(this.oPopover);
|
|
1144
|
+
});
|
|
1145
|
+
})
|
|
1146
|
+
.catch(function() {
|
|
1147
|
+
reject();
|
|
1148
|
+
});
|
|
1149
|
+
});
|
|
1150
|
+
} else {
|
|
1151
|
+
return Promise.resolve(this.oPopover);
|
|
1152
|
+
}
|
|
822
1153
|
}
|
|
823
1154
|
|
|
824
1155
|
@Public
|
|
825
1156
|
public onKPIPressed(oKPITag: any, kpiID: string): void {
|
|
826
|
-
const oKPIModel = oKPITag.getModel("kpiModel") as JSONModel
|
|
1157
|
+
const oKPIModel = oKPITag.getModel("kpiModel") as JSONModel<any>;
|
|
827
1158
|
|
|
828
1159
|
if (this.aKPIDefinitions && this.aKPIDefinitions.length) {
|
|
829
1160
|
const kpiDefinition = this.aKPIDefinitions.find(function(oDef) {
|
|
@@ -831,13 +1162,19 @@ class KPIManagementControllerExtension extends ControllerExtension {
|
|
|
831
1162
|
});
|
|
832
1163
|
|
|
833
1164
|
if (kpiDefinition) {
|
|
834
|
-
const
|
|
835
|
-
const
|
|
1165
|
+
const oModel = oKPITag.getModel();
|
|
1166
|
+
const aPromises = [
|
|
1167
|
+
this.loadKPITagData(kpiDefinition, oModel, oKPIModel, true),
|
|
1168
|
+
this.loadKPICardData(kpiDefinition, oModel, oKPIModel),
|
|
1169
|
+
this.getPopover(oKPITag)
|
|
1170
|
+
];
|
|
836
1171
|
|
|
837
1172
|
Promise.all(aPromises)
|
|
838
|
-
.then(
|
|
1173
|
+
.then(aResults => {
|
|
839
1174
|
this.oCard.setManifest(oKPIModel.getProperty("/" + kpiID + "/manifest"));
|
|
840
1175
|
this.oCard.refresh();
|
|
1176
|
+
|
|
1177
|
+
const oPopover = aResults[2];
|
|
841
1178
|
oPopover.openBy(oKPITag, false);
|
|
842
1179
|
})
|
|
843
1180
|
.catch(err => {
|