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

Custom item renderer for app switcher #2674

Merged
merged 27 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
29df945
custom item renderer
JohannesDoberer Apr 19, 2022
4a246bd
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Apr 19, 2022
cf48cd7
docu suggestion
JohannesDoberer Apr 20, 2022
0068fb0
Merge branch 'master' into custom-renderer-for-app-switcher
stanleychh Apr 25, 2022
298b18f
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Apr 25, 2022
1e3c5cd
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Apr 25, 2022
a4da5ec
Merge branch 'master' into custom-renderer-for-app-switcher
stanleychh Apr 27, 2022
bd94724
Merge branch 'master' into custom-renderer-for-app-switcher
stanleychh Apr 27, 2022
7c7a24e
Update core/src/navigation/LogoTitle.svelte
JohannesDoberer Apr 27, 2022
37cea0c
suggestions
JohannesDoberer Apr 27, 2022
09e61d6
Merge branch 'custom-renderer-for-app-switcher' of github.com:SAP/lui…
JohannesDoberer Apr 27, 2022
1990628
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Apr 27, 2022
0e26e78
suggestions
JohannesDoberer Apr 27, 2022
87fec67
Merge branch 'custom-renderer-for-app-switcher' of github.com:SAP/lui…
JohannesDoberer Apr 27, 2022
e9abba1
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Apr 29, 2022
32ae7c6
Merge branch 'master' into custom-renderer-for-app-switcher
UlianaMunich May 12, 2022
d873ed1
Merge branch 'master' into custom-renderer-for-app-switcher
UlianaMunich May 18, 2022
620ddc3
resolve merge conflict
JohannesDoberer Jun 27, 2022
d7ce605
close dropdown
JohannesDoberer Jun 29, 2022
7b534c0
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Jun 29, 2022
2f645fd
Merge branch 'custom-renderer-for-app-switcher' of github.com:SAP/lui…
JohannesDoberer Jun 29, 2022
cf017bf
suggestions
JohannesDoberer Jul 6, 2022
7b460bc
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Jul 6, 2022
56142aa
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Jul 6, 2022
c56bd51
Merge branch 'master' into custom-renderer-for-app-switcher
stanleychh Jul 7, 2022
8e3849f
renaming
JohannesDoberer Jul 8, 2022
ab1e506
Merge branch 'master' into custom-renderer-for-app-switcher
JohannesDoberer Jul 8, 2022
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
51 changes: 39 additions & 12 deletions core/src/navigation/LogoTitle.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { beforeUpdate, createEventDispatcher, onMount, getContext } from 'svelte';
import * as Header from './services/header';
import { Routing } from '../services/routing';
import { NavigationHelpers, RoutingHelpers } from '../utilities/helpers';
import { NavigationHelpers, RoutingHelpers, GenericHelpers } from '../utilities/helpers';

const dispatch = createEventDispatcher();

Expand All @@ -15,11 +15,13 @@
export let selectedItem;
export let defaultTitle;
export let appSwitcherItems;
export let customAppSwitcherItemRenderer;
export let pathParams;
export let subTitle;
export let defaultSubTitle;
export let pathData;
export let addNavHrefForAnchor;
let luigiCustomAppSwitcherItemRenderer__slotContainer;
let previousPathData;
let getUnsavedChangesModalPromise = getContext('getUnsavedChangesModalPromise');
let getTranslation = getContext('getTranslation');
Expand All @@ -33,6 +35,7 @@
pathData,
pathParams,
appSwitcherItems,
customAppSwitcherItemRenderer,
selectedItem,
defaultTitle,
title,
Expand All @@ -51,7 +54,9 @@
pathData = obj.pathData;
} else if (prop === 'appSwitcherItems') {
appSwitcherItems = obj.appSwitcherItems;
} else if (prop === 'pathParams') {
} else if (prop === 'customAppSwitcherItemRenderer') {
customAppSwitcherItemRenderer = obj.customAppSwitcherItemRenderer;
}else if (prop === 'pathParams') {
JohannesDoberer marked this conversation as resolved.
Show resolved Hide resolved
pathParams = obj.pathParams;
} else if (prop === 'selectedItem') {
selectedItem = obj.selectedItem;
Expand Down Expand Up @@ -90,6 +95,13 @@
}
});

function renderCustomList(item, slot){
setTimeout(()=>{
customAppSwitcherItemRenderer(item,slot);
});
return '';
}

