diff --git a/nodes/_utils.js b/nodes/_utils.js index 14a0f7d..2a65c37 100644 --- a/nodes/_utils.js +++ b/nodes/_utils.js @@ -67,29 +67,35 @@ async function handleDatalinkAutoComplete(RED, req, res) { // Try to get the node, but it might not exist yet if this is a new node let node = RED.nodes.getNode(nodeId); - let seqeraConfigId = null; + let seqeraConfigId = req.query.seqeraConfig || req.body?.seqeraConfig; let baseUrl = "https://api.cloud.seqera.io"; let workspaceId = null; + let credentials = null; if (node && node.seqeraConfig) { - // Node exists and has config + // Node exists and has config - use deployed node's config seqeraConfigId = node.seqeraConfig.id; baseUrl = node.seqeraConfig.baseUrl || baseUrl; workspaceId = node.seqeraConfig.workspaceId; + credentials = node.seqeraConfig.credentials; // Check for workspace ID override in the node configuration if (node.workspaceIdProp && node.workspaceIdPropType === "str" && node.workspaceIdProp.trim()) { workspaceId = node.workspaceIdProp; } - } else { - // Try to get config ID from request body or query params - seqeraConfigId = req.query.seqeraConfig || req.body?.seqeraConfig; - if (seqeraConfigId) { - const configNode = RED.nodes.getNode(seqeraConfigId); - if (configNode) { - baseUrl = configNode.baseUrl || baseUrl; - workspaceId = configNode.workspaceId; - } + } else if (seqeraConfigId) { + // Try to get deployed config node + const configNode = RED.nodes.getNode(seqeraConfigId); + if (configNode) { + baseUrl = configNode.baseUrl || baseUrl; + workspaceId = configNode.workspaceId; + credentials = configNode.credentials; + } else { + // Config node not deployed - use query params for baseUrl/workspaceId + // and look up saved credentials by config node ID + baseUrl = req.query.baseUrl || baseUrl; + workspaceId = req.query.workspaceId || null; + credentials = RED.nodes.getCredentials(seqeraConfigId); } } @@ -102,16 +108,16 @@ async function handleDatalinkAutoComplete(RED, req, res) { return res.json([]); // Return empty array instead of error for better UX } - // Create a temporary node-like object for apiCall if we don't have a real node - const nodeForApi = node || { - seqeraConfig: RED.nodes.getNode(seqeraConfigId), + if (!credentials || !credentials.token) { + return res.json([]); // No credentials available + } + + // Create a temporary node-like object for apiCall + const nodeForApi = { + seqeraConfig: { credentials }, warn: () => {}, // Dummy warn function }; - if (!nodeForApi.seqeraConfig) { - return res.json([]); - } - // Build the data-links API URL with search parameter const params = new URLSearchParams({ workspaceId }); if (search) { diff --git a/nodes/datalink-list.html b/nodes/datalink-list.html index ddaee67..717a24f 100644 --- a/nodes/datalink-list.html +++ b/nodes/datalink-list.html @@ -180,16 +180,25 @@ return; } + // Get config node from editor (works for undeployed nodes) + const configNode = RED.nodes.node(seqeraConfigId); + const params = new URLSearchParams({ search: value, seqeraConfig: seqeraConfigId, }); - // Add workspace ID override if configured + // Pass config values for undeployed nodes + if (configNode) { + if (configNode.baseUrl) params.append("baseUrl", configNode.baseUrl); + if (configNode.workspaceId) params.append("workspaceId", configNode.workspaceId); + } + + // Add workspace ID override if configured (takes precedence) const workspaceIdOverride = $("#node-input-workspaceId").typedInput("value"); const workspaceIdType = $("#node-input-workspaceId").typedInput("type"); if (workspaceIdType === "str" && workspaceIdOverride && workspaceIdOverride.trim()) { - params.append("workspaceId", workspaceIdOverride); + params.set("workspaceId", workspaceIdOverride); } $.ajax({ diff --git a/nodes/datalink-poll.html b/nodes/datalink-poll.html index 356a612..9dbd58e 100644 --- a/nodes/datalink-poll.html +++ b/nodes/datalink-poll.html @@ -231,16 +231,25 @@ return; } + // Get config node from editor (works for undeployed nodes) + const configNode = RED.nodes.node(seqeraConfigId); + const params = new URLSearchParams({ search: value, seqeraConfig: seqeraConfigId, }); - // Add workspace ID override if configured + // Pass config values for undeployed nodes + if (configNode) { + if (configNode.baseUrl) params.append("baseUrl", configNode.baseUrl); + if (configNode.workspaceId) params.append("workspaceId", configNode.workspaceId); + } + + // Add workspace ID override if configured (takes precedence) const workspaceIdOverride = $("#node-input-workspaceId").typedInput("value"); const workspaceIdType = $("#node-input-workspaceId").typedInput("type"); if (workspaceIdType === "str" && workspaceIdOverride && workspaceIdOverride.trim()) { - params.append("workspaceId", workspaceIdOverride); + params.set("workspaceId", workspaceIdOverride); } $.ajax({ diff --git a/nodes/workflow-launch.html b/nodes/workflow-launch.html index 96717b9..712dc39 100644 --- a/nodes/workflow-launch.html +++ b/nodes/workflow-launch.html @@ -204,16 +204,25 @@ return; } + // Get config node from editor (works for undeployed nodes) + const configNode = RED.nodes.node(seqeraConfigId); + const params = new URLSearchParams({ search: value, seqeraConfig: seqeraConfigId, }); - // Add workspace ID override if configured + // Pass config values for undeployed nodes + if (configNode) { + if (configNode.baseUrl) params.append("baseUrl", configNode.baseUrl); + if (configNode.workspaceId) params.append("workspaceId", configNode.workspaceId); + } + + // Add workspace ID override if configured (takes precedence) const workspaceIdOverride = $("#node-input-workspaceId").typedInput("value"); const workspaceIdType = $("#node-input-workspaceId").typedInput("type"); if (workspaceIdType === "str" && workspaceIdOverride && workspaceIdOverride.trim()) { - params.append("workspaceId", workspaceIdOverride); + params.set("workspaceId", workspaceIdOverride); } $.ajax({ diff --git a/nodes/workflow-launch.js b/nodes/workflow-launch.js index 1709ea9..ddd0e2c 100644 --- a/nodes/workflow-launch.js +++ b/nodes/workflow-launch.js @@ -7,29 +7,35 @@ module.exports = function (RED) { // Try to get the node, but it might not exist yet if this is a new node let node = RED.nodes.getNode(nodeId); - let seqeraConfigId = null; + let seqeraConfigId = req.query.seqeraConfig || req.body?.seqeraConfig; let baseUrl = "https://api.cloud.seqera.io"; let workspaceId = null; + let credentials = null; if (node && node.seqeraConfig) { - // Node exists and has config + // Node exists and has config - use deployed node's config seqeraConfigId = node.seqeraConfig.id; baseUrl = node.seqeraConfig.baseUrl || baseUrl; workspaceId = node.seqeraConfig.workspaceId; + credentials = node.seqeraConfig.credentials; // Check for workspace ID override in the node configuration if (node.workspaceIdProp && node.workspaceIdPropType === "str" && node.workspaceIdProp.trim()) { workspaceId = node.workspaceIdProp; } - } else { - // Try to get config ID from request body or query params - seqeraConfigId = req.query.seqeraConfig || req.body?.seqeraConfig; - if (seqeraConfigId) { - const configNode = RED.nodes.getNode(seqeraConfigId); - if (configNode) { - baseUrl = configNode.baseUrl || baseUrl; - workspaceId = configNode.workspaceId; - } + } else if (seqeraConfigId) { + // Try to get deployed config node + const configNode = RED.nodes.getNode(seqeraConfigId); + if (configNode) { + baseUrl = configNode.baseUrl || baseUrl; + workspaceId = configNode.workspaceId; + credentials = configNode.credentials; + } else { + // Config node not deployed - use query params for baseUrl/workspaceId + // and look up saved credentials by config node ID + baseUrl = req.query.baseUrl || baseUrl; + workspaceId = req.query.workspaceId || null; + credentials = RED.nodes.getCredentials(seqeraConfigId); } } @@ -42,16 +48,16 @@ module.exports = function (RED) { return res.json([]); // Return empty array instead of error for better UX } - // Create a temporary node-like object for apiCall if we don't have a real node - const nodeForApi = node || { - seqeraConfig: RED.nodes.getNode(seqeraConfigId), + if (!credentials || !credentials.token) { + return res.json([]); // No credentials available + } + + // Create a temporary node-like object for apiCall + const nodeForApi = { + seqeraConfig: { credentials }, warn: () => {}, // Dummy warn function }; - if (!nodeForApi.seqeraConfig) { - return res.json([]); - } - const { apiCall } = require("./_utils"); // Build the pipelines API URL