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 all 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
61 changes: 49 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,15 +15,22 @@
export let selectedItem;
export let defaultTitle;
export let appSwitcherItems;
export let itemRenderer;
export let pathParams;
export let subTitle;
export let defaultSubTitle;
export let pathData;
export let addNavHrefForAnchor;
let customItemRenderer__slotContainer;
let previousPathData;
let getUnsavedChangesModalPromise = getContext('getUnsavedChangesModalPromise');
let getTranslation = getContext('getTranslation');
let store = getContext('store');
const appSwitcherApiObj = {
closeDropDown: () => {
toggleDropdownState('appSwitcherPopover');
}
}

//TODO refactor
const getComponentWrapper = () => {
Expand All @@ -33,6 +40,7 @@
pathData,
pathParams,
appSwitcherItems,
itemRenderer,
selectedItem,
defaultTitle,
title,
Expand All @@ -51,6 +59,8 @@
pathData = obj.pathData;
} else if (prop === 'appSwitcherItems') {
appSwitcherItems = obj.appSwitcherItems;
} else if (prop === 'itemRenderer') {
itemRenderer = obj.itemRenderer;
} else if (prop === 'pathParams') {
pathParams = obj.pathParams;
} else if (prop === 'selectedItem') {
Expand Down Expand Up @@ -90,6 +100,15 @@
}
});

function renderCustomList(item, slot, index){
setTimeout(()=>{
if(slot){
itemRenderer(item, slot.children[index], appSwitcherApiObj);
}
});
return '';
}

export function goTo(path) {
getUnsavedChangesModalPromise().then(() => {
Routing.navigateTo(RoutingHelpers.applyPathParams(path, pathParams));
Expand Down Expand Up @@ -138,8 +157,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 +190,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 +212,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 +284,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={customItemRenderer__slotContainer}
>
{#if showMainAppEntry && selectedItem}
<li class="fd-menu__item">
<a
Expand All @@ -279,14 +304,26 @@
</li>
{/if}
{#if appSwitcherItems && appSwitcherItems.length > 0}
{#each appSwitcherItems as item}
{#if item !== selectedItem && hasValidLink(item, pathParams)}
{#each appSwitcherItems as item, index}
{#if GenericHelpers.isFunction(itemRenderer)}
{#if customItemRenderer__slotContainer}
<li class="fd-menu__item" tabindex="0">
{@html renderCustomList(
item,
customItemRenderer__slotContainer,
index
)}
</li>
{/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({ itemRenderer: appSwitcher.itemRenderer });
}
component.set({
hasApps:
Expand Down
8 changes: 6 additions & 2 deletions core/src/utilities/helpers/generic-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class GenericHelpersClass {
* @returns {string} string without leading slash
*/
trimLeadingSlash(str) {
return str.replace(/^\/+/g, '');
return this.isString(str) ? str.replace(/^\/+/g, '') : '';
}

/**
Expand All @@ -178,7 +178,7 @@ class GenericHelpersClass {
* @returns string string without any trailing slash
*/
trimTrailingSlash(str) {
return str.replace(/\/+$/, '');
return this.isString(str) ? str.replace(/\/+$/, '') : '';
}

getTrimmedUrl(path) {
Expand Down Expand Up @@ -396,6 +396,10 @@ class GenericHelpersClass {
getRemotePromise(id) {
return LuigiConfig._remotePromises ? LuigiConfig._remotePromises.promises[id] : undefined;
}

isString(value) {
return typeof value === 'string' || value instanceof String;
}
}

export const GenericHelpers = new GenericHelpersClass();
1 change: 1 addition & 0 deletions docs/luigi-core-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@ Add a feature toggle to an active feature toggles list
##### Parameters

- `featureToggleName` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the feature toggle
- `fromUrlQuery` (optional, default `false`)

##### Examples

Expand Down
43 changes: 42 additions & 1 deletion docs/navigation-parameters-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,48 @@ The app switcher is a dropdown list available in the top navigation bar. It allo
1. Define a [header object](general-settings.md#headerlogo) in the `settings:` section of your Luigi configuration.
2. Add the **appSwitcher** parameter to the **navigation** object using the optional parameters listed below.

### itemRenderer
- **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.
- **appSwitcherApiObj**
- **type**: Object
- **description**: It is an object with a function `closeDropDown` as property. This function closes the custom app switcher dropdown.
- **example**:
```javascript
appSwitcher: {
items:[...],
itemRenderer: (item, slot, appSwitcherApiObj) => {
let a = document.createElement('a');
a.setAttribute('class', 'fd-menu__link');
a.addEventListener('click', e => {
Luigi.navigation().navigate(item.link);
appSwitcherApiObj.closeDropDown();
e.stopPropagation();
Luigi.configChanged('navigation')
});
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);
slot.appendChild(a);
}
}
```
- **since**: NEXTRELEASE

### items
- **type**: array
- **description**: defines the list of application elements.
Expand All @@ -868,7 +910,6 @@ The app switcher is a dropdown list available in the top navigation bar. It allo
- **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.


## Global search

The global search is an input field available in the top navigation bar. The search is available if the Luigi configuration file contains on its root level a section called `globalSearch`. Within this section you can implement and configure a search provider object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ describe('Fiddle 2', () => {
beforeEach(() => {
newConfig = cloneDeep(fiddleConfig);
newConfig.settings.theming = {
themes: () => [{ id: 'light', name: 'Fiori3 Light' }, { id: 'dark', name: 'Fiori3 Dark' }],
themes: () => [
{ id: 'light', name: 'Fiori3 Light' },
{ id: 'dark', name: 'Fiori3 Dark' }
],
defaultTheme: 'light'
// nodeViewURLDecorator: {
// queryStringParameter: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ describe('Navigation', () => {
//Choose option one above French
cy.get('[data-testid="lui-us-language-dropdown"]')
.should('exist')
.type('{upArrow}').type('{enter}');
.type('{upArrow}')
.type('{enter}');

//Confirm with keyboard: Enter
cy.get('.fd-popover__body--dropdown-fill')
Expand All @@ -221,7 +222,8 @@ describe('Navigation', () => {
//Choose option one below English
cy.get('[data-testid="lui-us-language-dropdown"]')
.should('exist')
.type('{downArrow}').type('{enter}');
.type('{downArrow}')
.type('{enter}');

//Confirm with keyboard: Enter
cy.get('.fd-popover__body--dropdown-fill')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,8 @@ <h3 class="fd-layout-panel__title">
.navigate('/overview')
"
data-testid="navigate-withOptions-no-history-context"
>Go to /overview using withOptions() which makes no browser history be kept and no context updated.
>Go to /overview using withOptions() which makes no browser history be kept
and no context updated.
</a>
<app-code-snippet
data="linkManager().withOptions({preventHistoryEntry: true, preventContextUpdate:true}).navigate('/overview')"
Expand Down