export function goTo(path) {
getUnsavedChangesModalPromise().then(() => {
Routing.navigateTo(RoutingHelpers.applyPathParams(path, pathParams));
Expand Down Expand Up @@ -138,8 +150,9 @@
? 'fd-shellbar__logo--image-replaced'
: ''} {hasLogo ? 'lui-customlogo' : ''}"
aria-label={title}
on:click={(event) => {
NavigationHelpers.handleNavAnchorClickedWithoutMetaKey(event) && goTo('/');
on:click={event => {
NavigationHelpers.handleNavAnchorClickedWithoutMetaKey(event) &&
goTo('/');
}}
href="/"
role="button"
Expand Down Expand Up @@ -170,8 +183,9 @@
<a
class="fd-shellbar__title lui-shellbar-single-app-title"
data-testid="luigi-topnav-title"
on:click={(event) => {
NavigationHelpers.handleNavAnchorClickedWithoutMetaKey(event) && goTo('/');
on:click={event => {
NavigationHelpers.handleNavAnchorClickedWithoutMetaKey(event) &&
goTo('/');
}}
href="/"
>
Expand All @@ -191,8 +205,9 @@
{#if addNavHrefForAnchor}
{#if appSwitcherItems && appSwitcherItems.length === 1}
<a
href="{getRouteLink(appSwitcherItems[0])}"
class="fd-shellbar__title lui-shellbar-single-app-title">
href={getRouteLink(appSwitcherItems[0])}
class="fd-shellbar__title lui-shellbar-single-app-title"
>
<span>
{$getTranslation(appSwitcherItems[0].title)}
</span>
Expand Down Expand Up @@ -262,7 +277,10 @@
id="appSwitcherPopover"
>
<nav class="fd-menu">
<ul class="fd-menu__list fd-menu__list--no-shadow">
<ul
class="fd-menu__list fd-menu__list--no-shadow"
bind:this={luigiCustomAppSwitcherItemRenderer__slotContainer}
>
{#if showMainAppEntry && selectedItem}
<li class="fd-menu__item">
<a
Expand All @@ -280,13 +298,22 @@
{/if}
{#if appSwitcherItems && appSwitcherItems.length > 0}
{#each appSwitcherItems as item}
{#if item !== selectedItem && hasValidLink(item, pathParams)}
{#if GenericHelpers.isFunction(customAppSwitcherItemRenderer)}
{#if luigiCustomAppSwitcherItemRenderer__slotContainer}
{@html renderCustomList(
item,
luigiCustomAppSwitcherItemRenderer__slotContainer
)}
{/if}
{:else if item !== selectedItem && hasValidLink(item, pathParams)}
<li class="fd-menu__item">
<a
role="button"
class="fd-menu__link"
on:click={(event) => {
NavigationHelpers.handleNavAnchorClickedWithoutMetaKey(event) && goTo(item.link);
on:click={event => {
NavigationHelpers.handleNavAnchorClickedWithoutMetaKey(
event
) && goTo(item.link);
}}
href={addNavHrefForAnchor
? getRouteLink(item, pathParams)
Expand Down
1 change: 1 addition & 0 deletions core/src/navigation/services/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const processHeaderSettings = component => {
if (appSwitcher) {
component.set({ appSwitcherItems: appSwitcher.items });
component.set({ showMainAppEntry: appSwitcher.showMainAppEntry });
component.set({ customAppSwitcherItemRenderer: appSwitcher.customAppSwitcherItemRenderer });
}
component.set({
hasApps:
Expand Down
6 changes: 6 additions & 0 deletions core/src/utilities/helpers/generic-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ class GenericHelpersClass {
* @returns {string} string without leading slash
*/
trimLeadingSlash(str) {
if (typeof str !== 'string') {
return '';
}
UlianaMunich marked this conversation as resolved.
Show resolved Hide resolved
return str.replace(/^\/+/g, '');
}

Expand All @@ -149,6 +152,9 @@ class GenericHelpersClass {
* @returns string string without any trailing slash
*/
trimTrailingSlash(str) {
if (typeof str !== 'string') {
return '';
}
return str.replace(/\/+$/, '');
}

Expand Down
39 changes: 39 additions & 0 deletions docs/navigation-parameters-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,45 @@ The app switcher is a drop-down list available in the top navigation bar. It all
- **type**: boolean
- **description**: includes the link to the root of the Luigi application in the drop-down using the **title** specified in the **settings/header** section of the configuration as a label.

### customAppSwitcherItemRenderer
- **type**: Function
- **description**: This function allows you to customize the single list element rendered in the default app switcher popover.
- **attributes**:
- **item** single application element
- **slot** `ul` element as slot. You can append your custom `li` entries to this `ul` element.
JohannesDoberer marked this conversation as resolved.
Show resolved Hide resolved
- **example**:
```javascript
appSwitcher: {
items:[...],
customAppSwitcherItemRenderer: (item, slot) => {
let li = document.createElement('li');
li.setAttribute('class', 'fd-menu__item');
let a = document.createElement('a');
a.setAttribute('class', 'fd-menu__link');
a.addEventListener('click', e => {
Luigi.navigation().navigate(item.link);
e.stopPropagation();
});
let span = document.createElement('span');
span.setAttribute('class', 'fd-menu__addon-before');
let i = document.createElement('i');
if (item.title === 'Application One') {
i.setAttribute('class', 'sap-icon--phone');
} else {
i.setAttribute('class', 'sap-icon--settings');
}
span.appendChild(i);
let spanText = document.createElement('span');
spanText.setAttribute('class', 'fd-menu__title');
spanText.innerText = item.title;
a.appendChild(span);
a.appendChild(spanText);
li.appendChild(a);
slot.appendChild(li);
}
}
```
- **since**: NEXTRELEASE

## Global search

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ describe('Fiddle', () => {
};
newConfig.navigation.nodes[0].children.push(node);
});

it('Add and delete search params path routing enabled', () => {
newConfig.routing.useHashRouting = false;
cy.visitFiddleConfigWithPathRouting('', newConfig);
Expand Down Expand Up @@ -1092,4 +1092,87 @@ describe('Fiddle', () => {
});
});
});
describe('Custom AppSwitcher List', () => {
let newConfig;
beforeEach(() => {
newConfig = cloneDeep(fiddleConfig);
newConfig.navigation.appSwitcher = {
showMainAppEntry: false,
customAppSwitcherItemRenderer: (item, slot) => {
let li = document.createElement('li');
li.setAttribute('class', 'fd-menu__item');
li.setAttribute('data-testid', `${item.title}`);
let a = document.createElement('a');
a.setAttribute('class', 'fd-menu__link');
a.addEventListener('click', e => {
Luigi.navigation().navigate(item.link);
e.stopPropagation();
});
let span = document.createElement('span');
span.setAttribute('class', 'fd-menu__addon-before');
if (item.title !== 'Luigi') {
let i = document.createElement('i');
if (item.title === 'Application One') {
i.setAttribute('class', 'sap-icon--phone');
} else {
i.setAttribute('class', 'sap-icon--settings');
}
span.appendChild(i);
} else {
let img = document.createElement('img');
img.setAttribute('src', 'https://team-phteven.gitlab.io/assets/phteven.png');
span.appendChild(img);
}
let spanText = document.createElement('span');
spanText.setAttribute('class', 'fd-menu__title');
spanText.innerText = item.title;
a.appendChild(span);
a.appendChild(spanText);
li.appendChild(a);
slot.appendChild(li);
},
items: [
{
title: 'Application One',
subTitle: 'the first app',
link: '/home/empty'
},
{
title: 'Application Two',
link: '/projects/pr2',
subTitle: 'the second app'
},
{
title: 'Luigi',
link: 'https://docs.luigi-project.io/',
subTitle: 'v1.18.0'
}
]
};
newConfig.settings.header = {
logo:
'data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MTIuMzggMjA0Ij48ZGVmcz48c3R5bGU+LmNscy0xLC5jbHMtMntmaWxsLXJ1bGU6ZXZlbm9kZH0uY2xzLTF7ZmlsbDp1cmwoI2xpbmVhci1ncmFkaWVudCl9LmNscy0ye2ZpbGw6I2ZmZn08L3N0eWxlPjxsaW5lYXJHcmFkaWVudCBpZD0ibGluZWFyLWdyYWRpZW50IiB4MT0iMjA2LjE5IiB4Mj0iMjA2LjE5IiB5Mj0iMjA0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjMDBiOGYxIi8+PHN0b3Agb2Zmc2V0PSIuMDIiIHN0b3AtY29sb3I9IiMwMWI2ZjAiLz48c3RvcCBvZmZzZXQ9Ii4zMSIgc3RvcC1jb2xvcj0iIzBkOTBkOSIvPjxzdG9wIG9mZnNldD0iLjU4IiBzdG9wLWNvbG9yPSIjMTc3NWM4Ii8+PHN0b3Agb2Zmc2V0PSIuODIiIHN0b3AtY29sb3I9IiMxYzY1YmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMxZTVmYmIiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48dGl0bGU+U0FQX2dyYWRfUl9zY3JuX1plaWNoZW5mbMOkY2hlIDE8L3RpdGxlPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTAgMjA0aDIwOC40MUw0MTIuMzggMEgwdjIwNCIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTI0NC43MyAzOC4zNmgtNDAuNnY5Ni41MmwtMzUuNDYtOTYuNTVoLTM1LjE2bC0zMC4yNyA4MC43MkMxMDAgOTguNyA3OSA5MS42NyA2Mi40IDg2LjQgNTEuNDYgODIuODkgMzkuODUgNzcuNzIgNDAgNzJjLjA5LTQuNjggNi4yMy05IDE4LjM4LTguMzggOC4xNy40MyAxNS4zNyAxLjA5IDI5LjcxIDhsMTQuMS0yNC41NUM4OS4wNiA0MC40MiA3MSAzNi4yMSA1Ni4xNyAzNi4xOWgtLjA5Yy0xNy4yOCAwLTMxLjY4IDUuNi00MC42IDE0LjgzQTM0LjIzIDM0LjIzIDAgMCAwIDUuNzcgNzQuN0M1LjU0IDg3LjE1IDEwLjExIDk2IDE5LjcxIDEwM2M4LjEgNS45NCAxOC40NiA5Ljc5IDI3LjYgMTIuNjIgMTEuMjcgMy40OSAyMC40NyA2LjUzIDIwLjM2IDEzQTkuNTcgOS41NyAwIDAgMSA2NSAxMzVjLTIuODEgMi45LTcuMTMgNC0xMy4wOSA0LjEtMTEuNDkuMjQtMjAtMS41Ni0zMy42MS05LjU5TDUuNzcgMTU0LjQyYTkzLjc3IDkzLjc3IDAgMCAwIDQ2IDEyLjIyaDIuMTFjMTQuMjQtLjI1IDI1Ljc0LTQuMzEgMzQuOTItMTEuNzEuNTMtLjQxIDEtLjg0IDEuNDktMS4yOGwtNC4xMiAxMC44NUgxMjNsNi4xOS0xOC44MmE2Ny40NiA2Ny40NiAwIDAgMCAyMS42OCAzLjQzIDY4LjMzIDY4LjMzIDAgMCAwIDIxLjE2LTMuMjVsNiAxOC42NGg2MC4xNHYtMzloMTMuMTFjMzEuNzEgMCA1MC40Ni0xNi4xNSA1MC40Ni00My4yIDAtMzAuMTEtMTguMjItNDMuOTQtNTcuMDEtNDMuOTR6TTE1MC45MSAxMjFhMzYuOTMgMzYuOTMgMCAwIDEtMTMtMi4yOGwxMi44Ny00MC41OWguMjJsMTIuNjUgNDAuNzFhMzguNSAzOC41IDAgMCAxLTEyLjc0IDIuMTZ6bTk2LjItMjMuMzNoLTguOTRWNjQuOTFoOC45NGMxMS45MyAwIDIxLjQ0IDQgMjEuNDQgMTYuMTQgMCAxMi42LTkuNTEgMTYuNTctMjEuNDQgMTYuNTciLz48L3N2Zz4=',
title: 'Luigi Demo',
favicon: '/assets/favicon-sap.ico'
};
});
it('Custom app switcher list renderer', () => {
cy.visitWithFiddleConfig('/', newConfig);
cy.get('.lui-app-switch')
.should('exist')
.click();
cy.get('[data-testid="Application One"]').should('exist');
cy.get('.sap-icon--phone').should('exist');
});
it('app switcher w/o custom renderer', () => {
delete newConfig.navigation.appSwitcher.customAppSwitcherItemRenderer;
cy.visitWithFiddleConfig('/', newConfig);
cy.get('.lui-app-switch')
.should('exist')
.click();
cy.get('[data-testid="Application One"]').should('not.exist');
cy.get('.sap-icon--phone').should('not.exist');
cy.get('#appSwitcherPopover').contains('Application One');
});
});
});