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

Bookmarkable modals #1841

Merged
merged 29 commits into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0a935b7
adds possibility to set a modal vial url, with tests #1172
maxmarkus Jan 3, 2021
a109171
refactor to query param, tests tbd
maxmarkus Jan 25, 2021
d76346b
add showModalPathInUrl as parameter
maxmarkus Feb 3, 2021
7a5cc7e
fix e2e tests and slight refactoring
maxmarkus Feb 17, 2021
49ea1da
add test for hash routing
maxmarkus Feb 17, 2021
18d0b05
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Feb 22, 2021
fadcdc6
enable modal path for openInModal node setting
maxmarkus Mar 3, 2021
4173943
unit tests
maxmarkus Mar 3, 2021
0e09860
update fiddle test
maxmarkus Mar 4, 2021
0f3d5a4
Merge branch '1772-bookmarkable-modal-mf' of github.com:maxmarkus/lui…
maxmarkus Mar 4, 2021
c4245ca
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 9, 2021
7c0526e
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 10, 2021
b20bb7d
test fix
JohannesDoberer Mar 10, 2021
a711f70
wrong fix
JohannesDoberer Mar 11, 2021
e1eb50e
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 15, 2021
2ef22f3
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 15, 2021
d68bdac
test fix
JohannesDoberer Mar 15, 2021
c8f1905
increase bundle size ie11
JohannesDoberer Mar 16, 2021
05f7370
url update for closing a modal
JohannesDoberer Mar 17, 2021
c2f64e7
tests for append and remove modal data from url
JohannesDoberer Mar 18, 2021
170ee0f
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 18, 2021
2010395
luigi bundle size
JohannesDoberer Mar 18, 2021
184e819
Merge branch '1772-bookmarkable-modal-mf' of github.com:maxmarkus/lui…
JohannesDoberer Mar 18, 2021
e4ea3c2
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 18, 2021
4face9a
hash routing tests
JohannesDoberer Mar 22, 2021
474414a
Merge branch '1772-bookmarkable-modal-mf' of github.com:maxmarkus/lui…
JohannesDoberer Mar 22, 2021
4d17f48
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 23, 2021
7d24ba3
improvement + bug fix
JohannesDoberer Mar 23, 2021
06eb54c
Merge branch 'master' into 1772-bookmarkable-modal-mf
JohannesDoberer Mar 24, 2021
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
6 changes: 3 additions & 3 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"bundlesize": [
{
"path": "./public/luigi.js",
"maxSize": "455 kB",
"maxSize": "460 kB",
"compression": "none"
},
{
Expand All @@ -82,7 +82,7 @@
},
{
"path": "./public-ie11/luigi-ie11.js",
"maxSize": "655 kB",
"maxSize": "670kB",
"compression": "none"
},
{
Expand Down Expand Up @@ -136,4 +136,4 @@
"type": "git",
"url": "ssh://github.com/SAP/luigi.git"
}
}
}
24 changes: 23 additions & 1 deletion core/src/App.html
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@
// subsequential route handling
RoutingHelpers.addRouteChangeListener((path, withoutSync) => {
const pv = preservedViews;
// TODO: check if bookmarkable modal is interferring here
if (!isValidBackRoute(pv, path)) {
preservedViews = [];
Iframe.removeInactiveIframes(node);
Expand Down Expand Up @@ -944,6 +945,7 @@
mfModal.displayed = false;
mfModal.nodepath = undefined;
mfModal.settings = {};
modalIframe = undefined;
};

resetMicrofrontendModalData();
Expand All @@ -956,6 +958,13 @@
mfModal.displayed = true;
mfModal.nodepath = nodepath;
mfModal.settings = settings;

const showModalPathInUrl = LuigiConfig.getConfigBooleanValue(
'routing.showModalPathInUrl'
);
if (showModalPathInUrl) {
Routing.appendModalDataToUrl(nodepath, settings);
}
};

const modalIframeCreated = event => {
Expand All @@ -969,11 +978,24 @@
};

const closeModal = event => {

if (modalIframe) {
getUnsavedChangesModalPromise(modalIframe.contentWindow).then(() => {
const showModalPathInUrl = LuigiConfig.getConfigBooleanValue(
'routing.showModalPathInUrl'
);
if (showModalPathInUrl) {
Routing.removeModalDataFromUrl();
}
resetMicrofrontendModalData();
});
} else if (modalWC) {
const showModalPathInUrl = LuigiConfig.getConfigBooleanValue(
'routing.showModalPathInUrl'
);
if (showModalPathInUrl) {
Routing.removeModalDataFromUrl();
}
resetMicrofrontendModalData();
}
};
Expand Down Expand Up @@ -1247,7 +1269,7 @@
path = GenericHelpers.addLeadingSlash(path);
contentNode = node;
resetMicrofrontendModalData();
openViewInModal(path, e.data.params.modal);
openViewInModal(path, e.data.params.modal === true ? {} : e.data.params.modal);
} else if (e.data.params.splitView !== undefined) {
let path = buildPath(e.data.params);
path = GenericHelpers.addLeadingSlash(path);
Expand Down
117 changes: 98 additions & 19 deletions core/src/services/routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
RoutingHelpers,
IframeHelpers, EventListenerHelpers
} from '../utilities/helpers';
import { LuigiConfig, LuigiI18N } from '../core-api';
import { LuigiConfig, LuigiI18N, LuigiNavigation } from '../core-api';
import { Iframe } from './';
import { NAVIGATION_DEFAULTS } from './../utilities/luigi-config-defaults';
import { NodeDataManagementStorage } from './node-data-management';
Expand All @@ -16,10 +16,10 @@ class RoutingClass {
getNodePath(node, params) {
return node
? RoutingHelpers.buildRoute(
node,
node.pathSegment ? '/' + node.pathSegment : '',
params
)
node,
node.pathSegment ? '/' + node.pathSegment : '',
params
)
: '';
}

