@upscopeio/twilio-flex-component
Version:
Upscope Co-browsing component for Twilio Flex
357 lines (326 loc) • 17.2 kB
JavaScript
require("./UpscopeWidget.css");
var $iA2ta$reactjsxruntime = require("react/jsx-runtime");
var $iA2ta$react = require("react");
var $iA2ta$sentryreact = require("@sentry/react");
var $iA2ta$twilioflexui = require("@twilio/flex-ui");
var $iA2ta$debug = require("debug");
var $iA2ta$axios = require("axios");
var $iA2ta$caseconverter = require("case-converter");
function $parcel$interopDefault(a) {
return a && a.__esModule ? a.default : a;
}
function $parcel$defineInteropFlag(a) {
Object.defineProperty(a, '__esModule', {value: true, configurable: true});
}
function $parcel$export(e, n, v, s) {
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
}
$parcel$defineInteropFlag(module.exports);
$parcel$export(module.exports, "default", () => $9233cea927cb9637$export$2e2bcd8739ae039);
var $1572597be94ce13f$exports = {};
$1572597be94ce13f$exports = JSON.parse('{"name":"@upscopeio/twilio-flex-component","version":"2025.2.24","description":"Upscope Co-browsing component for Twilio Flex","main":"./dist/UpscopeWidget.js","license":"MIT","scripts":{"component:build":"yarn build && jq \'.main = \\"./UpscopeWidget.js\\"\' package.json > dist/package.json","build":"rm -rf .parcel-cache; parcel build src/index.tsx","dev:watch":"parcel watch src/index.tsx"},"keywords":["Upscope","Cobrowse","Twilio"],"author":"dev@upscope.io","dependencies":{"@sentry/browser":"^7.112.2","@sentry/react":"^7.44.2","@sentry/tracing":"^7.44.2","@twilio/flex-ui":"^2.8.2","axios":"^1.6.8","case-converter":"^1.0.1","debug":"^4.3.4","react":"^18.2.0","react-dom":"^18.2.0","react-timeago":"^7.1.0"},"devDependencies":{"@parcel/optimizer-data-url":"^2.12.0","@parcel/transformer-css":"^2.12.0","@parcel/transformer-inline-string":"^2.12.0","@parcel/transformer-svg-react":"^2.8.3","@types/axios":"^0.14.0","@types/debug":"^4.1.12","@types/react":"^18.2.14","@types/react-dom":"^18.2.14","@types/react-timeago":"^4.1.7","parcel":"^2.8.3","typescript":"5.0.4"},"@parcel/transformer-css":{"cssModules":{"global":true}}}');
class $4e0fc80ff36c942b$export$2e2bcd8739ae039 extends Error {
constructor({ message: message, response: response, status: status }){
super();
this.message = message;
this.response = response;
this.status = status;
}
}
const $20660adb77b18d0d$var$debug = (0, ($parcel$interopDefault($iA2ta$debug)))("upscope:cache");
const $20660adb77b18d0d$var$MINUTES_TO_EXPIRE_CACHE = 5;
function $20660adb77b18d0d$export$75a0f4a65be4542c(cacheKey) {
if (!cacheKey) return;
const key = $20660adb77b18d0d$var$storageKey(cacheKey);
const cache = sessionStorage.getItem(key);
if (!cache) {
$20660adb77b18d0d$var$debug("Cache not found, will fetch the visitor...");
return;
}
$20660adb77b18d0d$var$debug("Visitor found in cache: %o", JSON.parse(cache));
const parsedResponse = JSON.parse(cache);
if (parsedResponse.expiresAt < new Date().getTime()) {
$20660adb77b18d0d$var$debug("Cache expired, removing...");
sessionStorage.removeItem(key);
return;
}
return parsedResponse;
}
function $20660adb77b18d0d$export$1cd522512d0e0bcf(cacheKey, response) {
sessionStorage.setItem($20660adb77b18d0d$var$storageKey(cacheKey), JSON.stringify({
...response,
expiresAt: new Date().getTime() + $20660adb77b18d0d$var$MINUTES_TO_EXPIRE_CACHE * 60000
}));
$20660adb77b18d0d$var$debug("Visitor cached, will expire in 5 minutes: %o", response);
}
function $20660adb77b18d0d$var$storageKey(cacheKey) {
return `upscope:watchLinks:${cacheKey}`;
}
function $9ba0f9a5c47c04f2$export$b70aabe880331950(upscopeEnv) {
if (upscopeEnv === "production") return "https://integrations.userview.com";
if (upscopeEnv === "staging") return "https://integrations.userview.xyz";
return "http://integrations.userview.local";
}
const $8963e835ba2cb6ae$var$debug = (0, ($parcel$interopDefault($iA2ta$debug)))("upscope:upscope_client");
async function $8963e835ba2cb6ae$export$96162cf08faeeb3c({ request: request, searchMethod: searchMethod, integrationToken: integrationToken, upscopeEnv: upscopeEnv }) {
const { conversationId: conversationId } = request;
const visitorFromCache = (0, $20660adb77b18d0d$export$75a0f4a65be4542c)(conversationId);
if (visitorFromCache) return visitorFromCache;
try {
const { data: data } = await (0, ($parcel$interopDefault($iA2ta$axios))).post(`${(0, $9ba0f9a5c47c04f2$export$b70aabe880331950)(upscopeEnv)}/twilioFlex/${searchMethod}`, (0, $iA2ta$caseconverter.toSnakeCase)(request), {
headers: {
"X-Api-Key": integrationToken,
"Content-Type": "application/json"
}
});
const response = (0, $iA2ta$caseconverter.toCamelCase)(data);
if (conversationId) (0, $20660adb77b18d0d$export$1cd522512d0e0bcf)(conversationId, response);
return response;
} catch (error) {
$8963e835ba2cb6ae$var$debug("Error with request: %o", error);
let errorResponse;
if ((0, ($parcel$interopDefault($iA2ta$axios))).isAxiosError(error)) {
if (error.response && typeof error.response.data !== "undefined") errorResponse = (0, $iA2ta$caseconverter.toCamelCase)(error.response.data);
} else errorResponse = {
error: "unknown",
status: "error"
};
const customError = new (0, $4e0fc80ff36c942b$export$2e2bcd8739ae039)({
message: error.message,
status: error.status,
response: errorResponse
});
$8963e835ba2cb6ae$var$debug("Upscope search error: %o", customError);
throw customError;
}
}
async function $8963e835ba2cb6ae$export$d7f5377eac794d6(authUrl) {
const twilioAuthToken = (0, $iA2ta$twilioflexui.Manager).getInstance().user.token;
try {
const { data: data } = await (0, ($parcel$interopDefault($iA2ta$axios))).post(authUrl, {
Token: twilioAuthToken
});
const response = (0, $iA2ta$caseconverter.toCamelCase)(data);
return response;
} catch (error) {
$8963e835ba2cb6ae$var$debug("Error with request auth (%O)", error);
const serverError = new Error(error.response?.data?.message ?? "Unknown request auth error");
serverError.statusCode = error.response?.status;
serverError.response = error.response;
throw serverError;
}
}
var $d7ec9a077a206342$export$a851f5232a518044;
var $d7ec9a077a206342$export$4f723fecf35d9bb1;
var $d7ec9a077a206342$export$ad7e230961880cff;
var $d7ec9a077a206342$export$84a93a92d5727e8b;
var $d7ec9a077a206342$export$9dcbe3d4e8db3dc9;
var $d7ec9a077a206342$export$d76ae9d5882572c9;
var $d7ec9a077a206342$export$ea133318a29f7212;
$d7ec9a077a206342$export$a851f5232a518044 = `pHDwTG_UpscopeWidget__Alert`;
$d7ec9a077a206342$export$4f723fecf35d9bb1 = `pHDwTG_UpscopeWidget__Alert__Error`;
$d7ec9a077a206342$export$ad7e230961880cff = `pHDwTG_UpscopeWidget__Button`;
$d7ec9a077a206342$export$84a93a92d5727e8b = `pHDwTG_UpscopeWidget__Container`;
$d7ec9a077a206342$export$9dcbe3d4e8db3dc9 = `pHDwTG_UpscopeWidget__Input`;
$d7ec9a077a206342$export$d76ae9d5882572c9 = `pHDwTG_UpscopeWidget__Logo`;
$d7ec9a077a206342$export$ea133318a29f7212 = `pHDwTG_UpscopeWidget__Screenshare__Container`;
const $9233cea927cb9637$var$debug = (0, ($parcel$interopDefault($iA2ta$debug)))("upscope:widget");
function $9233cea927cb9637$var$UpscopeWidget({ authUrl: authUrl, upscopeEnv: upscopeEnv }) {
const [errorMessage, setErrorMessage] = (0, $iA2ta$react.useState)();
const [lookupCodeInput, setLookupCodeInput] = (0, $iA2ta$react.useState)();
const [lookupCodeErrorMessage, setLookupCodeErrorMessage] = (0, $iA2ta$react.useState)();
const [showLookupCodeInput, setShowLookupCodeInput] = (0, $iA2ta$react.useState)(false);
const [triedVisitorSearch, setTriedVisitorSearch] = (0, $iA2ta$react.useState)(false);
const [visitor, setVisitor] = (0, $iA2ta$react.useState)();
const [watchLink, setWatchLink] = (0, $iA2ta$react.useState)();
const [conversationSid, setConversationSid] = (0, $iA2ta$react.useState)();
const [loading, setLoading] = (0, $iA2ta$react.useState)(false);
const [integrationToken, setIntegrationToken] = (0, $iA2ta$react.useState)();
(0, $iA2ta$react.useEffect)(()=>{
(0, $8963e835ba2cb6ae$export$d7f5377eac794d6)(authUrl).then(({ integrationToken: integrationToken })=>setIntegrationToken(integrationToken));
}, [
authUrl
]);
if ([
"staging",
"production"
].includes(upscopeEnv)) $iA2ta$sentryreact.init({
dsn: "https://e96ba443f2d74485ae84af150dd77253@o73137.ingest.sentry.io/4504889193136128",
integrations: [
$iA2ta$sentryreact.browserTracingIntegration()
],
environment: upscopeEnv,
release: (0, (/*@__PURE__*/$parcel$interopDefault($1572597be94ce13f$exports))).version
});
function onScreenShare(event) {
event.preventDefault();
window.open(watchLink ?? undefined);
}
const onSuccessRequest = ({ watchLink: watchLink, visitor: visitor })=>{
$9233cea927cb9637$var$debug("Got watch link: %s and visitor: %o", watchLink, visitor);
setWatchLink(watchLink);
setVisitor(visitor);
setLoading(false);
};
const onErrorRequest = (error)=>{
setLoading(false);
$9233cea927cb9637$var$debug("Error request: %o", error);
if (typeof error.response === "undefined") {
$9233cea927cb9637$var$debug("Upscope internal error: %O", error);
setErrorMessage("Upscope is currently not available");
$iA2ta$sentryreact.captureException(error);
return;
}
if (error.response.error === "integration_not_found") {
$9233cea927cb9637$var$debug("Upscope unauthorized error response: %o", error.response);
setErrorMessage("Contact your team admin to setup the integration");
return;
}
if (error.response.error === "not_found") {
$9233cea927cb9637$var$debug("Error with search: %o", error.response);
const { message: message, tryLookupCode: tryLookupCode } = error.response;
setShowLookupCodeInput(tryLookupCode);
setErrorMessage(tryLookupCode ? undefined : message);
setLookupCodeErrorMessage(tryLookupCode ? message : undefined);
} else {
setErrorMessage("An unexpected error occured");
$iA2ta$sentryreact.captureException(error);
}
};
async function onLookupCodeSearch(event) {
event.preventDefault();
if (loading) return;
if (lookupCodeInput && conversationSid && integrationToken) (0, $8963e835ba2cb6ae$export$96162cf08faeeb3c)({
searchMethod: "from_lookup_code",
request: {
lookupCode: lookupCodeInput,
conversationId: conversationSid
},
integrationToken: integrationToken,
upscopeEnv: upscopeEnv
}).then(({ watchLink: watchLink, visitor: visitor })=>{
onSuccessRequest({
watchLink: watchLink,
visitor: visitor
});
window.open(watchLink);
}).catch(onErrorRequest);
}
function onLookupCodeInput(event) {
setLookupCodeInput(event.target.value.replace(/\D/g, ""));
}
const newAppInstance = (0, $iA2ta$react.useCallback)(async (payload)=>{
setLoading(true);
if ("task" in payload && typeof payload.task === "undefined") return;
const conversationData = payload.task._task.attributes;
const workerData = payload.task._task._worker.attributes;
const customerEmail = conversationData.customerEmail;
setConversationSid(()=>conversationData.conversationSid);
const agentName = workerData.full_name;
const agentEmail = workerData.email;
if (conversationSid && integrationToken) (0, $8963e835ba2cb6ae$export$96162cf08faeeb3c)({
searchMethod: "from_visitor_details",
request: {
email: customerEmail,
integrationId: `twilio_flex:${conversationSid}`,
agentName: agentName,
agentEmail: agentEmail,
conversationId: conversationSid
},
integrationToken: integrationToken,
upscopeEnv: upscopeEnv
}).then(onSuccessRequest).catch(onErrorRequest);
}, [
conversationSid,
integrationToken,
upscopeEnv
]);
(0, $iA2ta$react.useEffect)(()=>{
(0, $iA2ta$twilioflexui.Actions).replaceAction("WrapupTask", async (payload, original)=>{
setTriedVisitorSearch(false);
setWatchLink("");
setShowLookupCodeInput(false);
setLookupCodeInput("");
setErrorMessage("");
setLookupCodeErrorMessage("");
setVisitor(undefined);
await original(payload);
});
(0, $iA2ta$twilioflexui.Actions).addListener("afterSelectTask", newAppInstance);
}, [
newAppInstance
]);
return /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsxs)("div", {
className: "UpscopeWidget__Container",
children: [
/*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
className: "UpscopeWidget__Logo"
}),
(()=>{
if (!triedVisitorSearch) return /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
className: "UpscopeWidget__Alert",
children: /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("p", {
children: "Please, select a conversation to start Upscope."
})
});
if (watchLink && visitor) return /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsxs)("div", {
className: "UpscopeWidget__Screenshare__Container",
children: [
/*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
children: "Screen share available"
}),
/*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("button", {
className: "UpscopeWidget__Button",
onClick: onScreenShare,
children: "Screen Share now"
})
]
});
if (showLookupCodeInput) return /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsxs)("div", {
children: [
lookupCodeErrorMessage && /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
className: "UpscopeWidget__Alert",
children: /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("p", {
children: lookupCodeErrorMessage
})
}),
/*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsxs)("form", {
onSubmit: onLookupCodeSearch,
children: [
/*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("input", {
className: "UpscopeWidget__Input",
autoFocus: true,
type: "text",
placeholder: "1234",
value: lookupCodeInput ?? undefined,
onChange: onLookupCodeInput
}),
/*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("button", {
className: "UpscopeWidget__Button",
type: "submit",
children: "Screen share"
})
]
}),
errorMessage && /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
className: "UpscopeWidget__Alert UpscopeWidget__Alert__Error",
children: /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("p", {
children: errorMessage
})
})
]
});
if (errorMessage) return /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
children: /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("div", {
className: "UpscopeWidget__Alert UpscopeWidget__Alert__Error",
children: /*#__PURE__*/ (0, $iA2ta$reactjsxruntime.jsx)("p", {
children: errorMessage
})
})
});
})()
]
});
}
var $9233cea927cb9637$export$2e2bcd8739ae039 = $9233cea927cb9637$var$UpscopeWidget;
//# sourceMappingURL=UpscopeWidget.js.map