Skip to content

Commit

Permalink
Luigi core navigate function returns promise (SAP#2509)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalgamon authored Mar 1, 2022
1 parent 3306487 commit 172475b
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 40 deletions.
2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"bundlesize": [
{
"path": "./public/luigi.js",
"maxSize": "600 kB",
"maxSize": "650 kB",
"compression": "none"
},
{
Expand Down
74 changes: 59 additions & 15 deletions core/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
// Navigate to the raw path. Any errors/alerts are handled later.
// Make sure we use `replaceState` instead of `pushState` method if navigation sync is disabled.
Routing.navigateTo(path, true, isNavigationSyncEnabled);
return Routing.navigateTo(path, true, isNavigationSyncEnabled);
};
const removeQueryParams = (str) => str.split('?')[0];
Expand All @@ -241,7 +241,7 @@
};
const getUnsavedChangesModalPromise = (source) => {
return new Promise((resolve) => {
return new Promise((resolve, reject) => {
if (shouldShowUnsavedChangesModal(source)) {
showUnsavedChangesModal().then(
() => {
Expand All @@ -254,7 +254,9 @@
}
resolve();
},
() => {}
() => {
reject();
}
);
} else {
resolve();
Expand Down Expand Up @@ -1275,6 +1277,9 @@
if ('luigi.navigation.open' === e.data.msg) {
isNavigateBack = false;
const previousUrl = window.location.href;
const srcNode = isSpecialIframe ? iframe.luigi.currentNode : undefined;
const srcPathParams = isSpecialIframe
? iframe.luigi.pathParams
Expand All @@ -1284,25 +1289,58 @@
params;
const isSpecial = newTab || modal || splitView || drawer;
const resolveRemotePromise = () => {
const remotePromise = GenericHelpers.getRemotePromise(e.data.remotePromiseId);
if (remotePromise) {
remotePromise.doResolve();
}
};
const rejectRemotePromise = () => {
const remotePromise = GenericHelpers.getRemotePromise(e.data.remotePromiseId);
if (remotePromise) {
remotePromise.doReject();
}
};
const checkResolve = checkLocationChange => {
if (!checkLocationChange || previousUrl !== window.location.href) {
resolveRemotePromise();
} else {
rejectRemotePromise();
}
};
if (e.source !== window && !intent && params.link) {
params.link = params.link.split('?')[0];
}
if (!isSpecial) {
getUnsavedChangesModalPromise().then(() => {
isNavigationSyncEnabled = !withoutSync;
handleNavigation(e.data, config, srcNode, srcPathParams);
closeModal();
closeSplitView();
closeDrawer();
isNavigationSyncEnabled = true;
});
getUnsavedChangesModalPromise()
.then(() => {
isNavigationSyncEnabled = !e.data.params.withoutSync;
handleNavigation(e.data, config, srcNode, srcPathParams)
.then(() => {
checkResolve(true);
})
.catch(() => {
rejectRemotePromise();
});
closeModal();
closeSplitView();
closeDrawer();
isNavigationSyncEnabled = true;
})
.catch(() => {
rejectRemotePromise();
});
} else {
let path = buildPath(e.data.params, srcNode, srcPathParams);
path = GenericHelpers.addLeadingSlash(path);
if (newTab) {
openViewInNewTab(path);
await openViewInNewTab(path);
checkResolve();
return;
}
Expand All @@ -1312,20 +1350,26 @@
path,
pathExist
);
if (!path) {
rejectRemotePromise();
return;
}
contentNode = node;
if (modal !== undefined) {
resetMicrofrontendModalData();
openViewInModal(path, modal === true ? {} : modal);
await openViewInModal(path, modal === true ? {} : modal);
checkResolve();
} else if (splitView !== undefined) {
openSplitView(path, splitView);
await openSplitView(path, splitView);
checkResolve();
} else if (drawer !== undefined) {
resetMicrofrontendDrawerData();
drawer.isDrawer = true;
openViewInDrawer(path, drawer);
await openViewInDrawer(path, drawer);
checkResolve();
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions core/src/core-api/_internalLinkManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,22 @@ export class linkManager extends LuigiCoreAPIBase {
};
}

navigate(path, preserveView, modalSettings, splitViewSettings, drawerSettings) {
async navigate(path, preserveView, modalSettings, splitViewSettings, drawerSettings) {
if (this.options.errorSkipNavigation) {
this.options.errorSkipNavigation = false;
return;
return Promise.reject(new Error('navigation skipped'));
}

this.options.preserveView = preserveView;
const relativePath = path[0] !== '/';

if (path === '/' && (modalSettings || splitViewSettings || drawerSettings)) {
console.warn('Navigation with an absolute path prevented.');
return;
return Promise.reject(new Error('Navigation with an absolute path prevented.'));
}

const remotePromise = GenericHelpers.createRemotePromise();

const navigationOpenMsg = {
msg: 'luigi.navigation.open',
params: Object.assign(this.options, {
Expand All @@ -43,10 +45,12 @@ export class linkManager extends LuigiCoreAPIBase {
modal: modalSettings,
splitView: splitViewSettings,
drawer: drawerSettings
})
}),
remotePromiseId: remotePromise.id
};

this.sendPostMessageToLuigiCore(navigationOpenMsg);
return remotePromise;
}

openAsModal(path, modalSettings = {}) {
Expand Down
69 changes: 55 additions & 14 deletions core/src/utilities/helpers/generic-helpers.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Standalone or partly-standalone methods that are used widely through the whole app and are synchronous.
import { LuigiElements } from '../../core-api';
import { LuigiConfig } from '../../core-api';
import { LuigiElements, LuigiConfig } from '../../core-api';

class GenericHelpersClass {
/**
* Creates a random Id
* @returns random numeric value {number}
* @private
*/
getRandomId() /* istanbul ignore next */ {
getRandomId /* istanbul ignore next */() {
// window.msCrypto for IE 11
return (window.crypto || window.msCrypto).getRandomValues(new Uint32Array(1))[0];
}
Expand All @@ -21,9 +20,9 @@ class GenericHelpersClass {
return anyParam && this.isFunction(anyParam.then);
}

isIE() /* istanbul ignore next */ {
isIE /* istanbul ignore next */() {
const ua = navigator.userAgent;
/* MSIE used to detect old browsers and Trident used to newer ones*/
/* MSIE used to detect old browsers and Trident used to newer ones */
return Boolean(ua.includes('MSIE ') || ua.includes('Trident/'));
}

Expand Down Expand Up @@ -94,8 +93,8 @@ class GenericHelpersClass {
*/
getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var result = regex.exec(window.location.search);
const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
const result = regex.exec(window.location.search);
return (result && decodeURIComponent(result[1].replace(/\+/g, ' '))) || '';
}

Expand Down Expand Up @@ -154,7 +153,7 @@ class GenericHelpersClass {
}

getTrimmedUrl(path) {
const pathUrl = 0 < path.length ? this.getPathWithoutHash(path) : path;
const pathUrl = path.length > 0 ? this.getPathWithoutHash(path) : path;
return this.trimTrailingSlash(pathUrl.split('?')[0]);
}

Expand Down Expand Up @@ -209,7 +208,7 @@ class GenericHelpersClass {
return processedString;
}

getInnerHeight() /* istanbul ignore next */ {
getInnerHeight /* istanbul ignore next */() {
return LuigiElements.isCustomLuigiContainer() ? LuigiElements.getLuigiContainer().clientHeight : window.innerHeight;
}

Expand Down Expand Up @@ -288,11 +287,11 @@ class GenericHelpersClass {
* ['1.3', '1.2', '1.4', '1.1'].sort(semverCompare)
*/
semverCompare(a, b) {
var pa = a.split('-')[0].split('.');
var pb = b.split('-')[0].split('.');
for (var i = 0; i < 3; i++) {
var na = Number(pa[i]);
var nb = Number(pb[i]);
const pa = a.split('-')[0].split('.');
const pb = b.split('-')[0].split('.');
for (let i = 0; i < 3; i++) {
const na = Number(pa[i]);
const nb = Number(pb[i]);
if (na > nb) return 1;
if (nb > na) return -1;
if (!isNaN(na) && isNaN(nb)) return 1;
Expand All @@ -316,6 +315,48 @@ class GenericHelpersClass {
}
return val;
}

/**
* Creates a remote promise.
* @returns {Promise} which returns true when the promise will be resolved and returns false if the promise will be rejected.
*/
createRemotePromise() {
let res, rej;
const prom = new Promise(resolve => {
res = () => {
resolve(true);
};
rej = () => {
resolve(false);
};
});

let luiRP = LuigiConfig._remotePromises;
if (!luiRP) {
luiRP = {
counter: 0,
promises: []
};
LuigiConfig._remotePromises = luiRP;
}
prom.id = luiRP.counter++;
luiRP.promises[prom.id] = prom;

prom.doResolve = () => {
delete luiRP.promises[prom.id];
res();
};
prom.doReject = () => {
delete luiRP.promises[prom.id];
rej();
};

return prom;
}

getRemotePromise(id) {
return LuigiConfig._remotePromises ? LuigiConfig._remotePromises.promises[id] : undefined;
}
}

export const GenericHelpers = new GenericHelpersClass();
34 changes: 34 additions & 0 deletions core/test/core-api/internal-link-manager.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { GenericHelpers } from '../../src/utilities/helpers';

const sinon = require('sinon');

import { linkManager } from '../../src/core-api/_internalLinkManager';
Expand Down Expand Up @@ -76,6 +78,38 @@ describe('linkManager', function() {
lm.navigate(path, true, modalSettings, splitViewSettings, drawerSettings);
lm.sendPostMessageToLuigiCore.calledOnceWithExactly(navigationOpenMsg);
});

it('should call sendPostMessageToLuigiCore with Promise', () => {
this.options = {
preserveView: false,
nodeParams: {},
errorSkipNavigation: false,
fromContext: null,
fromClosestContext: false,
relative: false,
link: ''
};
const remotePromise = GenericHelpers.createRemotePromise();
const modalSettings = { modalSetting: 'modalValue' };
const splitViewSettings = { splitViewSetting: 'splitViewValue' };
const drawerSettings = { drawerSetting: 'drawerValue' };
const path = '/path';
const relativePath = path[0] !== '/';
const navigationOpenMsg = {
msg: 'luigi.navigation.open',
params: Object.assign(this.options, {
link: path,
relative: relativePath,
modal: modalSettings,
splitView: splitViewSettings,
drawer: drawerSettings
}),
remotePromiseId: remotePromise.id
};

lm.navigate(path, true, modalSettings, splitViewSettings, drawerSettings);
lm.sendPostMessageToLuigiCore.calledOnceWithExactly(navigationOpenMsg);
});
});

describe('openAsModal', () => {
Expand Down
1 change: 1 addition & 0 deletions docs/luigi-client-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ Navigates to the given path in the application hosted by Luigi. It contains eith
- `drawerSettings.backdrop` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** By default, it is set to `false`. If it is set to `true` the rest of the screen has a backdrop.
- `drawerSettings.size` **(`"l"` \| `"m"` \| `"s"` \| `"xs"`)** size of the drawer (optional, default `"s"`)


##### Examples

```javascript
Expand Down
4 changes: 3 additions & 1 deletion docs/luigi-core-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ Navigates to the given path in the application. It contains either a full absolu
- `drawerSettings.backdrop` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** By default, it is set to `false`. If it is set to `true` the rest of the screen has a backdrop.
- `drawerSettings.size` **(`"l"` \| `"m"` \| `"s"` \| `"xs"`)** size of the drawer (optional, default `"s"`)

Returns **[promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** a promise which resolves to a Boolean variable specifying whether the navigation was executed or not.

##### Examples

```javascript
Expand Down Expand Up @@ -697,7 +699,7 @@ let pathExists;
);
```

Returns **[promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** a promise which resolves to a Boolean variable specifying whether the path exists or not
Returns **[promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)** a promise which resolves to a Boolean variable specifying whether the path exists or not.

#### hasBack

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 172475b

Please sign in to comment.