Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(framework): OpenUI5 integration #1138

Merged
merged 22 commits into from
Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
693fe94
fix tools package npmignore file
vladitasev Jan 13, 2020
7e8829a
feat: add OpenUI5 integration
vladitasev Jan 15, 2020
79f2875
font face, make the initial config lazy
vladitasev Jan 16, 2020
747d518
full initial config
vladitasev Jan 16, 2020
0c6de04
Add CLDR support
vladitasev Jan 16, 2020
b283485
add dedicated page, add docs
vladitasev Jan 16, 2020
2d91741
add note
vladitasev Jan 16, 2020
2503703
if OpenUI5 is not loaded, but support is enabled, prevent configurati…
vladitasev Jan 16, 2020
f192922
fixes
vladitasev Jan 16, 2020
d1c9c1e
pass firstDayOfWeek properly and merge objects properly
vladitasev Jan 23, 2020
5f54ae1
small addition to bundle config
vladitasev Jan 23, 2020
73b5d52
Merge remote-tracking branch 'origin/master' into ui5-integration
vladitasev Jan 28, 2020
ea2010b
Merge remote-tracking branch 'origin/master' into ui5-integration
vladitasev Jan 29, 2020
a73d197
wait for OpenUI5 boot
vladitasev Jan 29, 2020
95040fc
fix requires
vladitasev Jan 29, 2020
893e5d0
update docs with beforeDefine
vladitasev Jan 29, 2020
f08792f
fix animation mode
vladitasev Jan 29, 2020
9e377b6
rename beforeDefine to onDefine
vladitasev Jan 30, 2020
00f4eb8
Merge remote-tracking branch 'origin/master' into ui5-integration
vladitasev Feb 3, 2020
850dc3d
do not hard-code a default firstDayOfWeek - let components use the lo…
vladitasev Feb 3, 2020
28a725f
Merge remote-tracking branch 'origin/master' into ui5-integration
vladitasev Feb 11, 2020
ce17e0f
Merge branch 'master' into ui5-integration
vladitasev Feb 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/Public Module Imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,26 @@ You can pass the parameters directly, as an object, or as a URL:
3) Pass a URL to a JSON file, containing the CSS Vars in its "_" property. Will be fetched on demand, not upon registration.

`registerThemeProperties("my-package", "my_theme", "http://url/to/my/theme.json");`

### 7. OpenUI5 integration

```js
import "@ui5/webcomponents-base/dist/features/OpenUI5Support.js";
```

If your app uses both OpenUI5 and UI5 Web Components, UI5 Web Components can benefit
from OpenUI5 configuration and resources.

When you import the above module:
1. OpenUI5 configuration takes precedence over UI5 Web Components configuration
for all common entities (theme, language, RTL, etc...). In addition, changing the theme
in OpenUI5 will also change the theme in UI5 Web Components.
2. Fonts will not be loaded twice (just once by OpenUI5, and reused).
3. Locale Data assets will not be fetched twice (just once by OpenUI5, and reused).

Therefore, if you intend to run both frameworks in the same browser window,
it is highly recommended to enable OpenUI5 support and benefit from these optimizations.

*Note:* In general the order in which OpenUI5 and UI5 Web Components are loaded does not matter.
However, if your app needs to support Internet Explorer 11, either load OpenUI5 first, or load
UI5 Web Components deferred.
8 changes: 3 additions & 5 deletions docs/dev/Developing Web Components.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@ class Demo extends UI5Element {
return DemoCss;
}

static async define(...params) {
static async onDefine() {
await fetchI18nBundle("my-ui5-web-components");
super.define(...params);
}
}

Expand Down Expand Up @@ -374,9 +373,8 @@ class Demo extends UI5Element {
return DemoCss;
}

static async define(...params) {
static async onDefine() {
await fetchI18nBundle("my-ui5-web-components");
super.define(...params);
}
}

