refactoring to a better nodejs template and adding
better filtering using sample data
This commit is contained in:
20
src/api/routes/config.js
Normal file
20
src/api/routes/config.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const config = {
|
||||
"auth:": {
|
||||
username: process.env.EO_API_USERNAME,
|
||||
password: process.env.EO_API_PASSWORD ? "*******" : undefined,
|
||||
scope: process.env.EO_API_SCOPE,
|
||||
client_id: process.env.EO_API_CLIENT_ID,
|
||||
client_secret: process.env.EO_API_SECRET ? "*******" : undefined,
|
||||
},
|
||||
endpoints: {
|
||||
token: process.env.EO_API_ACCESS_TOKEN_URL,
|
||||
udg: process.env.EO_API_UDG_URL,
|
||||
},
|
||||
};
|
||||
res.send(config);
|
||||
});
|
||||
export default router;
|
||||
11
src/api/routes/index.js
Normal file
11
src/api/routes/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Router } from "express";
|
||||
import config from "./config.js";
|
||||
import interactionsFlows from "./interactions-flow.js";
|
||||
import udg from "./unified-data-gateway.js";
|
||||
const router = Router();
|
||||
|
||||
router.use("/config", config);
|
||||
router.use("/interactions-flow", interactionsFlows);
|
||||
router.use("/unified-data-gateway", udg);
|
||||
|
||||
export default router;
|
||||
157
src/api/routes/interactions-flow.js
Normal file
157
src/api/routes/interactions-flow.js
Normal file
@@ -0,0 +1,157 @@
|
||||
import { Router } from "express";
|
||||
import sampleFlow from "../../utils/sampleFlow.js";
|
||||
import sampleUDG from "../../utils/sampleUDGresponse.js";
|
||||
import { logger } from "../../utils/index.js";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
const filter = req.query.filter;
|
||||
|
||||
// nodes
|
||||
var channels = [];
|
||||
var queues = [];
|
||||
var outcomes = [];
|
||||
|
||||
// links
|
||||
var channel_queue_links = {};
|
||||
var channel_outcome_links = {};
|
||||
var queue_outcome_links = {};
|
||||
|
||||
sampleUDG.data.findContactsCompletedBetween.edges.forEach((value) => {
|
||||
const hasChannel = value.node.interaction.__typename ? true : false;
|
||||
const hasQueue = value.node.queue ? true : false;
|
||||
const hasOutcome = value.node.outcome ? true : false;
|
||||
|
||||
// NODES
|
||||
if (
|
||||
hasChannel &&
|
||||
channels.indexOf(value.node.interaction.__typename) == -1
|
||||
) {
|
||||
channels.push(value.node.interaction.__typename);
|
||||
}
|
||||
|
||||
if (hasQueue) {
|
||||
const queue = JSON.stringify(value.node.queue);
|
||||
if (queues.indexOf(queue) == -1) {
|
||||
queues.push(queue);
|
||||
}
|
||||
|
||||
if (hasChannel) {
|
||||
const key =
|
||||
value.node.interaction.__typename + JSON.stringify(value.node.queue);
|
||||
|
||||
if (channel_queue_links[key]) {
|
||||
channel_queue_links[key].value++;
|
||||
} else {
|
||||
channel_queue_links[key] = {
|
||||
source: value.node.interaction.__typename,
|
||||
target: JSON.stringify(value.node.queue),
|
||||
value: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOutcome) {
|
||||
value.node.outcome.edges.forEach((element) => {
|
||||
var outcome = element.node.text;
|
||||
|
||||
if (outcomes.indexOf(outcome) == -1) {
|
||||
outcomes.push(outcome);
|
||||
}
|
||||
|
||||
if (hasQueue) {
|
||||
var key = outcome+JSON.stringify(value.node.queue);
|
||||
|
||||
if (queue_outcome_links[key]) {
|
||||
queue_outcome_links[key].value++;
|
||||
} else {
|
||||
queue_outcome_links[key] = {
|
||||
source: JSON.stringify(value.node.queue),
|
||||
target: outcome,
|
||||
value: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChannel) {
|
||||
key = outcome+value.node.interaction.__typename;
|
||||
|
||||
if (channel_outcome_links[key]) {
|
||||
channel_outcome_links[key].value++;
|
||||
} else {
|
||||
channel_outcome_links[key] = {
|
||||
source: value.node.interaction.__typename,
|
||||
target: outcome,
|
||||
value: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug(`channels: ${JSON.stringify(channels)}`);
|
||||
logger.debug(`queues: ${JSON.stringify(queues)}`);
|
||||
logger.debug(`channel_queue_links: ${JSON.stringify(channel_queue_links)}`);
|
||||
logger.debug(`outcomes: ${JSON.stringify(outcomes)}`);
|
||||
|
||||
if (req.query.useSampleData) {
|
||||
const data = sampleFlow(filter);
|
||||
res.send(data);
|
||||
return;
|
||||
}
|
||||
|
||||
var data = {
|
||||
nodes: [],
|
||||
links: [],
|
||||
};
|
||||
|
||||
if (filter.includes("Channel")) {
|
||||
channels.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Channel",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Queue")) {
|
||||
queues.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Queue",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Outcome")) {
|
||||
outcomes.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Outcome",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Channel") && filter.includes("Queue")) {
|
||||
Object.values(channel_queue_links).forEach((element) => {
|
||||
data.links.push(element);
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Queue") && filter.includes("Outcome")) {
|
||||
Object.values(queue_outcome_links).forEach((element) => {
|
||||
data.links.push(element);
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Channel") && filter.includes("Outcome") && !filter.includes("Queue")) {
|
||||
Object.values(channel_outcome_links).forEach((element) => {
|
||||
data.links.push(element);
|
||||
});
|
||||
}
|
||||
|
||||
res.send(data);
|
||||
});
|
||||
export default router;
|
||||
253
src/api/routes/unified-data-gateway.js
Normal file
253
src/api/routes/unified-data-gateway.js
Normal file
@@ -0,0 +1,253 @@
|
||||
import { Router } from "express";
|
||||
import axios from "axios";
|
||||
import { URLSearchParams } from "url";
|
||||
import { inspect } from "util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
// token in session -> get user data and send it back to the vue app
|
||||
if (req.session.token) {
|
||||
query(req.query.referenceId);
|
||||
}
|
||||
// no token -> send nothing
|
||||
else {
|
||||
const params = new URLSearchParams({
|
||||
grant_type: "password",
|
||||
username: process.env.EO_API_USERNAME,
|
||||
password: process.env.EO_API_PASSWORD,
|
||||
scope: process.env.EO_API_SCOPE,
|
||||
client_id: process.env.EO_API_CLIENT_ID,
|
||||
client_secret: process.env.EO_API_SECRET,
|
||||
});
|
||||
|
||||
axios
|
||||
.post(process.env.EO_API_ACCESS_TOKEN_URL, params.toString(), {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
// save token to session
|
||||
req.session.token = result.data.access_token;
|
||||
console.log(result);
|
||||
|
||||
query(req.query.referenceId);
|
||||
})
|
||||
.catch((err) => {
|
||||
sendError(err, res);
|
||||
});
|
||||
}
|
||||
|
||||
function query(referenceId) {
|
||||
console.log("Executing Query");
|
||||
|
||||
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));
|
||||
|
||||
axios
|
||||
.post(
|
||||
process.env.EO_API_UDG_URL,
|
||||
JSON.stringify({
|
||||
query,
|
||||
variables: { startTime, endTime },
|
||||
}),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `OIDC_id_token ${req.session.token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((result) => {
|
||||
const contacts = result.data.data.findContactsCompletedBetween.edges;
|
||||
|
||||
// Log error to console
|
||||
if (result.data.errors && result.data.errors.length > 0) {
|
||||
result.data.errors.forEach(function (error) {
|
||||
console.log("ERROR: Errors in results - " + error.message);
|
||||
});
|
||||
|
||||
// TODO: Should keep errors for filteredContacts
|
||||
result.data.errors = [];
|
||||
}
|
||||
|
||||
const filteredContacts = [];
|
||||
contacts.forEach(function (contact) {
|
||||
if (contact.node.interaction.__typename === "Email") {
|
||||
// threadId if Reference in Subject line will do
|
||||
if (
|
||||
(contact.node.interaction.threadId === referenceId) |
|
||||
contact.node.interaction.subject.includes(
|
||||
`<< Ref:${referenceId} >>`
|
||||
)
|
||||
) {
|
||||
filteredContacts.push(contact);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result.data.data.findContactsCompletedBetween.edges = filteredContacts;
|
||||
result.data.data.findContactsCompletedBetween.totalCount =
|
||||
filteredContacts.length;
|
||||
|
||||
// Summary Values
|
||||
const summary = {};
|
||||
|
||||
summary.totalCount = filteredContacts.length;
|
||||
summary.totalInboundCount = 0;
|
||||
summary.totalInboundActiveSeconds = 0;
|
||||
|
||||
if (summary.totalCount > 0) {
|
||||
summary.firstContactReceivedDate = new Date(
|
||||
filteredContacts[0].node.interaction.receivedDate
|
||||
);
|
||||
|
||||
filteredContacts.forEach(function (contact) {
|
||||
if (contact.node.direction === "INBOUND") {
|
||||
summary.totalInboundCount++;
|
||||
if (!summary.firstInboundContactStartDate) {
|
||||
summary.firstInboundContactStartDate = new Date(
|
||||
contact.node.startTime
|
||||
);
|
||||
|
||||
summary.firstContactReceivedDate = new Date(
|
||||
contact.node.interaction.receivedDate
|
||||
);
|
||||
}
|
||||
summary.totalInboundActiveSeconds += contact.node.activeDuration;
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Because of overlapping contacts, we may need to calculate max instead of last.
|
||||
summary.lastContactEndTime = new Date(
|
||||
filteredContacts[filteredContacts.length - 1].node.endTime
|
||||
);
|
||||
|
||||
summary.totalHTHours =
|
||||
(summary.lastContactEndTime.getTime() -
|
||||
summary.firstContactReceivedDate.getTime()) /
|
||||
(1000 * 3600);
|
||||
summary.activeHTMinutes =
|
||||
(summary.lastContactEndTime.getTime() -
|
||||
summary.firstInboundContactStartDate.getTime()) /
|
||||
(1000 * 60);
|
||||
}
|
||||
result.data.data.summary = summary;
|
||||
|
||||
if (result.data) {
|
||||
console.log(
|
||||
inspect(summary, {
|
||||
showHidden: false,
|
||||
depth: null,
|
||||
colors: true,
|
||||
})
|
||||
);
|
||||
|
||||
res.send(result.data);
|
||||
}
|
||||
|
||||
// expired token -> send nothing
|
||||
else {
|
||||
req.session.destroy();
|
||||
res.send({});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
// bin the token on error
|
||||
req.session.destroy();
|
||||
sendError(err, res);
|
||||
});
|
||||
}
|
||||
});
|
||||
function sendError(err, res) {
|
||||
console.error(err);
|
||||
let errStatus = 500;
|
||||
if (err.response) errStatus = err.response.status;
|
||||
res.status(errStatus).send({
|
||||
errors: [
|
||||
{
|
||||
status: errStatus,
|
||||
title: err.code,
|
||||
detail: err.message,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
export default router;
|
||||
17
src/app.js
Normal file
17
src/app.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import express from "express";
|
||||
import config from "./config/index.js";
|
||||
import loader from "./loaders/index.js";
|
||||
|
||||
const app = express();
|
||||
|
||||
loader(app);
|
||||
|
||||
app.listen(config.port, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return process.exit(1);
|
||||
}
|
||||
console.log(`Server is running on ${config.port}`);
|
||||
});
|
||||
|
||||
export default app;
|
||||
38
src/config/index.js
Normal file
38
src/config/index.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Set the NODE_ENV to 'development' by default
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || "development";
|
||||
|
||||
const envFound = dotenv.config();
|
||||
if (envFound.error) {
|
||||
// This error should crash whole process
|
||||
|
||||
throw new Error("⚠️ Couldn't find .env file ⚠️");
|
||||
}
|
||||
|
||||
export default {
|
||||
/**
|
||||
* Your favorite port
|
||||
*/
|
||||
port: parseInt(process.env.PORT, 10),
|
||||
|
||||
/**
|
||||
* Your secret sauce
|
||||
*/
|
||||
jwtSecret: process.env.JWT_SECRET,
|
||||
jwtAlgorithm: process.env.JWT_ALGO,
|
||||
|
||||
/**
|
||||
* Used by winston logger
|
||||
*/
|
||||
logs: {
|
||||
level: process.env.LOG_LEVEL || "silly",
|
||||
},
|
||||
|
||||
/**
|
||||
* API configs
|
||||
*/
|
||||
api: {
|
||||
prefix: "/api",
|
||||
},
|
||||
};
|
||||
47
src/index.js
Normal file
47
src/index.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const express = require("express");
|
||||
const cors = require("cors");
|
||||
const morgan = require("morgan");
|
||||
const session = require("express-session");
|
||||
|
||||
// dotenv
|
||||
require("dotenv").config();
|
||||
|
||||
const app = express();
|
||||
|
||||
// Use our middlewares
|
||||
app.use(cors({ origin: true, credentials: true }));
|
||||
app.use(morgan("common"));
|
||||
app.use(express.json());
|
||||
app.use(
|
||||
session({
|
||||
secret: "1234567890", // don't use this secret in prod :)
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
cookie: {
|
||||
secure: "auto",
|
||||
httpOnly: true,
|
||||
maxAge: 3600000,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// Provide a default port
|
||||
const port = process.env.SERVER_PORT || 3000;
|
||||
|
||||
// Listen to server
|
||||
app.listen(port, () => {
|
||||
console.log(`Listening on port ${port}`);
|
||||
});
|
||||
|
||||
// ...
|
||||
// Main Page
|
||||
app.get("/", (req, res) => {
|
||||
res.send({
|
||||
message: "Engagement Orchestration Services",
|
||||
});
|
||||
});
|
||||
// ...
|
||||
|
||||
app.use("/config", require("./routes/config"));
|
||||
app.use("/unified-data-gateway", require("./routes/unified-data-gateway"));
|
||||
app.use("/interactions-flow", require("./routes/interactions-flow"));
|
||||
99
src/loaders/express.js
Normal file
99
src/loaders/express.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import express from "express";
|
||||
import cors from "cors";
|
||||
import compression from "compression";
|
||||
import morgan from "morgan";
|
||||
import helmet from "helmet";
|
||||
import config from "./../config/index.js";
|
||||
import routes from "./../api/routes/index.js";
|
||||
import { logger } from "../utils/index.js";
|
||||
// import { rateLimiter } from '../api/middlewares/index.js';
|
||||
import bodyParser from "body-parser";
|
||||
import session from "express-session";
|
||||
|
||||
export default (app) => {
|
||||
logger.info("Loading Express ...");
|
||||
process.on("uncaughtException", async (error) => {
|
||||
logger.error(error);
|
||||
});
|
||||
|
||||
process.on("unhandledRejection", async (ex) => {
|
||||
logger.error(ex);
|
||||
});
|
||||
|
||||
if (!config.jwtSecret) {
|
||||
logger.crit("Jwtprivatekey is not defined");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
app.enable("trust proxy");
|
||||
// app.use(cors());
|
||||
|
||||
app.use(cors({ origin: true, credentials: true }));
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(morgan("dev"));
|
||||
app.use(helmet());
|
||||
app.use(compression());
|
||||
app.use(express.static("public"));
|
||||
app.disable("x-powered-by");
|
||||
app.disable("etag");
|
||||
app.use(
|
||||
session({
|
||||
secret: "1234567890", // don't use this secret in prod :)
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
cookie: {
|
||||
secure: "auto",
|
||||
httpOnly: true,
|
||||
maxAge: 3600000,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// app.use(rateLimiter);
|
||||
logger.info(`Mounting routes on ${config.api.prefix}`);
|
||||
app.use(config.api.prefix, routes);
|
||||
|
||||
app.get("/", (_req, res) => {
|
||||
return res
|
||||
.status(200)
|
||||
.json({
|
||||
resultMessage: {
|
||||
en: "Project is successfully working...",
|
||||
},
|
||||
resultCode: "00004",
|
||||
})
|
||||
.end();
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
// res.header("Access-Control-Allow-Origin", "*");
|
||||
// res.header(
|
||||
// "Access-Control-Allow-Headers",
|
||||
// "Origin, X-Requested-With, Content-Type, Accept, Authorization"
|
||||
// );
|
||||
// res.header("Content-Security-Policy-Report-Only", "default-src: https:");
|
||||
// if (req.method === "OPTIONS") {
|
||||
// res.header("Access-Control-Allow-Methods", "PUT POST PATCH DELETE GET");
|
||||
// return res.status(200).json({});
|
||||
// }
|
||||
next();
|
||||
});
|
||||
|
||||
app.use((_req, _res, next) => {
|
||||
const error = new Error("Endpoint could not find!");
|
||||
error.status = 404;
|
||||
next(error);
|
||||
});
|
||||
|
||||
app.use((error, req, res) => {
|
||||
res.status(error.status || 500);
|
||||
logger.error(error.message);
|
||||
return res.json({
|
||||
resultMessage: {
|
||||
en: error.message,
|
||||
tr: error.message,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
5
src/loaders/index.js
Normal file
5
src/loaders/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import expressLoader from "./express.js";
|
||||
|
||||
export default async (app) => {
|
||||
expressLoader(app);
|
||||
};
|
||||
1
src/utils/index.js
Normal file
1
src/utils/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default as logger } from "./logger.js";
|
||||
32
src/utils/logger.js
Normal file
32
src/utils/logger.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import winston from "winston";
|
||||
import config from "../config/index.js";
|
||||
|
||||
const transports = [];
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
transports.push(new winston.transports.Console());
|
||||
} else {
|
||||
transports.push(
|
||||
new winston.transports.Console({
|
||||
format: winston.format.combine(
|
||||
winston.format.cli(),
|
||||
winston.format.splat()
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const LoggerInstance = winston.createLogger({
|
||||
level: config.logs.level,
|
||||
levels: winston.config.npm.levels,
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({
|
||||
format: "YYYY-MM-DD HH:mm:ss",
|
||||
}),
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.splat(),
|
||||
winston.format.json()
|
||||
),
|
||||
transports,
|
||||
});
|
||||
|
||||
export default LoggerInstance;
|
||||
207
src/utils/sampleFlow.js
Normal file
207
src/utils/sampleFlow.js
Normal file
@@ -0,0 +1,207 @@
|
||||
import { logger } from "../utils/index.js";
|
||||
|
||||
export default function generate(filter) {
|
||||
filter = filter ? filter : "Channel, Sub-Channel, Queue, Outcome";
|
||||
logger.info(`Generating sample data for ${filter}`);
|
||||
|
||||
var data = {
|
||||
nodes: [],
|
||||
links: [],
|
||||
};
|
||||
|
||||
const channels = ["Email", "Messaging", "Legacy Live Chat"];
|
||||
const subChannels = ["Live Chat", "Facebook Messenger", "Twitter DM", "WhatsApp","Other"];
|
||||
const queues = ["General Enquiries", "Complaints", "Default"];
|
||||
const outcomes = ["No need for response", "Case Updated", "Escalated to Manager"];
|
||||
|
||||
if (filter.includes("Channel")) {
|
||||
channels.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Channel",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Sub-Channel")) {
|
||||
subChannels.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Sub-Channel",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Queue")) {
|
||||
queues.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Queue",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (filter.includes("Outcome")) {
|
||||
outcomes.forEach((value) => {
|
||||
data.nodes.push({
|
||||
name: value,
|
||||
category: "Outcome",
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
data.links.push(
|
||||
{
|
||||
source: "Email",
|
||||
target: "Default",
|
||||
value: 342,
|
||||
},
|
||||
{
|
||||
source: "Messaging",
|
||||
target: "Live Chat",
|
||||
value: 232,
|
||||
},
|
||||
{
|
||||
source: "Messaging",
|
||||
target: "Facebook Messenger",
|
||||
value: 623,
|
||||
},
|
||||
{
|
||||
source: "Messaging",
|
||||
target: "Twitter DM",
|
||||
value: 434,
|
||||
},
|
||||
{
|
||||
source: "Messaging",
|
||||
target: "WhatsApp",
|
||||
value: 1243,
|
||||
},
|
||||
{
|
||||
source: "Messaging",
|
||||
target: "Other",
|
||||
value: 150,
|
||||
},
|
||||
{
|
||||
source: "Live Chat",
|
||||
target: "Default",
|
||||
value: 132,
|
||||
},
|
||||
{
|
||||
source: "Live Chat",
|
||||
target: "Complaints",
|
||||
value: 90,
|
||||
},
|
||||
{
|
||||
source: "Live Chat",
|
||||
target: "General Enquires",
|
||||
value: 42,
|
||||
},
|
||||
{
|
||||
source: "WhatsApp",
|
||||
target: "Default",
|
||||
value: 343,
|
||||
},
|
||||
{
|
||||
source: "WhatsApp",
|
||||
target: "Complaints",
|
||||
value: 300,
|
||||
},
|
||||
{
|
||||
source: "WhatsApp",
|
||||
target: "General Enquires",
|
||||
value: 523,
|
||||
},
|
||||
{
|
||||
source: "Facebook Messenger",
|
||||
target: "Default",
|
||||
value: 143,
|
||||
},
|
||||
{
|
||||
source: "Facebook Messenger",
|
||||
target: "Complaints",
|
||||
value: 200,
|
||||
},
|
||||
{
|
||||
source: "Facebook Messenger",
|
||||
target: "General Enquires",
|
||||
value: 323,
|
||||
},
|
||||
{
|
||||
source: "Twitter DM",
|
||||
target: "Default",
|
||||
value: 143,
|
||||
},
|
||||
{
|
||||
source: "Twitter DM",
|
||||
target: "Complaints",
|
||||
value: 50,
|
||||
},
|
||||
{
|
||||
source: "Twitter DM",
|
||||
target: "General Enquires",
|
||||
value: 223,
|
||||
},
|
||||
{
|
||||
source: "General Enquires",
|
||||
target: "Case Closed",
|
||||
value: 421,
|
||||
},
|
||||
{
|
||||
source: "General Enquires",
|
||||
target: "Completed",
|
||||
value: 612,
|
||||
},
|
||||
{
|
||||
source: "General Enquires",
|
||||
target: "Escalated to Manager",
|
||||
value: 23,
|
||||
},
|
||||
{
|
||||
source: "General Enquires",
|
||||
target: "No need for response",
|
||||
value: 241,
|
||||
},
|
||||
{
|
||||
source: "Complaints",
|
||||
target: "Case Closed",
|
||||
value: 21,
|
||||
},
|
||||
{
|
||||
source: "Complaints",
|
||||
target: "Completed",
|
||||
value: 12,
|
||||
},
|
||||
{
|
||||
source: "Complaints",
|
||||
target: "Escalated to Manager",
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
source: "Complaints",
|
||||
target: "No need for response",
|
||||
value: 41,
|
||||
},
|
||||
{
|
||||
source: "Default",
|
||||
target: "Completed",
|
||||
value: 41,
|
||||
},
|
||||
{
|
||||
source: "Default",
|
||||
target: "Case Updated",
|
||||
value: 410,
|
||||
},
|
||||
{
|
||||
source: "General Enquires",
|
||||
target: "Case Updated",
|
||||
value: 50,
|
||||
},
|
||||
{
|
||||
source: "Complaints",
|
||||
target: "Case Updated",
|
||||
value: 410,
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
21746
src/utils/sampleUDGresponse.js
Normal file
21746
src/utils/sampleUDGresponse.js
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user