-
Notifications
You must be signed in to change notification settings - Fork 74
Description
Current Behavior
The onclick event when opening the layout editor for a given UI page in nodes/config/ui_base.html
async function showDashboardWysiwygEditor (pageId, baseId) {
// call to httpadmin endpoint requesting layout editor mode for this group
const windowUrl = new URL(window.location.href)
const base = RED.nodes.node(baseId)
const dashboardBasePath = (base.path || 'dashboard').replace(/\/$/, '').replace(/^\/+/, '')
const authTokens = RED.settings.get('auth-tokens') || {}
const headers = {}
if (authTokens?.access_token) {
headers.Authorization = `${authTokens.token_type || 'Bearer'} ${authTokens.access_token}`
}
// promisify the ajax call so we can await it & return false after opening the popup
const ajax = () => {
return new Promise((resolve, reject) => {
$.ajax({
url: `${dashboardBasePath}/api/v1/${baseId}/edit/${pageId}`, // e.g. /dashboard/api/v1/123/edit/456
type: 'PATCH',
headers,
data: {
mode: 'edit',
dashboard: baseId,
page: pageId
},
success: function (data) {
// construct the url to open the layout editor
const _url = new URL(`${dashboardBasePath}/${data.path}`.replace(/\/\//g, '/'), windowUrl.origin)
_url.searchParams.set('edit-key', data.editKey)
const editorPath = windowUrl.pathname?.replace(/\/$/, '').replace(/^\/+/, '') || ''
if (editorPath) {
_url.searchParams.set('editor-path', editorPath)
}
resolve(_url)
},
error: function (err) {
reject(err)
}
})
})
}
try {
const url = await ajax()
const target = `ff-dashboard-${baseId}` // try to reuse the same window per base
const newWindow = window.open(url, target)
// if we have an access_token then send it to the new window once opened
// This becomes necessary if the user has gotten logged out since opening the editor.
// Also, this squares up any token mismatch due to iframes/Same-Origin Policy etc.
if (authTokens?.access_token && newWindow) {
// Wait 1s then send the local access_token
// (it is unlikely user will have done any editing and be wanting to deploy within 1s!)
setTimeout(() => {
newWindow.postMessage({
type: 'authorization',
access_token: authTokens.access_token,
token_type: authTokens.token_type,
expires_in: authTokens.expires_in
}, url.origin)
}, 1000)
}
} catch (err) {
console.error('layout mode error', err)
RED.notify(RED._('@flowfuse/node-red-dashboard/ui-base:ui-base.error.layoutEditor'), 'error')
}
}Crafts an URL without considering the RED.settings.httpNodeRoot that can be altered by the user when setting up Nodered
// construct the url to open the layout editor
const _url = new URL(`${dashboardBasePath}/${data.path}`.replace(/\/\//g, '/'), windowUrl.origin)
_url.searchParams.set('edit-key', data.editKey)
const editorPath = windowUrl.pathname?.replace(/\/$/, '').replace(/^\/+/, '') || ''
if (editorPath) {
_url.searchParams.set('editor-path', editorPath)
}
resolve(_url)resulting in a wrong redirect causing a 404.
In other words, if Nodered starts at http://localhost:8000/custompath/ instead of simply http://localhost:8000/, clicking on the Layout Editor button results in a redirect to http://localhost:8000/dashboard/page1?edit... causing a 404 instead of http://localhost:8000/custompath/dashboard/page1?edit....
This behavior can be seen by simply deploying any UI node such as a Button.
Expected Behavior
I expect the Layout Editor button to redirect me to the layout editor page listening under the path that considers the RED.settings.httpNodeRoot prefix.
For example, if Nodered starts at http://localhost:8000/custompath/ instead of simply http://localhost:8000/, clicking on the Layout Editor button should redirect me http://localhost:8000/custompath/dashboard/page1?edit... instead of http://localhost:8000/dashboard/page1?edit....
This could be fixed by considering the RED.settings.httpNodeRoot prefix here:
const _url = new URL(`${RED.settings.httpNodeRoot}/${dashboardBasePath}/${data.path}`.replace(/\/\//g, '/'), windowUrl.origin)instead of
const _url = new URL(`${dashboardBasePath}/${data.path}`.replace(/\/\//g, '/'), windowUrl.origin)Steps To Reproduce
Alter Nodered settings and set a custom prefix on RED.settings.httpNodeRoot, then deploy any UI node such as a Button and proceed to click on the "Layout editor" button on the Dashboard 2.0 sidebar under the given page, usually labeled as Page 1 if no other configs have been changed. You should encounter a 404 error.
For referece instead, the "Open Dashboard" button works correctly.
Environment
- Dashboard version: 1.29.0
- Node-RED version: 4.0.9
- Node.js version: 22.16.0
- npm version: 10.9.2
- Platform/OS: Ubuntu 24.04.3
- Browser: Firefox
Have you provided an initial effort estimate for this issue?
I am not a FlowFuse team member
Metadata
Metadata
Assignees
Labels
Type
Projects
Status