Expand All @@ -385,7 +383,7 @@ Demo.define();
export default Demo;
```

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

Expand Down
1 change: 1 addition & 0 deletions packages/base/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "./dist/features/calendar/Persian.js";

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

// Test components
import "./dist/test-resources/elements/Generic.js";
Expand Down
7 changes: 7 additions & 0 deletions packages/base/src/FontFace.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* CSS font face used for the texts provided by SAP.
*/
import createStyleInHead from "./util/createStyleInHead.js";
import { getFeature } from "./FeaturesRegistry.js";

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

// If OpenUI5 is found, let it set the font
const OpenUI5Support = getFeature("OpenUI5Support");
if (OpenUI5Support && OpenUI5Support.isLoaded()) {
return;
}

createStyleInHead(fontFaceCSS, { "data-ui5-font-face": "" });
};

Expand Down
31 changes: 21 additions & 10 deletions packages/base/src/InitialConfiguration.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import merge from "@ui5/webcomponents-utils/dist/sap/base/util/merge.js";
import { getFeature } from "./FeaturesRegistry.js";

let initialized = false;

const initialConfig = {
let initialConfig = {
animationMode: "full",
theme: "sap_fiori_3",
rtl: null,
Expand Down Expand Up @@ -50,8 +53,6 @@ const booleanMapping = new Map();
booleanMapping.set("true", true);
booleanMapping.set("false", false);

let runtimeConfig = {};

const parseConfigurationScript = () => {
const configScript = document.querySelector("[data-ui5-config]") || document.querySelector("[data-id='sap-ui-config']"); // for backward compatibility

Expand All @@ -65,7 +66,7 @@ const parseConfigurationScript = () => {
}

if (configJSON) {
runtimeConfig = Object.assign({}, configJSON);
initialConfig = merge(initialConfig, configJSON);
}
}
};
Expand All @@ -86,24 +87,34 @@ const parseURLParameters = () => {
value = booleanMapping.get(lowerCaseValue);
}

runtimeConfig[param] = value;
initialConfig[param] = value;
});
};

const applyConfigurations = () => {
Object.keys(runtimeConfig).forEach(key => {
initialConfig[key] = runtimeConfig[key];
});
const applyOpenUI5Configuration = () => {
const OpenUI5Support = getFeature("OpenUI5Support");
if (!OpenUI5Support || !OpenUI5Support.isLoaded()) {
return;
}

const OpenUI5Config = OpenUI5Support.getConfigurationSettingsObject();
initialConfig = merge(initialConfig, OpenUI5Config);
};


const initConfiguration = () => {
if (initialized) {
return;
}

// 1. Lowest priority - configuration script
parseConfigurationScript();

// 2. URL parameters overwrite configuration script parameters
parseURLParameters();
applyConfigurations();

// 3. If OpenUI5 is detected, it has the highest priority
applyOpenUI5Configuration();

initialized = true;
};
Expand Down
5 changes: 5 additions & 0 deletions packages/base/src/UI5Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,11 @@ class UI5Element extends HTMLElement {
*/
static async define() {
await boot();

if (this.onDefine) {
await this.onDefine();
}

const tag = this.getMetadata().getTag();

const definedLocally = DefinitionsSet.has(tag);
Expand Down
7 changes: 7 additions & 0 deletions packages/base/src/boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ import insertFontFace from "./FontFace.js";
import { getTheme } from "./config/Theme.js";
import { _applyTheme } from "./Theming.js";
import whenPolyfillLoaded from "./compatibility/whenPolyfillLoaded.js";
import { getFeature } from "./FeaturesRegistry.js";

let bootPromise;
const OpenUI5Support = getFeature("OpenUI5Support");

const boot = () => {
if (bootPromise) {
return bootPromise;
}

bootPromise = new Promise(async resolve => {
if (OpenUI5Support) {
await OpenUI5Support.init();
}

await whenDOMReady();
await _applyTheme(getTheme());
OpenUI5Support && OpenUI5Support.attachListeners();
insertFontFace();
await whenPolyfillLoaded();
resolve();
Expand Down
6 changes: 5 additions & 1 deletion packages/base/src/config/AnimationMode.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { getAnimationMode as getConfiguredAnimationMode } from "../InitialConfiguration.js";

const animationMode = getConfiguredAnimationMode();
let animationMode;

const getAnimationMode = () => {
if (animationMode === undefined) {
animationMode = getConfiguredAnimationMode();
}

return animationMode;
};

Expand Down
6 changes: 5 additions & 1 deletion packages/base/src/config/CalendarType.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import CalendarType from "@ui5/webcomponents-utils/dist/sap/ui/core/CalendarType.js";
import { getCalendarType as getConfiguredCalendarType } from "../InitialConfiguration.js";

const calendarType = getConfiguredCalendarType();
let calendarType;

const getCalendarType = () => {
if (calendarType === undefined) {
calendarType = getConfiguredCalendarType();
}

if (calendarType) {
const type = Object.keys(CalendarType).find(calType => calType === calendarType);

Expand Down
6 changes: 5 additions & 1 deletion packages/base/src/config/FormatSettings.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { getFormatSettings } from "../InitialConfiguration.js";

const formatSettings = getFormatSettings();
let formatSettings;

const getFirstDayOfWeek = () => {
if (formatSettings === undefined) {
formatSettings = getFormatSettings();
}

return formatSettings.firstDayOfWeek;
};

Expand Down
5 changes: 4 additions & 1 deletion packages/base/src/config/Language.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { getLanguage as getConfiguredLanguage } from "../InitialConfiguration.js";

const language = getConfiguredLanguage();
let language;

const getLanguage = () => {
if (language === undefined) {
language = getConfiguredLanguage();
}
return language;
};

Expand Down
13 changes: 10 additions & 3 deletions packages/base/src/config/NoConflict.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,31 @@ const shouldFireOriginalEvent = eventName => {
return excludeList.includes(eventName);
};

let noConflict = getConfiguredNoConflict();
let noConflict;

const shouldNotFireOriginalEvent = eventName => {
return !(noConflict.events && noConflict.events.includes && noConflict.events.includes(eventName));
const nc = getNoConflict();
return !(nc.events && nc.events.includes && nc.events.includes(eventName));
};

const getNoConflict = () => {
if (noConflict === undefined) {
noConflict = getConfiguredNoConflict();
}

return noConflict;
};

const skipOriginalEvent = eventName => {
const nc = getNoConflict();

// Always fire these events
if (shouldFireOriginalEvent(eventName)) {
return false;
}

// Read from the configuration
if (noConflict === true) {
if (nc === true) {
return true;
}

Expand Down
6 changes: 5 additions & 1 deletion packages/base/src/config/Theme.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { getTheme as getConfiguredTheme } from "../InitialConfiguration.js";
import { _applyTheme } from "../Theming.js";

let theme = getConfiguredTheme();
let theme;

const getTheme = () => {
if (theme === undefined) {
theme = getConfiguredTheme();
}

return theme;
};

Expand Down
76 changes: 76 additions & 0 deletions packages/base/src/features/OpenUI5Support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { registerFeature } from "../FeaturesRegistry.js";
import { setTheme } from "../config/Theme.js";

const sap = window.sap;
const core = sap && sap.ui && typeof sap.ui.getCore === "function" && sap.ui.getCore();

const isLoaded = () => {
return !!core;
};

const init = () => {
if (!core) {
return Promise.resolve();
}

return new Promise(resolve => {
core.attachInit(() => {
sap.ui.require(["sap/ui/core/LocaleData"], resolve);
});
});
};

const getConfigurationSettingsObject = () => {
if (!core) {
return;
}

const config = core.getConfiguration();
const LocaleData = sap.ui.require("sap/ui/core/LocaleData");

return {
animationMode: config.getAnimationMode(),
language: config.getLanguage(),
theme: config.getTheme(),
rtl: config.getRTL(),
calendarType: config.getCalendarType(),
formatSettings: {
firstDayOfWeek: LocaleData.getInstance(config.getLocale()).getFirstDayOfWeek(),
},
};
};

const getLocaleDataObject = () => {
if (!core) {
return;
}

const config = core.getConfiguration();
const LocaleData = sap.ui.require("sap/ui/core/LocaleData");
return LocaleData.getInstance(config.getLocale()).mData;
};

const listenForThemeChange = () => {
const config = core.getConfiguration();
core.attachThemeChanged(async () => {
await setTheme(config.getTheme());
});
};

const attachListeners = () => {
if (!core) {
return;
}

listenForThemeChange();
};

const OpenUI5Support = {
isLoaded,
init,
getConfigurationSettingsObject,
getLocaleDataObject,
attachListeners,
};

registerFeature("OpenUI5Support", OpenUI5Support);
4 changes: 1 addition & 3 deletions packages/fiori/src/ShellBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -867,15 +867,13 @@ class ShellBar extends UI5Element {
return getRTL() ? "rtl" : undefined;
}

static async define(...params) {
static async onDefine() {
await Promise.all([
Icon.define(),
List.define(),
Popover.define(),
StandardListItem.define(),
]);

super.define(...params);
}
}

Expand Down
Loading