diff --git a/CHANGELOG.md b/CHANGELOG.md index 00c94fd03f..87cc6dfdd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,25 @@ The lerna-changelog tool detects changes based on PR labels and maps them to sec --> +## [v1.2.4] (2020-07-02) + +#### :bug: Fixed +* [#1453](https://github.com/SAP/luigi/pull/1453) Fix logout label ([@maxmarkus](https://github.com/maxmarkus)) +* [#1431](https://github.com/SAP/luigi/pull/1431) Fix semicollapsible resize ([@maxmarkus](https://github.com/maxmarkus)) + +## [v1.2.3] (2020-06-26) + +#### :rocket: Added +* [#1429](https://github.com/SAP/luigi/pull/1429) Added showLabel attribute to node for top level nav ([@azriel46d](https://github.com/azriel46d)) +* [#1409](https://github.com/SAP/luigi/pull/1409) Added badge counter to left navigation ([@azriel46d](https://github.com/azriel46d)) + +#### :bug: Fixed +* [#1433](https://github.com/SAP/luigi/pull/1433) Fix double frame ([@hardl](https://github.com/hardl)) +* [#1436](https://github.com/SAP/luigi/pull/1436) Remove window.parent check from Client ([@maxmarkus](https://github.com/maxmarkus)) + +## [v1.2.2] (2020-06-25) +* Reverted release. + ## [v1.2.1] (2020-06-04) #### :rocket: Added @@ -785,3 +804,7 @@ The lerna-changelog tool detects changes based on PR labels and maps them to sec [v1.1.0]: https://github.com/SAP/luigi/compare/v1.0.1...v1.1.0 [v1.1.1]: https://github.com/SAP/luigi/compare/v1.1.0...v1.1.1 [v1.2.1]: https://github.com/SAP/luigi/compare/v1.1.1...v1.2.1 + +[v1.2.2]: https://github.com/SAP/luigi/compare/v1.2.1...v1.2.2 +[v1.2.3]: https://github.com/SAP/luigi/compare/v1.2.2...v1.2.3 +[v1.2.4]: https://github.com/SAP/luigi/compare/v1.2.3...v1.2.4 \ No newline at end of file diff --git a/blog/.gitkeep b/blog/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/blog/2020-06-18-welcome-to-luigi-blog.md b/blog/2020-06-18-welcome-to-luigi-blog.md new file mode 100644 index 0000000000..ee7157827d --- /dev/null +++ b/blog/2020-06-18-welcome-to-luigi-blog.md @@ -0,0 +1,18 @@ +--- +title: Welcome to the Luigi blog! +description: This is our first blog entry and it introduces our new blog section. +author: + - Aleksandra Simeonova +layout: blog +--- + +The new blog section of our website will help you stay on top of the latest Luigi news and updates. + + +The Luigi project is growing quickly and attracting more attention in the open-source community. Micro frontend architecture is becoming more popular as an efficient strategy for future-proof, scalable applications. New features are added to Luigi regularly, and we want to keep you up to date. + +This is why we are adding a blog to our website to inform you of the latest Luigi releases, updates, and other important news! You can expect regular posts in the future documenting every release and other Luigi-related topics. If you have an idea for a blog post, you can write to aleksandra.simeonova@sap.com. + +And yes, our first blog post is just to let you know that we have a blog now. #meta #nerdy + +P.S. Follow us on [Twitter](https://twitter.com/luigiprojectio?lang=en) and [YouTube](https://www.youtube.com/channel/UC5WsYsHapDlg2K3iXS4n4AQ) for more Luigi content. \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index b3657c28a7..cdc65cc7c1 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2674,8 +2674,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -2696,14 +2695,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2718,20 +2715,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2848,8 +2842,7 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2861,7 +2854,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2876,7 +2868,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2884,14 +2875,12 @@ "minimist": { "version": "1.2.5", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2910,7 +2899,6 @@ "version": "0.5.3", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "^1.2.5" } @@ -2972,8 +2960,7 @@ "npm-normalize-package-bin": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "npm-packlist": { "version": "1.4.8", @@ -3001,8 +2988,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3014,7 +3000,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3092,8 +3077,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -3129,7 +3113,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3149,7 +3132,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3193,14 +3175,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/client/public-ie11/package.json b/client/public-ie11/package.json index dec41f4cb8..c6e1619b49 100644 --- a/client/public-ie11/package.json +++ b/client/public-ie11/package.json @@ -1,6 +1,6 @@ { "name": "@luigi-project/client-ie11", - "version": "1.2.1", + "version": "1.2.4", "description": "Javascript library supporting consumers of the Luigi framework", "license": "Apache-2.0", "main": "luigi-client-ie11.js", diff --git a/client/public/package.json b/client/public/package.json index b99707218b..9e109000cc 100644 --- a/client/public/package.json +++ b/client/public/package.json @@ -1,6 +1,6 @@ { "name": "@luigi-project/client", - "version": "1.2.1", + "version": "1.2.4", "description": "Javascript library supporting consumers of the Luigi framework", "license": "Apache-2.0", "main": "luigi-client.js", diff --git a/client/src/luigi-client.js b/client/src/luigi-client.js index 0afbefb7c5..e279f2dc1c 100644 --- a/client/src/luigi-client.js +++ b/client/src/luigi-client.js @@ -7,6 +7,8 @@ import { uxManager } from './uxManager'; * @private */ class LuigiClient { + constructor() {} + addInitListener(initFn) { return lifecycleManager.addInitListener(initFn); } diff --git a/core/package-lock.json b/core/package-lock.json index 4fb84625cb..3739fd60a0 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -3948,8 +3948,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -3970,14 +3969,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3992,20 +3989,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4122,8 +4116,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4135,7 +4128,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4150,7 +4142,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4158,14 +4149,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4184,7 +4173,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -4265,8 +4253,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -4278,7 +4265,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4364,8 +4350,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -4401,7 +4386,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4421,7 +4405,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4465,14 +4448,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -11394,7 +11375,8 @@ }, "yargs-parser": { "version": "13.1.1", - "resolved": "", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/core/public-ie11/package.json b/core/public-ie11/package.json index f9b27025cc..eec76dc32f 100644 --- a/core/public-ie11/package.json +++ b/core/public-ie11/package.json @@ -1,6 +1,6 @@ { "name": "@luigi-project/core-ie11", - "version": "1.2.1", + "version": "1.2.4", "description": "Javascript library supporting consumers of the Luigi framework with Internet Explorer 11 capability", "license": "Apache-2.0", "main": "luigi-ie11.js", diff --git a/core/public/package.json b/core/public/package.json index edb19033b7..f0c99e162a 100644 --- a/core/public/package.json +++ b/core/public/package.json @@ -1,6 +1,6 @@ { "name": "@luigi-project/core", - "version": "1.2.1", + "version": "1.2.4", "description": "Javascript library supporting consumers of the Luigi framework", "license": "Apache-2.0", "main": "luigi.js", diff --git a/core/src/Authorization.html b/core/src/Authorization.html index afb8f055de..2e3c8d29de 100644 --- a/core/src/Authorization.html +++ b/core/src/Authorization.html @@ -43,14 +43,14 @@ {/each} - {#if isAuthorizationEnabled} - {#if isLoggedIn && isProfileLogoutItem} + {#if isAuthorizationEnabled || isProfileLogoutItem} + {#if isLoggedIn || !isAuthorizationEnabled && isProfileLogoutItem}
  • - + {#if profileNav.logout.icon} {#if hasOpenUIicon(profileNav.logout)}
  • {/if} - {#if !isLoggedIn && !isProfileLogoutItem} + {#if isAuthorizationEnabled && !isLoggedIn}
  • - + Login
  • @@ -97,14 +97,14 @@ const dispatch = createEventDispatcher(); - let idpProviderInstance; - export let userInfo; export let isHidden = false; - export let isLoggedIn; - export let profileNav = { logout: {}, items: [] }; - export let isAuthorizationEnabled; - export let isProfileLogoutItem; + let idpProviderInstance; + let userInfo; + let isLoggedIn; + let profileNav = { logout: {}, items: [] }; + let isAuthorizationEnabled; + let isProfileLogoutItem; let navProfileListenerInstalled; let profileLogoutFnDefined; let store = getContext('store'); @@ -169,17 +169,18 @@ ...TOP_NAV_DEFAULTS.logout, ...logoutItem }; - isProfileLogoutItem = !!logoutItem; + + isProfileLogoutItem = Boolean(logoutItem); profileLogoutFnDefined = false; AuthLayerSvc.setProfileLogoutFn(null); - if (logoutItem) { - const profileLogoutfn = logoutItem.customLogoutFn; + if ( + logoutItem && + GenericHelpers.isFunction(logoutItem.customLogoutFn) + ) { // TODO: PROFNAVLOGOUT: three smiliar implementations. // TODO: whats the difference between this profileLogoutFn, profileNav, auth-layer - if (profileLogoutfn && GenericHelpers.isFunction(profileLogoutfn)) { - profileLogoutFnDefined = true; - AuthLayerSvc.setProfileLogoutFn(profileLogoutfn); - } + profileLogoutFnDefined = true; + AuthLayerSvc.setProfileLogoutFn(logoutItem.customLogoutFn); } profileNav = profileNavData; }, diff --git a/core/src/core-api/config.js b/core/src/core-api/config.js index 544e36ae2d..5bbc8ebc00 100644 --- a/core/src/core-api/config.js +++ b/core/src/core-api/config.js @@ -219,7 +219,7 @@ class LuigiConfig { /** * Unloads the current Luigi instance, which can be initialized later again by using `Luigi.setConfig({...})` * @memberof Configuration - * @since NEXTRELEASE + * @since 1.2.2 * @example * Luigi.unload() */ diff --git a/core/src/navigation/BadgeCounter.html b/core/src/navigation/BadgeCounter.html index 52f68b0e3d..f58f9b0118 100644 --- a/core/src/navigation/BadgeCounter.html +++ b/core/src/navigation/BadgeCounter.html @@ -56,4 +56,13 @@ } } } + + :global(.fd-nested-list__link) { + .fd-counter--notification { + transform: translate(0px, 0px) !important; + margin-left: auto; + min-width: 1.3rem; + margin-right: -0.3rem; + } + } diff --git a/core/src/navigation/LeftNav.html b/core/src/navigation/LeftNav.html index 43c9ed9f05..5df648ad94 100644 --- a/core/src/navigation/LeftNav.html +++ b/core/src/navigation/LeftNav.html @@ -48,6 +48,9 @@ class="sap-icon--action sap-icon--s" > {/if} + {#if node.badgeCounter} + + {/if} {/if} {/if} {/each} @@ -105,6 +108,9 @@ class="sap-icon--action sap-icon--s" > {/if} + {#if node.badgeCounter} + + {/if} {/if} {/if} {/each} @@ -134,6 +140,9 @@ class="sap-icon--action sap-icon--s" > {/if} + {#if node.badgeCounter} + + {/if} {/if} {/if} {/each} @@ -199,6 +208,9 @@ class="sap-icon--action sap-icon--s" > {/if} + {#if node.badgeCounter} + + {/if} {/if} {/if} {/each} @@ -275,9 +287,10 @@ import { Navigation } from './services/navigation'; import { IframeHelpers, NavigationHelpers } from '../utilities/helpers'; import { LuigiConfig, LuigiElements, LuigiI18N } from '../core-api'; - import { StateHelpers } from '../utilities/helpers'; + import { StateHelpers, EventListenerHelpers } from '../utilities/helpers'; import { CSS_BREAKPOINTS } from '../utilities/constants'; import { SemiCollapsibleNavigation } from './services/semi-collapsed-navigation'; + import BadgeCounter from './BadgeCounter.html'; export let children; export let hideNavComponent; @@ -347,6 +360,12 @@ SemiCollapsibleNavigation.onValueChanged(stateArr => { isSemiCollapsed = stateArr.isSemiCollapsed; }); + + EventListenerHelpers.addEventListener('message', e => { + if ('luigi.navigation.update-badge-counters' === e.data.msg) { + setLeftNavData(); + } + }); }); beforeUpdate(() => { @@ -596,6 +615,8 @@ } } + + :global(.fd-nested-list--compact) { .fd-nested-list__icon { img { diff --git a/core/src/navigation/TopNav.html b/core/src/navigation/TopNav.html index 0ac7c0feef..f1ee8c713c 100644 --- a/core/src/navigation/TopNav.html +++ b/core/src/navigation/TopNav.html @@ -67,10 +67,11 @@ > {/if} - {:else} - {getNodeLabel(node)} {/if} + {#if !node.icon || node.showLabel} + {getNodeLabel(node)} + {/if} @@ -113,10 +114,11 @@ > {/if} - {:else} - {getNodeLabel(node)} {/if} + {#if !node.icon || node.showLabel} + {getNodeLabel(node)} + {/if} @@ -633,6 +635,9 @@ margin-top: 10px; } } + .fd-top-nav__icon + span { + line-height: 2.4rem; + } } .hideNavComponent { diff --git a/core/src/navigation/services/semi-collapsed-navigation.js b/core/src/navigation/services/semi-collapsed-navigation.js index db6684b8cd..4a998d01f3 100644 --- a/core/src/navigation/services/semi-collapsed-navigation.js +++ b/core/src/navigation/services/semi-collapsed-navigation.js @@ -51,14 +51,22 @@ class SemiCollapsibleNavigationClass { window.innerWidth !== 0 && window.innerWidth < CSS_BREAKPOINTS.desktopMinWidth && this.previousWindowWidth >= CSS_BREAKPOINTS.desktopMinWidth; + const isMobileToDesktop = + window.innerWidth !== 0 && + window.innerWidth > CSS_BREAKPOINTS.desktopMinWidth && + this.previousWindowWidth >= CSS_BREAKPOINTS.desktopMinWidth; + if (isDesktopToMobile) { - this.setCollapsed(true); + this.setCollapsed(true, false); + } + if (!this.isStoredCollapsed() && isMobileToDesktop) { + this.setCollapsed(false, false); } selectedCategory = this.closePopupMenu(selectedCategory); return { isSemiCollapsed: this.isSemiCollapsed, selectedCategory }; } - setCollapsed(state) { + setCollapsed(state, persistState = true) { document.body.classList.remove('semiCollapsed'); // add if true if (state) { @@ -66,7 +74,9 @@ class SemiCollapsibleNavigationClass { } // initial state this.isSemiCollapsed = state; - localStorage.setItem(NavigationHelpers.COL_NAV_KEY, state); + if (persistState) { + localStorage.setItem(NavigationHelpers.COL_NAV_KEY, state); + } if (this.valueChangedFns instanceof Array) { this.valueChangedFns.forEach(fn => @@ -77,7 +87,14 @@ class SemiCollapsibleNavigationClass { } } + isStoredCollapsed() { + return JSON.parse(localStorage.getItem(NavigationHelpers.COL_NAV_KEY)); + } + getCollapsed() { + if (this.isStoredCollapsed()) { + return true; + } return this.isSemiCollapsed; } diff --git a/core/src/services/iframe.js b/core/src/services/iframe.js index 20906316d3..b40fce015c 100644 --- a/core/src/services/iframe.js +++ b/core/src/services/iframe.js @@ -175,17 +175,20 @@ class IframeClass { } /** - * Checks if Client has set the initOk if the clientVersion is younger than NEXTRELEASE + * Checks if Client has set the initOk if the clientVersion is younger than 1.2.2 * or if it failed to receive the initial get-context request. - * @since: NEXTRELEASE + * @since: 1.2.2 */ initHandshakeFailed(config) { + if (!(config && config.iframe && config.iframe.luigi)) { + return true; + } const clientVersion = config.iframe.luigi.clientVersion; if (config.iframe.luigi.initOk === undefined) { // initial get-context request was not received return true; } else if ( - // valid minimum handshake version: NEXTRELEASE + // valid minimum handshake version: 1.2.2 !clientVersion || GenericHelpers.semverCompare('1.1.1', clientVersion) !== -1 ) { @@ -275,6 +278,9 @@ class IframeClass { // if iframe does not exist, or handshake was interrupted, create a new one if (!config.iframe || this.initHandshakeFailed(config)) { + if (config.iframe) { + node.removeChild(config.iframe); + } // preserveView, hide other frames, else remove if (pvSituation) { this.notifyInactiveIframes(); diff --git a/docs/getting-started.md b/docs/getting-started.md index 769406f8ca..1bb1cc72c8 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -115,8 +115,8 @@ Go to the [Luigi Fiddle](https://fiddle.luigi-project.io/) website. Click on **M Follow these steps to create a global user interface and host a **full web application** in Luigi: 1. Set up a Luigi Core application on one of the following frameworks: - * [No framework](application-setup.md#application-setup-for-an-application-not-using-a-framework) - * [Angular 6](application-setup.md#application-setup-for-angular-6) + * [No framework](application-setup.md#application-setup-without-a-framework) + * [Angular 6](application-setup.md#application-setup-for-angular) * [SAPUI5/OpenUI5](application-setup.md#application-setup-for-sapui5openui5) * [VUE.JS](application-setup.md#application-setup-for-vuejs) * [React](application-setup.md#application-setup-for-react) diff --git a/docs/luigi-core-api.md b/docs/luigi-core-api.md index d1c4cc42eb..18b01990a7 100644 --- a/docs/luigi-core-api.md +++ b/docs/luigi-core-api.md @@ -168,7 +168,7 @@ Luigi.unload() **Meta** -- **since**: NEXTRELEASE +- **since**: 1.2.2 ## Luigi.elements() diff --git a/docs/navigation-parameters-reference.md b/docs/navigation-parameters-reference.md index ec15f09ed0..cb5a1bbbfc 100644 --- a/docs/navigation-parameters-reference.md +++ b/docs/navigation-parameters-reference.md @@ -214,7 +214,11 @@ settings: { ``` ### icon - **type**: string -- **description**: the name of an icon, without the `sap-icon--` prefix. Its source may be [OpenUI](https://openui5.hana.ondemand.com/1.40.10/iconExplorer.html) or a custom link (relative or absolute) to an image. It is recommended to use a square image. The icon is displayed next to the node label in the side navigation or instead of the label in the top navigation. +- **description**: the name of an icon, without the `sap-icon--` prefix. Its source may be [OpenUI](https://openui5.hana.ondemand.com/1.40.10/iconExplorer.html) or a custom link (relative or absolute) to an image. It is recommended to use a square image. The icon is displayed next to the node label in the side navigation or instead of the label in the top navigation. To show the label next to the icon in the top navigation, add the `showLabel` attribute. + +### showLabel +- **type**: boolean +- **description**: Forces the label to be visible in the top navigation even if an icon is set. ### altText - **type**: string @@ -227,7 +231,7 @@ settings: { ### badgeCounter - **type**: object -- **description**: adds a badge with a number and a label to a node. Nodes that are part of a category show a cumulated number of all badges in this category. **badgeCounter** is only available for top navigation items. +- **description**: adds a badge with a number and a label to a node. Nodes that are part of a category show a cumulated number of all badges in this category. - **attributes**: - **label** is the label of the badge. - **count** is a function or asynchronous function that returns a number. diff --git a/package.json b/package.json index 348a2f0bb4..c086613f2e 100644 --- a/package.json +++ b/package.json @@ -27,14 +27,13 @@ "breaking": ":boom: Breaking Change", "enhancement": ":rocket: Added", "bug": ":bug: Fixed", - "documentation": ":memo: Documentation", "internal": ":house: Internal" }, "cacheDir": ".changelog" }, "husky": { "hooks": { - "pre-commit": "./scripts/hooks/apply-formatters.sh && ./scripts/hooks/remove-test-prefixes.sh && ./scripts/hooks/generate-docu.sh && ./scripts/hooks/prevent-illegal-characters.sh" + "pre-commit": "./scripts/hooks/apply-formatters.sh && ./scripts/hooks/remove-test-prefixes.sh && ./scripts/hooks/generate-docu.sh && ./scripts/hooks/generate-website-blog.sh && ./scripts/hooks/prevent-illegal-characters.sh" } } } diff --git a/plugins/auth/public/auth-oauth2/package.json b/plugins/auth/public/auth-oauth2/package.json index 961d82d442..808e8529a0 100644 --- a/plugins/auth/public/auth-oauth2/package.json +++ b/plugins/auth/public/auth-oauth2/package.json @@ -1,6 +1,6 @@ { "name": "@luigi-project/plugin-auth-oauth2", - "version": "1.2.1", + "version": "1.2.4", "description": "OAuth2 implicit grant provider plugin for @luigi-project/core", "license": "Apache-2.0", "main": "plugin.js", diff --git a/plugins/auth/public/auth-oidc/package.json b/plugins/auth/public/auth-oidc/package.json index a5c5c7e50d..c1e16e4731 100644 --- a/plugins/auth/public/auth-oidc/package.json +++ b/plugins/auth/public/auth-oidc/package.json @@ -1,6 +1,6 @@ { "name": "@luigi-project/plugin-auth-oidc", - "version": "1.2.1", + "version": "1.2.4", "description": "OpenID Connect provider plugin for @luigi-project/core", "license": "Apache-2.0", "main": "plugin.js", diff --git a/plugins/package-lock.json b/plugins/package-lock.json index 233cf7b0d9..4f8eb10054 100644 --- a/plugins/package-lock.json +++ b/plugins/package-lock.json @@ -2737,8 +2737,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -2759,14 +2758,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2781,20 +2778,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2911,8 +2905,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2924,7 +2917,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2939,7 +2931,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2947,14 +2938,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2973,7 +2962,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3054,8 +3042,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3067,7 +3054,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3153,8 +3139,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -3190,7 +3175,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3210,7 +3194,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3254,14 +3237,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/scripts/hooks/generate-website-blog.sh b/scripts/hooks/generate-website-blog.sh new file mode 100755 index 0000000000..b40f1ddba9 --- /dev/null +++ b/scripts/hooks/generate-website-blog.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Checks if there are changes in blog or website folder +# and generates website if necessary +# Run this script only from Luigi root folder, else git adding won't work. +# ./scripts/hooks/generate-website-blog.sh + +function check_and_generate_website() { + staged_changes=$(git diff --cached --name-only --diff-filter=ACM | grep -e "website/landingpage/" -e "blog/" | wc -l) + if [[ "$staged_changes" != *"0"* ]]; then + echo "Changes in website or blog found. Building landingpage" + BASE=`pwd` + cd website/landingpage/dev + npm run build + RES=$? + cd $BASE; + if [ "$RES" != 0 ]; then + echo "lerna run build.website failed." + exit 1; + fi + + if [ -z "$staged_changes" ]; then + echo "No website or blog changes found. Ok" + else + not_staged_md=$(git diff --name-only | grep -e "website/landingpage") + untracked_landingpage=$(git ls-files -o --exclude-standard | grep "landingpage/public") + if [ ! -z "$not_staged_md" ] || [ ! -z "$untracked_landingpage" ]; then + echo "Staging generated website files" + if [ ! -z "$not_staged_md" ]; then + echo "$not_staged_md" + echo "$not_staged_md" | xargs git add + fi + if [ ! -z "$untracked_landingpage" ]; then + echo "$untracked_landingpage" + echo "$untracked_landingpage" | xargs git add + fi + exit 0 + else + echo "No website or blog changes found. Ok" + fi + fi + fi +} + +check_and_generate_website + +exit 0 diff --git a/test/e2e-test-application/e2e/support/commands.js b/test/e2e-test-application/e2e/support/commands.js index 1b870058cb..49dbaa980e 100644 --- a/test/e2e-test-application/e2e/support/commands.js +++ b/test/e2e-test-application/e2e/support/commands.js @@ -1,32 +1,87 @@ import fiddleConfig from '../configs/default'; + +const setAcceptedCookies = win => { + win.localStorage.setItem('cookiesAccepted', 'true'); +}; + +const setLoggedIn = win => { + const newTime = Date.now() + 6e4; + const newLuigiAuth = { + accessToken: 'thisisanaccesstokenthatisnotreallyneeded', + accessTokenExpirationDate: newTime, + idToken: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAiLCJzdWIiOiJtYXNrb3BhdG9sIiwiZXhwIjoxNjQzNzY0OTIwLCJhenAiOiJtYXNrb3BhdG9sIiwibm9uY2UiOiJidE5rWVZzc1FldVlWNmEyR1RVZm1wWVFFelBRN3c1ZENCbU54SG54IiwiZW1haWwiOiJsdWlnaXVzZXJAa3ltYS5jeCIsIm5hbWUiOiJMdWlnaSBVc2VyIn0.YUBE3tufmmNIJHwzKRXlImteuh_qDeuwGjkzN3Z0erg' + }; + const key = 'luigi.auth'; + win.localStorage.setItem(key, JSON.stringify(newLuigiAuth)); +}; + +const setLuigiConfig = (win, config) => { + const intv = setInterval(function() { + if (win.Luigi) { + win.Luigi.setConfig(config); + clearInterval(intv); + } + }, 20); +}; + Cypress.Commands.add( 'visitWithFiddleConfig', (path = '/', config = fiddleConfig) => { cy.visit(`http://localhost:8080/#${path}`, { onBeforeLoad: win => { - win.localStorage.setItem('cookiesAccepted', 'true'); - var intv = setInterval(function() { - if (win.Luigi) { - win.Luigi.setConfig(config); - clearInterval(intv); - } - }, 20); + win.localStorage.clear(); + win.sessionStorage.clear(); + setAcceptedCookies(win); + setLuigiConfig(win, config); } }); } ); +Cypress.Commands.add( + 'visitWithFiddleConfigString', + (path = '/', config = fiddleConfig) => { + cy.visit(`http://localhost:8080/#${path}`, { + onBeforeLoad: win => { + win.localStorage.clear(); + win.sessionStorage.clear(); + setAcceptedCookies(win); + // Not using setLuigiConfig(win, config); + const strConfig = + typeof config === 'object' ? JSON.stringify(config) : config; + win.sessionStorage.setItem('fiddle', `Luigi.setConfig(${strConfig})`); + win.localStorage.setItem('fiddle', `Luigi.setConfig(${strConfig})`); + } + }); + } +); + +Cypress.Commands.add( + 'visitLoggedInWithFiddleConfig', + (path = '/', config = fiddleConfig) => { + cy.visit(`http://localhost:8080/#${path}`, { + onBeforeLoad: win => { + win.localStorage.clear(); + win.sessionStorage.clear(); + setAcceptedCookies(win); + setLoggedIn(win); + + const strConfig = + typeof config === 'object' ? JSON.stringify(config) : config; + win.sessionStorage.setItem('fiddle', `Luigi.setConfig(${strConfig})`); + win.localStorage.setItem('fiddle', `Luigi.setConfig(${strConfig})`); + } + }); + } +); + Cypress.Commands.add('visitLoggedIn', (path = '/') => { cy.visit(path, { onBeforeLoad: win => { - const newTime = Date.now() + 6e4; - const newLuigiAuth = { - accessToken: 'thisisanaccesstokenthatisnotreallyneeded', - accessTokenExpirationDate: newTime, - idToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAiLCJzdWIiOiJtYXNrb3BhdG9sIiwiZXhwIjoxNjQzNzY0OTIwLCJhenAiOiJtYXNrb3BhdG9sIiwibm9uY2UiOiJidE5rWVZzc1FldVlWNmEyR1RVZm1wWVFFelBRN3c1ZENCbU54SG54IiwiZW1haWwiOiJsdWlnaXVzZXJAa3ltYS5jeCIsIm5hbWUiOiJMdWlnaSBVc2VyIn0.YUBE3tufmmNIJHwzKRXlImteuh_qDeuwGjkzN3Z0erg' - }; - const key = 'luigi.auth'; - win.localStorage.setItem(key, JSON.stringify(newLuigiAuth)); + win.localStorage.clear(); + win.sessionStorage.clear(); + setAcceptedCookies(win); + setLoggedIn(win); } }); }); @@ -37,14 +92,14 @@ Cypress.Commands.add( cy.get('.fd-input') .first() .clear() - .type('tets@email.com') - .should('have.value', 'tets@email.com'); + .type(email) + .should('have.value', email); cy.get('.fd-input') .last() .clear() - .type('tets') - .should('have.value', 'tets'); + .type(password) + .should('have.value', password); cy.get('.fd-button').click(); diff --git a/test/e2e-test-application/e2e/tests/0-fiddle/fiddle-navigation.spec.js b/test/e2e-test-application/e2e/tests/0-fiddle/fiddle-navigation.spec.js index b3d916e246..542bbee926 100644 --- a/test/e2e-test-application/e2e/tests/0-fiddle/fiddle-navigation.spec.js +++ b/test/e2e-test-application/e2e/tests/0-fiddle/fiddle-navigation.spec.js @@ -1,4 +1,6 @@ import fiddleConfig from '../../configs/default'; +import { cloneDeep } from 'lodash'; + Cypress.env('RETRIES', 1); describe('Fiddle', () => { describe('Navigation', () => { @@ -28,7 +30,7 @@ describe('Fiddle', () => { }); describe('Normal navigation', () => { beforeEach(() => { - const newConfig = Object.assign({}, fiddleConfig); + const newConfig = cloneDeep(fiddleConfig); newConfig.navigation.nodes[0].viewUrl = null; cy.visitWithFiddleConfig('/', newConfig); }); @@ -41,7 +43,7 @@ describe('Fiddle', () => { }); describe('virtualTree with fromVirtualTreeRoot', () => { beforeEach(() => { - const newConfig = Object.assign({}, fiddleConfig); + const newConfig = cloneDeep(fiddleConfig); newConfig.navigation.nodes.push({ pathSegment: 'virtual', label: 'Virtual', @@ -61,7 +63,7 @@ describe('Fiddle', () => { }); describe('context switcher', () => { beforeEach(() => { - let newConfig = Object.assign({}, fiddleConfig); + const newConfig = cloneDeep(fiddleConfig); newConfig.navigation.nodes.push({ hideFromNav: true, pathSegment: 'environments', @@ -123,7 +125,8 @@ describe('Fiddle', () => { }); describe('Unload and load Luigi', () => { beforeEach(() => { - cy.visitWithFiddleConfig('/home/two', fiddleConfig); + const newConfig = cloneDeep(fiddleConfig); + cy.visitWithFiddleConfig('/home/two', newConfig); }); it('Core API unload', () => { let config; @@ -153,4 +156,160 @@ describe('Fiddle', () => { cy.get('.fd-shellbar').should('be.visible'); }); }); + describe('Show-hide of Logout & Login Buttons', () => { + const loginLink = () => { + return cy.get('[data-testid="login-link"]'); + }; + const logoutLink = () => { + return cy.get('[data-testid="logout-link"]'); + }; + describe('No Auth', () => { + beforeEach(() => { + const newConfig = cloneDeep(fiddleConfig); + newConfig.auth = undefined; + newConfig.navigation.profile = { + logout: { + label: 'Bye bye', + icon: 'sys-cancel' + }, + staticUserInfoFn: () => ({ + name: 'Static User', + email: 'other.luigi.user@example.com', + picture: '/assets/github-logo.png' + }) + }; + cy.visitWithFiddleConfig('/home/two', newConfig); + }); + it('Static profile, and logging out with customLogoutFn', () => { + cy.get('[data-testid="luigi-topnav-profile"] button').click(); + logoutLink().should('exist'); + loginLink().should('not.exist'); + + let profileLogout; + cy.window().then(win => { + const config = win.Luigi.getConfig(); + profileLogout = config.navigation.profile.logout; + profileLogout.customLogoutFn = () => { + return true; + }; + cy.spy(profileLogout, 'customLogoutFn'); + win.Luigi.setConfig(config); + win.Luigi.configChanged('navigation.profile'); + }); + + // Verify profile value + logoutLink() + .contains('Bye bye') + .click(); + + // need to wrap 'expect' into some cypress function, else it executes immediately + cy.window().then(win => { + expect(profileLogout.customLogoutFn).to.be.called; + }); + }); + }); + describe('With Auth', () => { + let newConfig; + + const visitLoggedInWithAuthConfig = (path = '/', newConfig) => { + const strConfig = JSON.stringify(newConfig).replace( + '"OAUTH2_PROVIDER"', + 'window.LuigiAuthOAuth2' + ); // workaround else it would just be undefined + cy.visitLoggedInWithFiddleConfig(path, strConfig); + }; + const visitWithAuthConfig = (path = '/', newConfig) => { + const strConfig = JSON.stringify(newConfig).replace( + '"OAUTH2_PROVIDER"', + 'window.LuigiAuthOAuth2' + ); // workaround else it would just be undefined + cy.visitWithFiddleConfigString(path, strConfig); + }; + + beforeEach(() => { + newConfig = cloneDeep(fiddleConfig); + newConfig.auth = { + use: 'myOAuth2', + myOAuth2: { + idpProvider: 'OAUTH2_PROVIDER', + authorizeUrl: '/auth/idpmock/implicit.html', + logoutUrl: '/auth/idpmock/logout.html', + post_logout_redirect_uri: '/auth/logout.html', + authorizeMethod: 'GET', + oAuthData: { + client_id: 'egDuozijY5SVr0NSIowUP1dT6RVqHnlp', + redirect_uri: '/auth/callback.html' + } + } + }; + newConfig.navigation.profile = { + logout: { + label: 'Bye bye', + icon: 'sys-cancel' + } + }; + }); + + it('Profile, no auto-login, logged out', () => { + newConfig.auth.disableAutoLogin = true; + visitWithAuthConfig('/', newConfig); + + cy.get('[data-testid="luigi-topnav-profile"] button').click(); + logoutLink().should('not.exist'); + loginLink().should('exist'); + }); + it('No Profile, no auto-login, logged out and login', () => { + newConfig.auth.disableAutoLogin = true; + newConfig.navigation.profile = undefined; + visitWithAuthConfig('/', newConfig); + + // Logged out + cy.get('[data-testid="luigi-topnav-profile"] button').click(); + logoutLink().should('not.exist'); + loginLink().should('exist'); + + // Log in + loginLink().click(); + cy.login('tets@email.com', 'tets', true); + + // Logged in + cy.get('[data-testid="luigi-topnav-profile"] button').click(); + loginLink().should('not.exist'); + logoutLink().should('exist'); + + // Verify default value + logoutLink().contains('Sign Out'); + }); + + it('Profile, logged in', () => { + newConfig.navigation.profile = { + logout: { + label: 'Bye bye', + icon: 'sys-cancel' + } + }; + newConfig.auth.disableAutoLogin = false; + visitLoggedInWithAuthConfig('/', newConfig); + + cy.get('[data-testid="luigi-topnav-profile"] button').click(); + logoutLink().should('exist'); + loginLink().should('not.exist'); + + // Verify profile value + logoutLink().contains('Bye bye'); + }); + it('No profile, logged in', () => { + newConfig.navigation.profile = undefined; + newConfig.auth.disableAutoLogin = false; + visitLoggedInWithAuthConfig('/', newConfig); + + cy.get('[data-testid="luigi-topnav-profile"] button').click(); + logoutLink().should('exist'); + loginLink().should('not.exist'); + + // Verify default value + logoutLink().contains('Sign Out'); + }); + }); + }); }); diff --git a/test/e2e-test-application/e2e/tests/1-angular/navigation.spec.js b/test/e2e-test-application/e2e/tests/1-angular/navigation.spec.js index 1ceda71895..be674fdd78 100644 --- a/test/e2e-test-application/e2e/tests/1-angular/navigation.spec.js +++ b/test/e2e-test-application/e2e/tests/1-angular/navigation.spec.js @@ -172,6 +172,11 @@ describe('Navigation', () => { cy.get('button[title="Settings"]').should('contain', ''); }); + it('Icon with label label in TopNav', () => { + cy.get('button[data-testid="icon-and-label"]>.fd-top-nav__icon').should('exist'); + cy.get('button[data-testid="icon-and-label"]').should('contain', 'Git'); + }); + it('Icon with label in LeftNav', () => { cy.get('.fd-shellbar') .contains('Projects') diff --git a/test/e2e-test-application/src/luigi-config/extended/navigation.js b/test/e2e-test-application/src/luigi-config/extended/navigation.js index 409ca023db..295dce680f 100644 --- a/test/e2e-test-application/src/luigi-config/extended/navigation.js +++ b/test/e2e-test-application/src/luigi-config/extended/navigation.js @@ -75,6 +75,17 @@ class Navigation { viewUrl: '/sampleapp.html#/restricted', constraints: ['unicorns'] }, + { + externalLink: { + url: 'https://github.com/SAP/luigi', + sameWindow: true + }, + label: 'Git', + icon: 'globe', + showLabel: true, + hideSideNav: false, + testId: "icon-and-label" + }, { pathSegment: 'settings', label: 'Settings', @@ -83,6 +94,7 @@ class Navigation { hideSideNav: true, viewGroup: 'tets' }, + { category: { label: 'Misc', icon: 'badge' }, label: 'Open Google in this tab', @@ -91,6 +103,7 @@ class Navigation { sameWindow: true } }, // showing an anonymous content is possible only with auto login disabled + { category: 'Misc', pathSegment: 'all-users', @@ -135,6 +148,7 @@ class Navigation { } ] }, + { pathSegment: 'page-not-found', label: 'Page not found', diff --git a/test/e2e-test-application/src/luigi-config/extended/projectDetailNav.js b/test/e2e-test-application/src/luigi-config/extended/projectDetailNav.js index 6e30498ec7..e9a0ffff60 100644 --- a/test/e2e-test-application/src/luigi-config/extended/projectDetailNav.js +++ b/test/e2e-test-application/src/luigi-config/extended/projectDetailNav.js @@ -62,7 +62,11 @@ export const projectDetailNavStructure = projectId => [ pathSegment: 'developers', label: 'Developers', viewUrl: '/sampleapp.html#/projects/' + projectId + '/developers', - icon: 'employee' + icon: 'employee', + badgeCounter: { + label: 'Number of developers', + count: () => Math.floor(Math.random() * 100) + } }, { pathSegment: 'clientPermissionsTets', diff --git a/test/e2e-test-application/src/luigi-config/extended/projectDetailTabNav.js b/test/e2e-test-application/src/luigi-config/extended/projectDetailTabNav.js index b50946f91e..549c8a9b3b 100644 --- a/test/e2e-test-application/src/luigi-config/extended/projectDetailTabNav.js +++ b/test/e2e-test-application/src/luigi-config/extended/projectDetailTabNav.js @@ -11,7 +11,11 @@ export const projectDetailTabNavStructure = projectId => [ pathSegment: 'developers', label: 'Developers', viewUrl: '/sampleapp.html#/projects/' + projectId + '/developers', - icon: '/assets/favicon-sap.ico' + icon: '/assets/favicon-sap.ico', + badgeCounter: { + label: 'Number of developers', + count: () => 100 + } }, { pathSegment: 'clientPermissionsTets', diff --git a/website/docs/src/client-js/internal-links.js b/website/docs/src/client-js/internal-links.js index 4945c142e5..0febc2bcfb 100644 --- a/website/docs/src/client-js/internal-links.js +++ b/website/docs/src/client-js/internal-links.js @@ -32,8 +32,12 @@ export class InternalLinksHandler { console.debug('navigateInternal URL parse error', elem, elem.getAttribute('href'), error); } const urlWithPath = url.pathname.replace(ctx.coreBaseUrl, '').replace('.md', '').replace('/docu-microfrontend', ''); - if (url.hash) { - LuigiClient.linkManager().withParams({'section': url.hash.substring(1).toLowerCase()}).navigate(urlWithPath); + + // Links can be either with a ?section param or with hash, both should work. + const sectionParam = this.getUrlParameter('section', url.search); + const hashParam = url.hash ? url.hash.substring(1).toLowerCase() : false; + if (sectionParam || hashParam) { + LuigiClient.linkManager().withParams({'section': sectionParam || hashParam}).navigate(urlWithPath); } else { LuigiClient.linkManager().navigate(urlWithPath); } @@ -50,4 +54,17 @@ export class InternalLinksHandler { } }); } + + + /** + * Returns the value of a given url parameter name + * Original source: Luigi Core GenericHelpers + * @param {string} name + */ + getUrlParameter(name, locationSearch = window.location.search) { + name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); + var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); + var result = regex.exec(locationSearch); + return (result && decodeURIComponent(result[1].replace(/\+/g, ' '))) || ''; + } } diff --git a/website/docs/src/luigi-config/extended/navigation.js b/website/docs/src/luigi-config/extended/navigation.js index 037272a0b6..1d64bc4757 100644 --- a/website/docs/src/luigi-config/extended/navigation.js +++ b/website/docs/src/luigi-config/extended/navigation.js @@ -40,6 +40,13 @@ class Navigation { coreBaseUrl: window.location.origin } }, + { + label: 'Blog', + externalLink: { + url: 'https://luigi-project.io/blog', + sameWindow: true + } + }, { label: 'Twitter', externalLink: { diff --git a/website/docs/src/luigi-config/styles/index.scss b/website/docs/src/luigi-config/styles/index.scss index ef4b7328c7..34f0a50802 100644 --- a/website/docs/src/luigi-config/styles/index.scss +++ b/website/docs/src/luigi-config/styles/index.scss @@ -166,9 +166,8 @@ $side-nav-width-mobile: 260px; } .fd-menu__item { - font-size: 16px; padding: 15px 0; - color: white; + background-color: transparent; &:hover, &:active, @@ -176,12 +175,30 @@ $side-nav-width-mobile: 260px; &[aria-selected=true] { color: $primary-color; } - } + + .fd-menu__link { + &.is-hover, + &:hover { + background-color: transparent; + .fd-menu__title{ + color: $primary-color; + } + } + &.is-selected, + &[aria-selected=true] { + background-color: transparent; + border-bottom: none; + .fd-menu__title{ + color: $primary-color; + background-color: none; + } + } - .fd-menu__item, - .fd-menu__item.is-selected, - .fd-menu__item[aria-selected=true] { - background-color: transparent; + .fd-menu__title{ + color: #fff; + font-weight: 600; + } + } } .fd-top-nav__icon, @@ -192,6 +209,7 @@ $side-nav-width-mobile: 260px; li { border-bottom: 1px solid $border-color; + border-radius: 0; } } } @@ -275,8 +293,6 @@ $side-nav-width-mobile: 260px; left: $side-nav-width-desktop; } - - .fd-app__sidebar { box-shadow: none; background-color: #fafbfc; @@ -290,9 +306,6 @@ $side-nav-width-mobile: 260px; } } - - - .lui-customlogo { img { width: 118px; @@ -425,8 +438,9 @@ $side-nav-width-mobile: 260px; .fd-nested-list__icon { display: none; } - } + } + .lui-category { text-transform: uppercase; border: none; diff --git a/website/fiddle/package-lock.json b/website/fiddle/package-lock.json index 6531b85c19..9e1f70aa89 100644 --- a/website/fiddle/package-lock.json +++ b/website/fiddle/package-lock.json @@ -3,30 +3,10 @@ "requires": true, "lockfileVersion": 1, "dependencies": { - "@luigi-project/client": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@luigi-project/client/-/client-1.2.1.tgz", - "integrity": "sha512-OG2Cd/ZvVFr9CU9PvDgzbsP1ZzKQkhFcnwUNvWVwVGtSGztpt9zvwmtK3iwlSfVo1FFDoYUIhsL1o/1ucP4VIg==" - }, - "@luigi-project/core": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@luigi-project/core/-/core-1.2.1.tgz", - "integrity": "sha512-XeLvRmcphxP15KTAyt/E/jdoOLIZlFd4Ij5BUCKDi3LdpUdwLNL4mEA+1TdGpnO554JJvnK4fA+00G0E0xuBgQ==" - }, - "@luigi-project/plugin-auth-oauth2": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@luigi-project/plugin-auth-oauth2/-/plugin-auth-oauth2-1.2.1.tgz", - "integrity": "sha512-R9wEwPRsWxLRqC3uifUbCUDgZdlBYN3nszH0CVFnjP3XNBcDptePT4jeeFME+aS/uvEFoSbgZhRlaciJRexdAQ==" - }, - "@luigi-project/plugin-auth-oidc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@luigi-project/plugin-auth-oidc/-/plugin-auth-oidc-1.2.1.tgz", - "integrity": "sha512-VbumviodwO+hoq4APmhFCrTiRtr8xh2BhfbZjdBdnsIDBgyS0WFZRTI93VFdz1TGu/AxD3VIGNuGrfiG4aLoUQ==" - }, "@sap-theming/theming-base-content": { - "version": "11.1.18", - "resolved": "https://registry.npmjs.org/@sap-theming/theming-base-content/-/theming-base-content-11.1.18.tgz", - "integrity": "sha512-NDqUq35hc/eZQomLhsDQEO8PeCnNCZmJIittafuho5VlGNdJWR1ZsXj97MZSJnLLfttVWcpb5KNrj+b84F6aAw==" + "version": "11.1.19", + "resolved": "https://registry.npmjs.org/@sap-theming/theming-base-content/-/theming-base-content-11.1.19.tgz", + "integrity": "sha512-0RIoniX0XgQDMfMsySvNDeXVGtH3UQRQMkJYFIkaq/nrTGSyfXT9k+B4CbTf4546dyrlLM0YoaHIOtxmMsh1ZA==" }, "@types/events": { "version": "3.0.0", @@ -2766,9 +2746,9 @@ "dev": true }, "fundamental-styles": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/fundamental-styles/-/fundamental-styles-0.8.1.tgz", - "integrity": "sha512-lP29Hi4esdf9lOa3l1uMncTjnROR9sLjxM27InrztADa228H8Ry5LRqI7nJJTEfqo/e53QKVRjbZo3B1+hqqFg==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/fundamental-styles/-/fundamental-styles-0.10.0.tgz", + "integrity": "sha512-Y5kK1Y4wSgzJaW6rLVS6VXZGIPSmhjnPIFZ0R52KEsEKocR6BsWjWIY8XakeBs0VZaOFPwHEwSxacTXkIp2/jg==" }, "get-caller-file": { "version": "2.0.5", diff --git a/website/fiddle/package.json b/website/fiddle/package.json index 4208a20547..1ac2647cc8 100644 --- a/website/fiddle/package.json +++ b/website/fiddle/package.json @@ -24,8 +24,8 @@ "@luigi-project/core": "1.2.1", "@luigi-project/plugin-auth-oauth2": "1.2.1", "@luigi-project/plugin-auth-oidc": "1.2.1", - "@sap-theming/theming-base-content": "^11.1.18", + "@sap-theming/theming-base-content": "11.1.19", "ace-builds": "1.4.11", - "fundamental-styles": "0.8.1" + "fundamental-styles": "0.10.0" } } diff --git a/website/fiddle/public/examples/microfrontends/fundamental/table-demo-page.html b/website/fiddle/public/examples/microfrontends/fundamental/table-demo-page.html index 65e9ed4f2e..83d4ea078e 100644 --- a/website/fiddle/public/examples/microfrontends/fundamental/table-demo-page.html +++ b/website/fiddle/public/examples/microfrontends/fundamental/table-demo-page.html @@ -32,12 +32,12 @@

    -
    -
    -

    +
    +
    +

    Items (1180)

    -
    +
    @@ -59,7 +59,7 @@

    -