Expand Down Expand Up @@ -58,7 +58,7 @@ class RoutingClass {
}

if (LuigiConfig.getConfigValue('routing.useHashRouting')) {
if (!navSync){
if (!navSync) {
EventListenerHelpers.hashChangeWithoutSync = true;
}
window.location.hash = route;
Expand Down Expand Up @@ -159,9 +159,9 @@ class RoutingClass {
return LuigiConfig.getConfigValue('routing.useHashRouting')
? window.location.hash.replace('#', '') // TODO: GenericHelpers.getPathWithoutHash(window.location.hash) fails in ContextSwitcher
: window.location.search
? GenericHelpers.trimLeadingSlash(window.location.pathname) +
? GenericHelpers.trimLeadingSlash(window.location.pathname) +
window.location.search
: GenericHelpers.trimLeadingSlash(window.location.pathname);
: GenericHelpers.trimLeadingSlash(window.location.pathname);
}

async handleRouteChange(path, component, iframeElement, config, withoutSync) {
Expand Down Expand Up @@ -190,7 +190,7 @@ class RoutingClass {
this.handleRouteChange(path, component, iframeElement, config) &&
history.replaceState(window.state, '', newUrl);
},
() => {}
() => { }
);
return;
}
Expand All @@ -204,6 +204,8 @@ class RoutingClass {
RoutingHelpers.setFeatureToggles(featureToggleProperty, path);
}

await this.handleBookmarkableModalPath();

const previousCompData = component.get();
this.checkInvalidateCache(previousCompData, path);
const pathUrlRaw =
Expand Down Expand Up @@ -236,8 +238,8 @@ class RoutingClass {
this.showPageNotFoundError(
component,
GenericHelpers.trimTrailingSlash(pathData.matchedPath) +
'/' +
defaultChildNode,
'/' +
defaultChildNode,
pathUrlRaw,
true
);
Expand Down Expand Up @@ -328,10 +330,10 @@ class RoutingClass {
Object.assign({}, newNodeData, {
previousNodeValues: previousCompData
? {
viewUrl: previousCompData.viewUrl,
isolateView: previousCompData.isolateView,
viewGroup: previousCompData.viewGroup
}
viewUrl: previousCompData.viewUrl,
isolateView: previousCompData.isolateView,
viewGroup: previousCompData.viewGroup
}
: {}
})
);
Expand Down Expand Up @@ -398,6 +400,20 @@ class RoutingClass {
}
}

async handleBookmarkableModalPath() {
const additionalModalPath = RoutingHelpers.getModalPathFromPath();
if (additionalModalPath) {
const modalParams = RoutingHelpers.getModalParamsFromPath();
const { nodeObject } = await Navigation.extractDataFromPath(
additionalModalPath
);
LuigiNavigation.openAsModal(
additionalModalPath,
nodeObject.openNodeInModal || modalParams
);
}
}

