diff --git a/dictionary/interfaces.js b/dictionary/interfaces.js index 2b709f1..8c24a5c 100644 --- a/dictionary/interfaces.js +++ b/dictionary/interfaces.js @@ -74,6 +74,72 @@ const interfaces = { ] }, + NETportalsV2: { + interface: [ + { + type: "button", + label: "Submit", + mode: ["portalEdit"], + style: "primary", + actions: [ + { + "action_type": "javascript", + "script": "if (!validateAllFields()?.isValid) { setModalTitle('Validation Error'); setModalMessage('Please fix the highlighted fields.'); setModalOpen(true); return false; }" + }, + { + "action_type": "javascript", + "script": "const confirmed = await confirmModal(); if (!confirmed) { return false; }" + }, + { + action_type: "endpoint", + api_path: "API.saveButtonAction", + type: "POST", + body: "tokenId: params['id'], savedForm: JSON.stringify(createSavedData())" + }, + { + action_type: "endpoint", + api_path: "API.submitButtonAction", + type: "POST", + body: "tokenId: params['id']" + }, + { + action_type: "javascript", + script: `await handleSubmit();` + } + ] + }, + { + type: "button", + label: "Cancel", + mode: ["portalEdit", "portalView"], + style: "secondary", + actions: [ + { + action_type: "endpoint", + api_path: "API.cancelButtonAction", + type: "POST", + body: "tokenId: params['id']", + }, + { + action_type: "javascript", + script: "await handleCancel();" + } + ] + }, + { + type: "button", + label: "Print", + mode: ["portalView"], + style: "tertiary", + actions: [ + { + action_type: "javascript", + script: "handlePrint();" + } + ] + } + ] + }, CAREGIVER: { interface: [ { @@ -124,6 +190,58 @@ const interfaces = { } ] } + ] + }, + CAREGIVERV2: { + interface: [ + { + mode: [ + "portalNew", + "portalEdit" + ], + type: "button", + label: "Save", + style: "", + actions: [ + { + script: "if (!validateAllFields()?.isValid){ window.parent.postMessage(JSON.stringify({ \"event\": \"errorOnSave\" }), \"*\");return true; }", + action_type: "javascript" + }, + { + body: "tokenId: params['id'], savedForm: JSON.stringify(createSavedData())", + path: "/application-forms/saveDraft", + type: "POST", + api_path: "API.saveButtonAction", + action_type: "endpoint" + } + ] + }, + { + mode: [ + "portalNew", + "portalEdit" + ], + type: "button", + label: "Complete", + style: "", + actions: [ + { + script: "if (!validateAllFields()?.isValid){ window.parent.postMessage(JSON.stringify({ \"event\": \"errorOnComplete\" }), \"*\"); return false; }", + action_type: "javascript" + }, + { + body: "tokenId: params['id'], savedForm: JSON.stringify(createSavedData())", + path: "/application-forms/submit", + type: "POST", + api_path: "API.saveButtonAction", + action_type: "endpoint" + }, + { + script: `await handleSubmit();`, + action_type: "javascript" + } + ] + } ] } }; diff --git a/saveICMdataHandler.js b/saveICMdataHandler.js index cd21527..df6997a 100644 --- a/saveICMdataHandler.js +++ b/saveICMdataHandler.js @@ -12,9 +12,10 @@ const { formExceptions } = require("./dictionary/jsonXmlConversion.js"); const { propertyExists, propertyNotEmpty, keyExists } = require("./dictionary/dictionaryUtils.js"); const SIEBEL_ICM_API_FORMS_ENDPOINT = process.env.SIEBEL_ICM_API_FORMS_ENDPOINT; -// utility function to fetch Attachment status (In Progress, Open...) -// and Locked By User field -async function getICMAttachmentStatus(attachment_id, username, params) { + +// Fetch attachment status and locked-by fields from ICM +// authHeaders: optional pre-acquired headers to avoid duplicate Keycloak token calls +async function getICMAttachmentStatus(attachment_id, username, params, authHeaders = null) { let return_data = {}; return_data["Status"] = ""; return_data["Locked by User"] = ""; @@ -33,12 +34,18 @@ async function getICMAttachmentStatus(attachment_id, username, params) { let url = buildUrlWithParams(params["apiHost"], params["saveEndpoint"] + attachment_id + '/', params); try { let response; - const grant = - await keycloakForSiebel.grantManager.obtainFromClientCredentials(); - const headers = { - Authorization: `Bearer ${grant.id_token.token}`, - "X-ICM-TrustedUsername": username, + let headers; + + if (authHeaders) { + headers = authHeaders; + } else { + const grant = await keycloakForSiebel.grantManager.obtainFromClientCredentials(); + headers = { + Authorization: `Bearer ${grant.id_token.token}`, + "X-ICM-TrustedUsername": username, + }; } + const query = { viewMode: "Catalog" } @@ -68,7 +75,6 @@ async function getICMAttachmentStatus(attachment_id, username, params) { async function saveICMdata(req, res) { try { let params = req.body; - console.log("Req for Save:",params); const rawHost = (req.get("X-Original-Server") || req.hostname); const configOpt = appCfg[rawHost] || Object.values(appCfg).find(cfg => { try { @@ -78,7 +84,6 @@ async function saveICMdata(req, res) { } }) || {}; params = { ...params,...configOpt }; - console.log("Params for Save:",params); const attachment_id = params["attachmentId"]; const savedFormParam = params["savedForm"]; @@ -217,7 +222,7 @@ async function saveICMdata(req, res) { const xml = saveJson["XML Hierarchy"]; const xmlSize = Buffer.byteLength(xml, 'utf8'); // size in bytes - console.log("XML Hierarchy:", xml); + // console.log("XML Hierarchy:", xml); console.log("XML Hierarchy length (chars):", xml.length); console.log("XML Hierarchy size (bytes):", xmlSize); let url = buildUrlWithParams(params["apiHost"], params["saveEndpoint"] + attachment_id + '/', params); @@ -255,7 +260,7 @@ async function loadICMdata(req, res) { let params = req.body; const rawHost = (req.get("X-Original-Server") || req.hostname); const configOpt = appCfg[rawHost]; - params = { ...params,...configOpt }; + params = { ...params,...configOpt }; const attachment_id = params["attachmentId"]; const office_name = params["OfficeName"]; console.log("attachment_id>>", attachment_id); @@ -277,9 +282,23 @@ async function loadICMdata(req, res) { return res .status(401) .send({ error: getErrorMessage("INVALID_USER") }); - } - let icm_metadata = await getICMAttachmentStatus(attachment_id, username, params); - let icm_status = icm_metadata["Status"]; + } + + // Acquire token once and reuse for all ICM calls + let authHeaders; + try { + const grant = await keycloakForSiebel.grantManager.obtainFromClientCredentials(); + authHeaders = { + Authorization: `Bearer ${grant.id_token.token}`, + "X-ICM-TrustedUsername": username, + }; + } catch (error) { + console.error("Failed to acquire Keycloak token:", error); + return res.status(500).send({ error: getErrorMessage("GENERIC_ERROR_MSG") }); + } + + let icm_metadata = await getICMAttachmentStatus(attachment_id, username, params, authHeaders); + let icm_status = icm_metadata["Status"]; if (!icm_status || icm_status == "") { console.log("Error fetching Form Instance Thin data for ", attachment_id); return res @@ -290,12 +309,6 @@ async function loadICMdata(req, res) { let url = buildUrlWithParams(params["apiHost"], params["saveEndpoint"] + attachment_id + '/', params); try { let response; - const grant = - await keycloakForSiebel.grantManager.obtainFromClientCredentials(); - const headers = { - Authorization: `Bearer ${grant.id_token.token}`, - "X-ICM-TrustedUsername": username, - } const query = { viewMode: "Catalog", inlineattachment: true @@ -303,9 +316,9 @@ async function loadICMdata(req, res) { if (params.icmWorkspace) { query.workspace = params.icmWorkspace; } - response = await axios.get(url, { params: query, headers }); + response = await axios.get(url, { params: query, headers: authHeaders }); let return_data = Buffer.from(response.data["Doc Attachment Id"], 'base64').toString('utf-8'); - //validate the returned data to be of the expected format + //validate the returned data to be of the expected format const valid = isJsonStringValid(return_data); if (!valid) { console.log('JSON is not valid '); @@ -398,6 +411,7 @@ async function clearICMLockedFlag(req, res) { if (params.icmWorkspace) { query.workspace = params.icmWorkspace; } + response = await axios.put(url, saveJson, { params: query, headers }); return res.status(200).send({}); }