Skip to content

Commit 5527990

Browse files
authored
feat(framework): OpenUI5 integration (#1138)
1 parent b1459ce commit 5527990

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+267
-121
lines changed

docs/Public Module Imports.md

+23
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,26 @@ You can pass the parameters directly, as an object, or as a URL:
340340
3) Pass a URL to a JSON file, containing the CSS Vars in its "_" property. Will be fetched on demand, not upon registration.
341341

342342
`registerThemeProperties("my-package", "my_theme", "http://url/to/my/theme.json");`
343+
344+
### 7. OpenUI5 integration
345+
346+
```js
347+
import "@ui5/webcomponents-base/dist/features/OpenUI5Support.js";
348+
```
349+
350+
If your app uses both OpenUI5 and UI5 Web Components, UI5 Web Components can benefit
351+
from OpenUI5 configuration and resources.
352+
353+
When you import the above module:
354+
1. OpenUI5 configuration takes precedence over UI5 Web Components configuration
355+
for all common entities (theme, language, RTL, etc...). In addition, changing the theme
356+
in OpenUI5 will also change the theme in UI5 Web Components.
357+
2. Fonts will not be loaded twice (just once by OpenUI5, and reused).
358+
3. Locale Data assets will not be fetched twice (just once by OpenUI5, and reused).
359+
360+
Therefore, if you intend to run both frameworks in the same browser window,
361+
it is highly recommended to enable OpenUI5 support and benefit from these optimizations.
362+
363+
*Note:* In general the order in which OpenUI5 and UI5 Web Components are loaded does not matter.
364+
However, if your app needs to support Internet Explorer 11, either load OpenUI5 first, or load
365+
UI5 Web Components deferred.

docs/dev/Developing Web Components.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,8 @@ class Demo extends UI5Element {
5959
return DemoCss;
6060
}
6161

62-
static async define(...params) {
62+
static async onDefine() {
6363
await fetchI18nBundle("my-ui5-web-components");
64-
super.define(...params);
6564
}
6665
}
6766

@@ -374,9 +373,8 @@ class Demo extends UI5Element {
374373
return DemoCss;
375374
}
376375

377-
static async define(...params) {
376+
static async onDefine() {
378377
await fetchI18nBundle("my-ui5-web-components");
379-
super.define(...params);
380378
}
381379
}
382380

@@ -385,7 +383,7 @@ Demo.define();
385383
export default Demo;
386384
```
387385

388-
Please note that here we override the `define` method of `UI5Element` in order to ensure that i18n resources have been fetched
386+
Please note that here we use the `onDefine` method of `UI5Element` in order to ensure that i18n resources have been fetched
389387
before the web component has been defined. The used namespace for resource registration (in this example `my-ui5-web-components`)
390388
is the `name` property of your `package.json` file.
391389

packages/base/bundle.esm.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "./dist/features/calendar/Persian.js";
77

88
// ESM bundle targets Edge + browsers with native support
99
import "./dist/features/browsersupport/Edge.js";
10+
import "./dist/features/OpenUI5Support.js";
1011

1112
// Test components
1213
import "./dist/test-resources/elements/Generic.js";

packages/base/src/FontFace.js

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* CSS font face used for the texts provided by SAP.
33
*/
44
import createStyleInHead from "./util/createStyleInHead.js";
5+
import { getFeature } from "./FeaturesRegistry.js";
56

67
/* CDN Locations */
78
const font72RegularWoff = `https://ui5.sap.com/sdk/resources/sap/ui/core/themes/sap_fiori_3/fonts/72-Regular.woff?ui5-webcomponents`;
@@ -60,6 +61,12 @@ const insertFontFace = () => {
6061
return;
6162
}
6263

64+
// If OpenUI5 is found, let it set the font
65+
const OpenUI5Support = getFeature("OpenUI5Support");
66+
if (OpenUI5Support && OpenUI5Support.isLoaded()) {
67+
return;
68+
}
69+
6370
createStyleInHead(fontFaceCSS, { "data-ui5-font-face": "" });
6471
};
6572

packages/base/src/InitialConfiguration.js

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import merge from "@ui5/webcomponents-utils/dist/sap/base/util/merge.js";
2+
import { getFeature } from "./FeaturesRegistry.js";
3+
14
let initialized = false;
25

