From 3f788733c831516114dc96e2ae05edea86ac96a8 Mon Sep 17 00:00:00 2001 From: "Peter.Morton" Date: Sat, 5 Aug 2023 16:51:12 -0500 Subject: [PATCH] Separated out query for reuse and interactions-flow route no longer uses sample data --- src/api/routes/interactions-flow.js | 147 +++++++++++++++++-------- src/api/routes/unified-data-gateway.js | 88 ++------------- src/utils/graphQueries.js | 74 +++++++++++++ 3 files changed, 181 insertions(+), 128 deletions(-) create mode 100644 src/utils/graphQueries.js diff --git a/src/api/routes/interactions-flow.js b/src/api/routes/interactions-flow.js index efb6cb7..9ac9016 100644 --- a/src/api/routes/interactions-flow.js +++ b/src/api/routes/interactions-flow.js @@ -1,12 +1,13 @@ import { Router } from "express"; +import axios from "axios"; +import localStorage from "local-storage"; import sampleFlow from "../../utils/sampleFlow.js"; -import sampleUDG from "../../utils/sampleUDGresponse.js"; const router = Router(); import { logger } from "../../utils/index.js"; +import { referenceIdQuery } from "../../utils/graphQueries.js"; router.get("/", (req, res) => { - - var data = { + const data = { nodes: [], links: [], }; @@ -19,70 +20,120 @@ router.get("/", (req, res) => { chain[filterNames[index] + "-" + filterNames[index + 1]] = true; } - sampleUDG.data.findContactsCompletedBetween.edges.forEach((value) => { - addNode(filter, "Channel", value.node.interaction.__typename, data); + const startTime = new Date( + new Date().setFullYear(new Date().getFullYear() - 2) + ); + var endTime = new Date(); + // FIX for 'endTime' parameter cannot be later than one minute prior to now. + endTime.setMinutes(endTime.getMinutes() - 1); - if (value.node.interaction.subChannel) { - addNode(filter, "SubChannel", value.node.interaction.subChannel, data); - if (chain["Channel-SubChannel"]) { - addLink( - data, - value.node.interaction.__typename, - value.node.interaction.subChannel - ); + const { host, tenant, token } = localStorage(req.query.authKey); + + axios + .post( + `${host}/unified-data-gateway/${tenant}/graphql`, + JSON.stringify({ + query: referenceIdQuery, + variables: { startTime, endTime }, + }), + { + headers: { + Authorization: `OIDC_id_token ${token}`, + "Content-Type": "application/json", + }, } - } + ) + .then((result) => { + if (result.data.errors && result.data.errors.length > 0) { + result.data.errors.forEach(function (error) { + logger.error("ERROR: Errors in results - " + error.message); + }); - if (value.node.queue) { - const queueName = `${value.node.queue.name}(${value.node.queue.orgScope})`; - addNode(filter, "Queue", queueName, data); - if (chain["Channel-Queue"]) { - addLink(data, value.node.interaction.__typename, queueName); + // TODO: Should keep errors for filteredContacts + result.data.errors = []; } - if (chain["SubChannel-Queue"]) { - addSubChannelLink(queueName); + + if (!result.data.data.findContactsCompletedBetween) { + logger.debug("No findContactsCompletedBetween returned."); + res.send(data); + return; } - } - if (value.node.outcome) { - value.node.outcome.edges.forEach((element) => { - addNode(filter, "Outcome", element.node.text, data); + result.data.data.findContactsCompletedBetween.edges.forEach((value) => { + // TODO: Should add INBOUND and OUTBOUND Nodes before Channel + addNode(filter, "Channel", value.node.interaction.__typename, data); - if (chain["Channel-Outcome"]) { - addLink(data, value.node.interaction.__typename, element.node.text); + if (value.node.interaction.subChannel) { + addNode( + filter, + "SubChannel", + value.node.interaction.subChannel, + data + ); + if (chain["Channel-SubChannel"]) { + addLink( + data, + value.node.interaction.__typename, + value.node.interaction.subChannel + ); + } } - if (chain["SubChannel-Outcome"]) { - addSubChannelLink(element.node.text); - } - - if (chain["Queue-Outcome"] && !!value.node.queue) { + if (value.node.queue) { const queueName = `${value.node.queue.name}(${value.node.queue.orgScope})`; - addLink(data, queueName, element.node.text); + addNode(filter, "Queue", queueName, data); + if (chain["Channel-Queue"]) { + addLink(data, value.node.interaction.__typename, queueName); + } + if (chain["SubChannel-Queue"]) { + addSubChannelLink(queueName); + } + } + + if (value.node.outcome) { + value.node.outcome.edges.forEach((element) => { + addNode(filter, "Outcome", element.node.text, data); + + if (chain["Channel-Outcome"]) { + addLink( + data, + value.node.interaction.__typename, + element.node.text + ); + } + + if (chain["SubChannel-Outcome"]) { + addSubChannelLink(element.node.text); + } + + if (chain["Queue-Outcome"] && !!value.node.queue) { + const queueName = `${value.node.queue.name}(${value.node.queue.orgScope})`; + addLink(data, queueName, element.node.text); + } + }); + } + + function addSubChannelLink(target) { + if (value.node.interaction.subChannel) { + addLink(data, value.node.interaction.subChannel, target); + } else { + // SubChannel does not exist, revert to Channel if in chain + if (chain["Channel-SubChannel"]) { + addLink(data, value.node.interaction.__typename, target); + } + } } }); - } - function addSubChannelLink(target) { - if (value.node.interaction.subChannel) { - addLink(data, value.node.interaction.subChannel, target); - } else { - // SubChannel does not exist, revert to Channel if in chain - if (chain["Channel-SubChannel"]) { - addLink(data, value.node.interaction.__typename, target); - } - } - } - }); + logger.debug(`Sending data: ${JSON.stringify(data, null, 2)}`); + res.send(data); + }); if (req.query.useSampleData) { const data = sampleFlow(filter); res.send(data); return; } - - logger.debug(`Sending data: ${JSON.stringify(data, null, 2)}`); - res.send(data); }); function addLink(data, source, target) { diff --git a/src/api/routes/unified-data-gateway.js b/src/api/routes/unified-data-gateway.js index 65941e7..36895b1 100644 --- a/src/api/routes/unified-data-gateway.js +++ b/src/api/routes/unified-data-gateway.js @@ -4,101 +4,29 @@ import { logger } from "../../utils/index.js"; // import { URLSearchParams } from "url"; import { inspect } from "util"; import localStorage from "local-storage"; +import { referenceIdQuery } from "../../utils/graphQueries.js"; const router = Router(); router.get("/", (req, res, next) => { - query(req.query.referenceId); function query(referenceId) { logger.info(`Executing Query with ${referenceId}`); - const query = `query ($startTime: DateTime, $endTime: DateTime) { - findContactsCompletedBetween(startTime: $startTime, endTime: $endTime, filter: {interactionTypes : EMAIL}) { - - totalCount - edges { - node { - systemId - startTime - endTime - direction - handledBy { - username - firstName - lastName - nickname - orgScope - } - activeDuration - notes { - totalCount - edges { - node { - text - } - } - } - interaction { - systemId - locale - __typename - ... on Email { - messageId - threadId - sentDate - receivedDate - subject - fromAddress - toAddresses - ccAddresses - bccAddresses - detectedLanguage - mailboxName - attachmentCount - isDuplicate - } - } - outcome { - totalCount - edges { - node { - text - isActive - isVisible - } - } - } - customer { - totalCount - edges { - node { - ref - firstName - lastName - } - } - } - queue { - name - orgScope - } - } - } - } - }`; const startTime = new Date( new Date().setFullYear(new Date().getFullYear() - 2) ); - const endTime = new Date(new Date().setHours(new Date().getHours() - 1)); + var endTime = new Date(); + // FIX for 'endTime' parameter cannot be later than one minute prior to now. + endTime.setMinutes(endTime.getMinutes() - 1); const { host, tenant, token } = localStorage(req.query.authKey); axios .post( `${host}/unified-data-gateway/${tenant}/graphql`, JSON.stringify({ - query, + query: referenceIdQuery, variables: { startTime, endTime }, }), { @@ -109,8 +37,6 @@ router.get("/", (req, res, next) => { } ) .then((result) => { - const contacts = result.data.data.findContactsCompletedBetween.edges; - if (result.data.errors && result.data.errors.length > 0) { result.data.errors.forEach(function (error) { logger.error("ERROR: Errors in results - " + error.message); @@ -120,6 +46,8 @@ router.get("/", (req, res, next) => { result.data.errors = []; } + const contacts = result.data.data.findContactsCompletedBetween.edges; + const filteredContacts = []; contacts.forEach(function (contact) { if (contact.node.interaction.__typename === "Email") { @@ -204,7 +132,7 @@ router.get("/", (req, res, next) => { .catch((err) => { // bin the token on error req.session.destroy(); - next(err) + next(err); }); } }); diff --git a/src/utils/graphQueries.js b/src/utils/graphQueries.js new file mode 100644 index 0000000..af3dd48 --- /dev/null +++ b/src/utils/graphQueries.js @@ -0,0 +1,74 @@ +export const referenceIdQuery = `query ($startTime: DateTime, $endTime: DateTime) { + findContactsCompletedBetween(startTime: $startTime, endTime: $endTime) { + + totalCount + edges { + node { + systemId + startTime + endTime + direction + handledBy { + username + firstName + lastName + nickname + orgScope + } + activeDuration + notes { + totalCount + edges { + node { + text + } + } + } + interaction { + systemId + locale + __typename + ... on Email { + messageId + threadId + sentDate + receivedDate + subject + fromAddress + toAddresses + ccAddresses + bccAddresses + detectedLanguage + mailboxName + attachmentCount + isDuplicate + } + } + outcome { + totalCount + edges { + node { + text + isActive + isVisible + } + } + } + customer { + totalCount + edges { + node { + ref + firstName + lastName + } + } + } + queue { + name + orgScope + } + } + } + } +}`;