/**
This function takes the previous node data and the new node path and compares
if the navigation path of both contains a dynamic node.
Expand Down Expand Up @@ -426,10 +442,10 @@ class RoutingClass {
if (
!isSamePath ||
newPathSegment !==
RoutingHelpers.getDynamicNodeValue(
previousPathNode,
previousCompData.pathParams
)
RoutingHelpers.getDynamicNodeValue(
previousPathNode,
previousCompData.pathParams
)
) {
NodeDataManagementStorage.deleteNodesRecursively(
previousPathNode
Expand Down Expand Up @@ -576,6 +592,69 @@ class RoutingClass {
componentData.context
);
}

appendModalDataToUrl(modalPath, modalParams) {
// global setting for persistence in url .. default false
let queryParamSeparator = RoutingHelpers.getHashQueryParamSeparator();
const params = RoutingHelpers.getQueryParams();
const modalParamName = RoutingHelpers.getModalViewParamName();

const prevModalPath = params[modalParamName];
if (prevModalPath !== modalPath) {
params[modalParamName] = modalPath;
if (modalParams && Object.keys(modalParams).length) {
params[`${modalParamName}Params`] = JSON.stringify(modalParams);
}
const url = new URL(location.href);
const hashRoutingActive = LuigiConfig.getConfigBooleanValue(
'routing.useHashRouting'
);
if (hashRoutingActive) {
const queryParamIndex = location.hash.indexOf(queryParamSeparator);
if (queryParamIndex !== -1) {
url.hash = url.hash.slice(0, queryParamIndex);
}
url.hash = `${url.hash
}${queryParamSeparator}${RoutingHelpers.encodeParams(params)}`;
} else {
url.search = `?${RoutingHelpers.encodeParams(params)}`;
}
history.replaceState(window.state, '', url.href);
}
}

removeModalDataFromUrl() {
const params = RoutingHelpers.getQueryParams();
const modalParamName = RoutingHelpers.getModalViewParamName();
let url = new URL(location.href);
const hashRoutingActive = LuigiConfig.getConfigBooleanValue(
'routing.useHashRouting'
);
if (hashRoutingActive) {
let modalParamsObj = {};

if (params[modalParamName]) {
modalParamsObj[modalParamName] = params[modalParamName]
}
if (params[`${modalParamName}Params`]) {
modalParamsObj[`${modalParamName}Params`] = params[`${modalParamName}Params`];
}
let prevModalPath = RoutingHelpers.encodeParams(modalParamsObj);
if (url.hash.includes(`?${prevModalPath}`)) {
url.hash = url.hash.replace(`?${prevModalPath}`, '');
} else if (url.hash.includes(`&${prevModalPath}`)) {
url.hash = url.hash.replace(`&${prevModalPath}`, '');
}
} else {
let searchParams = new URLSearchParams(url.search.slice(1));
searchParams.delete(modalParamName);
searchParams.delete(`${modalParamName}Params`);
let finalUrl = '';
Array.from(searchParams.keys()).forEach(searchParamKey => { finalUrl += (finalUrl === '' ? '?' : '&') + searchParamKey + '=' + searchParams.get(searchParamKey); });
url.search = finalUrl;
}
history.replaceState(window.state, '', url.href);
}
}

export const Routing = new RoutingClass();
67 changes: 67 additions & 0 deletions core/src/utilities/helpers/routing-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { Routing } from '../../services/routing';
class RoutingHelpersClass {
constructor() {
this.defaultContentViewParamPrefix = '~';
this.defaultQueryParamSeparator = '?';
this.defaultModalViewParamName = 'modal';
}

getLastNodeObject(pathData) {
Expand Down Expand Up @@ -77,6 +79,16 @@ class RoutingHelpersClass {
return result;
}

encodeParams(dataObj) {
let queryArr = [];
for (let key in dataObj) {
queryArr.push(
encodeURIComponent(key) + '=' + encodeURIComponent(dataObj[key])
);
}
return queryArr.join('&');
}

getNodeParams(params) {
const result = {};
const paramPrefix = this.getContentViewParamPrefix();
Expand Down Expand Up @@ -119,6 +131,61 @@ class RoutingHelpersClass {
return prefix;
}

getModalViewParamName() {
let paramName = LuigiConfig.getConfigValue('routing.modalPathParam');
if (!paramName) {
paramName = this.defaultModalViewParamName;
}
return paramName;
}

/**
* Get the query param separator which is used with hashRouting
* Default: :
* @example /home?modal=(urlencoded)/some-modal?modalParams=(urlencoded){...}&otherParam=hmhm
* @returns the first query param separator (like ? for path routing)
*/
getHashQueryParamSeparator() {
return this.defaultQueryParamSeparator;
}

getQueryParam(paramName) {
return this.getQueryParams()[paramName];
}
getQueryParams() {
const hashRoutingActive = LuigiConfig.getConfigBooleanValue(
'routing.useHashRouting'
);
return hashRoutingActive
? this.getLocationHashQueryParams()
: this.getLocationSearchQueryParams();
}
getLocationHashQueryParams() {
const queryParamIndex = location.hash.indexOf(
this.defaultQueryParamSeparator
);
return queryParamIndex !== -1
? RoutingHelpers.parseParams(location.hash.slice(queryParamIndex + 1))
: {};
}
getLocationSearchQueryParams() {
return location.search
? RoutingHelpers.parseParams(location.search.slice(1))
: {};
}

getModalPathFromPath() {
const path = this.getQueryParam(this.getModalViewParamName());
return path && decodeURIComponent(path);
}

getModalParamsFromPath() {
const modalParamsStr = this.getQueryParam(
`${this.getModalViewParamName()}Params`
);
return modalParamsStr && JSON.parse(decodeURIComponent(modalParamsStr));
}

addRouteChangeListener(callback) {
const hashRoutingActive = LuigiConfig.getConfigValue(
'routing.useHashRouting'
Expand Down
Loading