3-
const initialConfig = {
6+
let initialConfig = {
47
animationMode: "full",
58
theme: "sap_fiori_3",
69
rtl: null,
@@ -50,8 +53,6 @@ const booleanMapping = new Map();
5053
booleanMapping.set("true", true);
5154
booleanMapping.set("false", false);
5255

53-
let runtimeConfig = {};
54-
5556
const parseConfigurationScript = () => {
5657
const configScript = document.querySelector("[data-ui5-config]") || document.querySelector("[data-id='sap-ui-config']"); // for backward compatibility
5758

@@ -65,7 +66,7 @@ const parseConfigurationScript = () => {
6566
}
6667

6768
if (configJSON) {
68-
runtimeConfig = Object.assign({}, configJSON);
69+
initialConfig = merge(initialConfig, configJSON);
6970
}
7071
}
7172
};
@@ -86,24 +87,34 @@ const parseURLParameters = () => {
8687
value = booleanMapping.get(lowerCaseValue);
8788
}
8889

89-
runtimeConfig[param] = value;
90+
initialConfig[param] = value;
9091
});
9192
};
9293

93-
const applyConfigurations = () => {
94-
Object.keys(runtimeConfig).forEach(key => {
95-
initialConfig[key] = runtimeConfig[key];
96-
});
94+
const applyOpenUI5Configuration = () => {
95+
const OpenUI5Support = getFeature("OpenUI5Support");
96+
if (!OpenUI5Support || !OpenUI5Support.isLoaded()) {
97+
return;
98+
}
99+
100+
const OpenUI5Config = OpenUI5Support.getConfigurationSettingsObject();
101+
initialConfig = merge(initialConfig, OpenUI5Config);
97102
};
98103

104+
99105
const initConfiguration = () => {
100106
if (initialized) {
101107
return;
102108
}
103109

110+
// 1. Lowest priority - configuration script
104111
parseConfigurationScript();
112+
113+
// 2. URL parameters overwrite configuration script parameters
105114
parseURLParameters();
106-
applyConfigurations();
115+
116+
// 3. If OpenUI5 is detected, it has the highest priority
117+
applyOpenUI5Configuration();
107118

108119
initialized = true;
109120
};

packages/base/src/UI5Element.js

+5
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,11 @@ class UI5Element extends HTMLElement {
800800
*/
801801
static async define() {
802802
await boot();
803+
804+
if (this.onDefine) {
805+
await this.onDefine();
806+
}
807+
803808
const tag = this.getMetadata().getTag();
804809

805810
const definedLocally = DefinitionsSet.has(tag);

packages/base/src/boot.js

+7
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@ import insertFontFace from "./FontFace.js";
33
import { getTheme } from "./config/Theme.js";
44
import { _applyTheme } from "./Theming.js";
55
import whenPolyfillLoaded from "./compatibility/whenPolyfillLoaded.js";
6+
import { getFeature } from "./FeaturesRegistry.js";
67

78
let bootPromise;
9+
const OpenUI5Support = getFeature("OpenUI5Support");
810

911
const boot = () => {
1012
if (bootPromise) {
1113
return bootPromise;
1214
}
1315

1416
bootPromise = new Promise(async resolve => {
17+
if (OpenUI5Support) {
18+
await OpenUI5Support.init();
19+
}
20+
1521
await whenDOMReady();
1622
await _applyTheme(getTheme());
23+
OpenUI5Support && OpenUI5Support.attachListeners();
1724
insertFontFace();
1825
await whenPolyfillLoaded();
1926
resolve();

packages/base/src/config/AnimationMode.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { getAnimationMode as getConfiguredAnimationMode } from "../InitialConfiguration.js";
22

3-
const animationMode = getConfiguredAnimationMode();
3+
let animationMode;
44

55
const getAnimationMode = () => {
6+
if (animationMode === undefined) {
7+
animationMode = getConfiguredAnimationMode();
8+
}
9+
610
return animationMode;
711
};
812

packages/base/src/config/CalendarType.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import CalendarType from "@ui5/webcomponents-utils/dist/sap/ui/core/CalendarType.js";
22
import { getCalendarType as getConfiguredCalendarType } from "../InitialConfiguration.js";
33

4-
const calendarType = getConfiguredCalendarType();
4+
let calendarType;
55

66
const getCalendarType = () => {
7+
if (calendarType === undefined) {
8+
calendarType = getConfiguredCalendarType();
9+
}
10+
711
if (calendarType) {
812
const type = Object.keys(CalendarType).find(calType => calType === calendarType);
913

packages/base/src/config/FormatSettings.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { getFormatSettings } from "../InitialConfiguration.js";
22

3-
const formatSettings = getFormatSettings();
3+
let formatSettings;
44

55
const getFirstDayOfWeek = () => {
6+
if (formatSettings === undefined) {
7+
formatSettings = getFormatSettings();
8+
}
9+
610
return formatSettings.firstDayOfWeek;
711
};
812

packages/base/src/config/Language.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { getLanguage as getConfiguredLanguage } from "../InitialConfiguration.js";
22

3-
const language = getConfiguredLanguage();
3+
let language;
44

55
const getLanguage = () => {
6+
if (language === undefined) {
7+
language = getConfiguredLanguage();
8+
}
69
return language;
710
};
811

packages/base/src/config/NoConflict.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,31 @@ const shouldFireOriginalEvent = eventName => {
99
return excludeList.includes(eventName);
1010
};
1111

12-
let noConflict = getConfiguredNoConflict();
12+
let noConflict;
1313

1414
const shouldNotFireOriginalEvent = eventName => {
15-
return !(noConflict.events && noConflict.events.includes && noConflict.events.includes(eventName));
15+
const nc = getNoConflict();
16+
return !(nc.events && nc.events.includes && nc.events.includes(eventName));
1617
};
1718

1819
const getNoConflict = () => {
20+
if (noConflict === undefined) {
21+
noConflict = getConfiguredNoConflict();
22+
}
23+
1924
return noConflict;
2025
};
2126

2227
const skipOriginalEvent = eventName => {
28+
const nc = getNoConflict();
29+
2330
// Always fire these events
2431
if (shouldFireOriginalEvent(eventName)) {
2532
return false;
2633
}
2734

2835
// Read from the configuration
29-
if (noConflict === true) {
36+
if (nc === true) {
3037
return true;
3138
}
3239

packages/base/src/config/Theme.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { getTheme as getConfiguredTheme } from "../InitialConfiguration.js";
22
import { _applyTheme } from "../Theming.js";
33

4-
let theme = getConfiguredTheme();
4+
let theme;
55

66
const getTheme = () => {
7+
if (theme === undefined) {
8+
theme = getConfiguredTheme();
9+
}
10+
711
return theme;
812
};
913

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { registerFeature } from "../FeaturesRegistry.js";
2+
import { setTheme } from "../config/Theme.js";
3+
4+
const sap = window.sap;
5+
const core = sap && sap.ui && typeof sap.ui.getCore === "function" && sap.ui.getCore();
6+
7+
const isLoaded = () => {
8+
return !!core;
9+
};
10+
11+
const init = () => {
12+
if (!core) {
13+
return Promise.resolve();
14+
}
15+
16+
return new Promise(resolve => {
17+
core.attachInit(() => {
18+
sap.ui.require(["sap/ui/core/LocaleData"], resolve);
19+
});
20+
});
21+
};
22+
23+
const getConfigurationSettingsObject = () => {
24+
if (!core) {
25+
return;
26+
}
27+
28+
const config = core.getConfiguration();
29+
const LocaleData = sap.ui.require("sap/ui/core/LocaleData");
30+
31+
return {
32+
animationMode: config.getAnimationMode(),
33+
language: config.getLanguage(),
34+
theme: config.getTheme(),
35+
rtl: config.getRTL(),
36+
calendarType: config.getCalendarType(),
37+
formatSettings: {
38+
firstDayOfWeek: LocaleData.getInstance(config.getLocale()).getFirstDayOfWeek(),
39+
},
40+
};
41+
};
42+
43+
const getLocaleDataObject = () => {
44+
if (!core) {
45+
return;
46+
}
47+
48+
const config = core.getConfiguration();
49+
const LocaleData = sap.ui.require("sap/ui/core/LocaleData");
50+
return LocaleData.getInstance(config.getLocale()).mData;
51+
};
52+
53+
const listenForThemeChange = () => {
54+
const config = core.getConfiguration();
55+
core.attachThemeChanged(async () => {
56+
await setTheme(config.getTheme());
57+
});
58+
};
59+
60+
const attachListeners = () => {
61+
if (!core) {
62+
return;
63+
}
64+
65+
listenForThemeChange();
66+
};
67+
68+
const OpenUI5Support = {
69+
isLoaded,
70+
init,
71+
getConfigurationSettingsObject,
72+
getLocaleDataObject,
73+
attachListeners,
74+
};
75+
76+
registerFeature("OpenUI5Support", OpenUI5Support);

packages/fiori/src/ShellBar.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -867,15 +867,13 @@ class ShellBar extends UI5Element {
867867
return getRTL() ? "rtl" : undefined;
868868
}
869869

870-
static async define(...params) {
870+
static async onDefine() {
871871
await Promise.all([
872872
Icon.define(),
873873
List.define(),
874874
Popover.define(),
875875
StandardListItem.define(),
876876
]);
877-
878-
super.define(...params);
879877
}
880878
}
881879

0 commit comments

Comments
 (0)