Skip to content
Merged
Changes from all commits
Commits
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
43 changes: 42 additions & 1 deletion src/components/PluginLoader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,33 @@ const handleExternalNavigation = (iframeLoadEvent, pluginHref) => {
}
}

/**
* Equivalent URLs:
* <appRoot>/
* <appRoot>/index.html
* <appRoot>/index.html?redirect=false
*
* newUrl is expected to come from pluginHref,
* and will always have /index.html?redirect=false
*/
const isBaseEquivalent = (currentUrlOrig, newUrlOrig) => {
// Copy before mutating
const [currentUrl, newUrl] = [new URL(currentUrlOrig), new URL(newUrlOrig)]
newUrl.searchParams.sort()
// If redirect is not already false in the search set that
currentUrl.searchParams.set('redirect', 'false')
currentUrl.searchParams.sort()
// If pathname doesn't end in html, add that
if (currentUrl.pathname.endsWith('/')) {
currentUrl.pathname = currentUrl.pathname + 'index.html'
}

const [newBase] = newUrl.href.split('#')
const [currentBase] = currentUrl.href.split('#')

return newBase === currentBase
Comment on lines +110 to +124
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be more restrictive than it needs to be - we could probably just check for any sub-path of the base url - but I tested this and it works well!

}

const failedLoadErrorMessage =
'The requested page is not accessible by the DHIS2 global shell, ' +
'and the URL is therefore inaccessible to be printed here. ' +
Expand Down Expand Up @@ -179,10 +206,24 @@ export const PluginLoader = ({ appsInfoQuery }) => {
return
}

if (!iframeRef.current) {
return
}

const newUrl = new URL(pluginHref)
const currentLocationUrl = new URL(
iframeRef.current.contentWindow.location
)
// For further updates, replace iframe window location
if (iframeRef.current) {
if (!isBaseEquivalent(currentLocationUrl, newUrl)) {
// If 'base' has changed, replace whole location
iframeRef.current.contentWindow.location.replace(pluginHref)
} else if (newUrl.hash !== currentLocationUrl.hash) {
// If 'base' is functionally equivalent, update just hash,
// if it has changed. Tested and preserves location state
iframeRef.current.contentWindow.location.hash = newUrl.hash
}
// Otherwise, URLs are identical; don't need to update
}, [pluginHref])

if (error) {
Expand Down
Loading