Skip to content

Commit

Permalink
Node category merging improvements (SAP#2352)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesDoberer authored Nov 8, 2021
1 parent bde1963 commit d17e278
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 21 deletions.
2 changes: 2 additions & 0 deletions core/src/core-api/baseClass.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* istanbul ignore file */

/**
* @private
* @abstract
Expand Down
2 changes: 2 additions & 0 deletions core/src/core-api/globalsearch.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* istanbul ignore file */

/**
* Functions to use Luigi Global Search
* @name GlobalSearch
Expand Down
1 change: 1 addition & 0 deletions core/src/core-api/navigation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { linkManager } from './_internalLinkManager';

/* istanbul ignore file */
class LuigiNavigationManager {
/**
* Use these functions for navigation-related features.
Expand Down
2 changes: 2 additions & 0 deletions core/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import App from './App.html';
import { LuigiConfig, LuigiI18N, LuigiElements } from './core-api';
import { writable, readable } from 'svelte/store';
import { AuthLayerSvc } from './services';
/* istanbul ignore file */

const createConfigStore = () => {
const { subscribe, update, reset } = writable({});
const scopeSubscribers = {};
Expand Down
1 change: 1 addition & 0 deletions core/src/utilities/helpers/event-listener-helpers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* istanbul ignore file */
class EventListenerHelpersClass {
constructor() {
this.listeners = [];
Expand Down
52 changes: 34 additions & 18 deletions core/src/utilities/helpers/navigation-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class NavigationHelpersClass {
}

groupNodesBy(nodes, property, useVirtualGroups) {
const result = {};
let result = {};
let groupCounter = 0;
let virtualGroupCounter = 0;

Expand All @@ -114,8 +114,8 @@ class NavigationHelpersClass {
let key;
let metaInfo;
const category = node[property];
if (category && typeof category === 'object') {
key = category.label;
if (GenericHelpers.isObject(category)) {
key = category.id ? category.id : category.label;
metaInfo = Object.assign({}, category);
} else {
key = category;
Expand All @@ -141,13 +141,28 @@ class NavigationHelpersClass {
if (!arr.metaInfo) {
arr.metaInfo = metaInfo;
}
if (!arr.metaInfo.collapsible && metaInfo.collapsible) {
arr.metaInfo.collapsible = metaInfo.collapsible;
}
if (GenericHelpers.isObject(category) && category.id && category.label) {
arr.metaInfo = { ...arr.metaInfo, label: category.label, id: category.id };
}
if (!arr.metaInfo.categoryUid && key && arr.metaInfo.collapsible) {
arr.metaInfo.categoryUid = node.parent ? this.getNodePath(node.parent) + ':' + key : key;
}
if (!node.hideFromNav) {
arr.push(node);
}
});

Object.keys(result).forEach(category => {
const metaInfo = result[category].metaInfo;
if (metaInfo && metaInfo.id) {
result[metaInfo.label] = result[metaInfo.id];
delete result[metaInfo.id];
}
});

Object.keys(result).forEach(category => {
orderNodes(result[category]);
if (result[category].length === 0) {
Expand All @@ -157,6 +172,21 @@ class NavigationHelpersClass {
return result;
}

generateTooltipText(node, translation) {
let ttText = node.tooltipText;
if (ttText === undefined) {
ttText = LuigiConfig.getConfigValue('navigation.defaults.tooltipText');
}

if (ttText === undefined) {
return translation;
} else if (ttText === false) {
return '';
} else {
return LuigiI18N.getTranslation(ttText);
}
}

async generateTopNavNodes(pathData) {
const rawChildren = await Navigation.getFilteredChildren(pathData[0]);
let selectedNode = null;
Expand Down Expand Up @@ -306,6 +336,7 @@ class NavigationHelpersClass {
return undefined;
}

/* istanbul ignore next */
stripNode(node) {
const strippedNode = { ...node };
delete strippedNode.parent;
Expand Down Expand Up @@ -423,21 +454,6 @@ class NavigationHelpersClass {
reject(error);
});
}

generateTooltipText(node, translation) {
let ttText = node.tooltipText;
if (ttText === undefined) {
ttText = LuigiConfig.getConfigValue('navigation.defaults.tooltipText');
}

if (ttText === undefined) {
return translation;
} else if (ttText === false) {
return '';
} else {
return LuigiI18N.getTranslation(ttText);
}
}
}

export const NavigationHelpers = new NavigationHelpersClass();
1 change: 1 addition & 0 deletions core/src/utilities/keycode.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* istanbul ignore file */
export const KEYCODE_ARROW_UP = 38;
export const KEYCODE_ARROW_DOWN = 40;
export const KEYCODE_ENTER = 13;
Expand Down
55 changes: 54 additions & 1 deletion core/test/utilities/helpers/navigation-helpers.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ describe('Navigation-helpers', () => {
assert.equal(actual, false);
});
});

describe('node title data', () => {
let object;

Expand Down Expand Up @@ -442,5 +442,58 @@ describe('Navigation-helpers', () => {
assert.equal(titleData.label, 'Project');
});
});

describe('groupNodesBy', () => {
let nodes;
beforeEach(() => {
nodes = [
{
category: '1',
pathSegment: 'luigi',
label: 'luigi',
viewUrl: '/microfrontend.html'
},
{
pathSegment: 'amfe',
label: 'a mfe',
viewUrl: '/microfrontend.html',
category: { label: 'test' }
},
{
pathSegment: 'amfe',
label: 'a mfe',
viewUrl: '/microfrontend.html',
category: { label: 'luigi' }
},
{
category: 'luigi',
pathSegment: 'luigi',
label: 'luigi',
viewUrl: '/microfrontend.html'
}
];
});
it('group nodes by category id', () => {
nodes[1].category.id = '1';
nodes[1].category.collapsible = true;
const result = NavigationHelpers.groupNodesBy(nodes, 'category', true);
assert.deepEqual(Object.keys(result), ['luigi', 'test']);
assert.deepEqual(result.luigi['metaInfo'], { label: 'luigi', order: 1 });
assert.deepEqual(result.test['metaInfo'], {
label: 'test',
order: 0,
id: '1',
collapsible: true,
categoryUid: '1'
});
});
it('group nodes by category label', () => {
nodes[1].category.collapsible = true;
const result = NavigationHelpers.groupNodesBy(nodes, 'category', true);
console.log('result ', result.test['metaInfo']);
assert.deepEqual(Object.keys(result), ['1', 'test', 'luigi']);
assert.deepEqual(result.test['metaInfo'], { categoryUid: 'test', label: 'test', collapsible: true, order: 1 });
});
});
});
});
32 changes: 30 additions & 2 deletions docs/navigation-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ The URL of the micro frontend which will be displayed in the main content area o
You may use these parameters if you want to group related navigation nodes:
### category
You can add the **category** property to navigation nodes you want to group. The resulting structure will be different depending on whether you want to group top or side navigation nodes. In both cases, you should define at least one node in a group with **label** and **icon** properties. For all other nodes, you can set **category** as a string with the label value.
You can add the **category** property to navigation nodes you want to group. The resulting structure will be different depending on whether you want to group top or side navigation nodes. In both cases, you should define at least one node in a group with **label** and **icon** properties. In addition it is also possible to define an **id** property. In that case the **id** is responsible for grouping and the **label** of the group will be the name in the navigation. For all other nodes, you can set **category** as a string with the label value.
* Top navigation:
top navigation nodes in the same category will be rendered as a dropdown.
Expand All @@ -152,7 +152,7 @@ To define all subsequent nodes, use the category label:
```javascript
{
category: Links,
category: 'Links',
externalLink: {
url: 'http://www.luigi-project.io',
sameWindow: false
Expand All @@ -161,3 +161,31 @@ To define all subsequent nodes, use the category label:
},
...
```
This is an example of what a node with a category including an id, label and icon looks like:
```javascript
{
category: {id: 'anyId', label: 'Links', icon: 'myIcon', collapsible: true },
externalLink: {
url: 'http://www.luigi-project.io',
sameWindow: false
},
label: 'Click here to visit the Luigi homepage',
},
...
```
To define all subsequent nodes, use the category label:
```javascript
{
category: 'anyId',
externalLink: {
url: 'http://www.luigi-project.io',
sameWindow: false
},
label: 'Click here to visit the Luigi homepage',
},
...
```
1 change: 1 addition & 0 deletions docs/navigation-parameters-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ Node parameters are all the parameters that can be added to an individual naviga
- **altText** adds the HTML `alt` attribute to an icon. Note that this property only applies to icons with a defined absolute or relative path.
- **collapsible** if set to `true`, category items are hidden at first. To expand them, click the main category node.
- **testId** is a string where you can define your own custom `testId` for E2E tests. If nothing is specified, it is the node's label written as one word in lower case, for example`label`.
- **id** if this property is defined all nodes with the same category `id` will be grouped.
### children
- **type**: array | function
Expand Down

0 comments on commit d17e278

Please sign in to comment.