UNPKG

@risecx/carespace-chat-ui

Version:

carespace-chat-ui React component

448 lines (403 loc) 12.7 kB
"use strict"; var converter = new showdown.Converter(); converter.setOption("openLinksInNewWindow", true); var Botkit = { config: { ws_url: (location.protocol === "https:" ? "wss" : "ws") + "://" + location.host, reconnect_timeout: 3000, max_reconnect: 5 }, options: { sound: false, use_sockets: true }, reconnect_count: 0, guid: null, current_user: null, on: function on(event, handler) { this.message_window.addEventListener(event, function (evt) { handler(evt.detail); }); }, trigger: function trigger(event, details) { var event = new CustomEvent(event, { detail: details }); this.message_window.dispatchEvent(event); }, request: function request(url, body) { var that = this; return new Promise(function (resolve, reject) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == XMLHttpRequest.DONE) { if (xmlhttp.status == 200) { var response = xmlhttp.responseText; var message = null; try { message = JSON.parse(response); } catch (err) { reject(err); return; } resolve(message); } else { reject(new Error("status_" + xmlhttp.status)); } } }; xmlhttp.open("POST", url, true); xmlhttp.setRequestHeader("Content-Type", "application/json"); xmlhttp.send(JSON.stringify(body)); }); }, send: function send(text, e) { var that = this; if (e) e.preventDefault(); if (!text) { return; } var message = { type: "outgoing", text: text }; this.clearReplies(); that.renderMessage(message); that.deliverMessage({ type: "message", text: text, user: this.guid, channel: this.options.use_sockets ? "socket" : "webhook" }); this.input.value = ""; this.trigger("sent", message); return false; }, deliverMessage: function deliverMessage(message) { if (this.options.use_sockets) { this.socket.send(JSON.stringify(message)); } else { this.webhook(message); } }, getHistory: function getHistory(guid) { var that = this; if (that.guid) { that.request("/botkit/history", { user: that.guid }).then(function (history) { if (history.success) { that.trigger("history_loaded", history.history); } else { that.trigger("history_error", new Error(history.error)); } })["catch"](function (err) { that.trigger("history_error", err); }); } }, webhook: function webhook(message) { var that = this; that.request("/botkit/receive", message).then(function (message) { that.trigger(message.type, message); })["catch"](function (err) { that.trigger("webhook_error", err); }); }, connect: function connect(user) { var that = this; if (user && user.id) { Botkit.setCookie("botkit_guid", user.id, 1); user.timezone_offset = new Date().getTimezoneOffset(); that.current_user = user; console.log("CONNECT WITH USER", user); } // connect to the chat server! if (that.options.use_sockets) { that.connectWebsocket(that.config.ws_url); } else { that.connectWebhook(); } }, connectWebhook: function connectWebhook() { var that = this; if (Botkit.getCookie("botkit_guid")) { that.guid = Botkit.getCookie("botkit_guid"); connectEvent = "welcome_back"; } else { that.guid = that.generate_guid(); Botkit.setCookie("botkit_guid", that.guid, 1); } that.getHistory(); // connect immediately that.trigger("connected", {}); that.webhook({ type: connectEvent, user: that.guid, channel: "webhook" }); }, connectWebsocket: function connectWebsocket(ws_url) { var that = this; // Create WebSocket connection. that.socket = new WebSocket(ws_url); var connectEvent = "hello"; if (Botkit.getCookie("botkit_guid")) { that.guid = Botkit.getCookie("botkit_guid"); connectEvent = "welcome_back"; } else { that.guid = that.generate_guid(); Botkit.setCookie("botkit_guid", that.guid, 1); } that.getHistory(); // Connection opened that.socket.addEventListener("open", function (event) { console.log("CONNECTED TO SOCKET"); that.reconnect_count = 0; that.trigger("connected", event); that.deliverMessage({ type: connectEvent, user: that.guid, channel: "socket", user_profile: that.current_user ? that.current_user : null }); }); that.socket.addEventListener("error", function (event) { console.error("ERROR", event); }); that.socket.addEventListener("close", function (event) { console.log("SOCKET CLOSED!"); that.trigger("disconnected", event); if (that.reconnect_count < that.config.max_reconnect) { setTimeout(function () { console.log("RECONNECTING ATTEMPT ", ++that.reconnect_count); that.connectWebsocket(that.config.ws_url); }, that.config.reconnect_timeout); } else { that.message_window.className = "offline"; } }); // Listen for messages that.socket.addEventListener("message", function (event) { var message = null; try { message = JSON.parse(event.data); } catch (err) { that.trigger("socket_error", err); return; } that.trigger(message.type, message); }); }, clearReplies: function clearReplies() { this.replies.innerHTML = ""; }, quickReply: function quickReply(payload) { this.send(payload); }, focus: function focus() { this.input.focus(); }, renderMessage: function renderMessage(message) { var that = this; if (!that.next_line) { that.next_line = document.createElement("div"); that.message_list.appendChild(that.next_line); } if (message.text) { message.html = converter.makeHtml(message.text); } that.next_line.innerHTML = that.message_template({ message: message }); if (!message.isTyping) { delete that.next_line; } }, triggerScript: function triggerScript(script, thread) { this.deliverMessage({ type: "trigger", user: this.guid, channel: "socket", script: script, thread: thread }); }, identifyUser: function identifyUser(user) { user.timezone_offset = new Date().getTimezoneOffset(); this.guid = user.id; Botkit.setCookie("botkit_guid", user.id, 1); this.current_user = user; this.deliverMessage({ type: "identify", user: this.guid, channel: "socket", user_profile: user }); }, receiveCommand: function receiveCommand(event) { switch (event.data.name) { case "trigger": // tell Botkit to trigger a specific script/thread console.log("TRIGGER", event.data.script, event.data.thread); Botkit.triggerScript(event.data.script, event.data.thread); break; case "identify": // link this account info to this user console.log("IDENTIFY", event.data.user); Botkit.identifyUser(event.data.user); break; case "connect": // link this account info to this user Botkit.connect(event.data.user); break; default: console.log("UNKNOWN COMMAND", event.data); } }, sendEvent: function sendEvent(event) { if (this.parent_window) { this.parent_window.postMessage(event, "*"); } }, setCookie: function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000); var expires = "expires=" + d.toUTCString(); document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; }, getCookie: function getCookie(cname) { var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(";"); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == " ") { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; }, generate_guid: function generate_guid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); } return s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4(); }, boot: function boot(user) { console.log("Booting up"); var that = this; that.message_window = document.getElementById("message_window"); that.message_list = document.getElementById("message_list"); var source = document.getElementById("message_template").innerHTML; that.message_template = Handlebars.compile(source); that.replies = document.getElementById("message_replies"); that.input = document.getElementById("messenger_input"); that.focus(); that.on("connected", function () { that.message_window.className = "connected"; that.input.disabled = false; that.sendEvent({ name: "connected" }); }); that.on("disconnected", function () { that.message_window.className = "disconnected"; that.input.disabled = true; }); that.on("webhook_error", function (err) { alert("Error sending message!"); console.error("Webhook Error", err); }); that.on("typing", function () { that.clearReplies(); that.renderMessage({ isTyping: true }); }); that.on("sent", function () { if (that.options.sound) { var audio = new Audio("sent.mp3"); audio.play(); } }); that.on("message", function () { if (that.options.sound) { var audio = new Audio("beep.mp3"); audio.play(); } }); that.on("message", function (message) { that.renderMessage(message); }); that.on("message", function (message) { if (message.goto_link) { window.location = message.goto_link; } }); that.on("message", function (message) { that.clearReplies(); if (message.quick_replies) { var list = document.createElement("ul"); var elements = []; for (var r = 0; r < message.quick_replies.length; r++) { (function (reply) { var li = document.createElement("li"); var el = document.createElement("a"); el.innerHTML = reply.title; el.href = "#"; el.onclick = function () { that.quickReply(reply.payload); }; li.appendChild(el); list.appendChild(li); elements.push(li); })(message.quick_replies[r]); } that.replies.appendChild(list); // uncomment this code if you want your quick replies to scroll horizontally instead of stacking // var width = 0; // // resize this element so it will scroll horizontally // for (var e = 0; e < elements.length; e++) { // width = width + elements[e].offsetWidth + 18; // } // list.style.width = width + 'px'; if (message.disable_input) { that.input.disabled = true; } else { that.input.disabled = false; } } else { that.input.disabled = false; } }); that.on("history_loaded", function (history) { if (history) { for (var m = 0; m < history.length; m++) { that.renderMessage({ text: history[m].text, type: history[m].type == "message_received" ? "outgoing" : "incoming" // set appropriate CSS class }); } } }); if (window.self !== window.top) { // this is embedded in an iframe. // send a message to the master frame to tell it that the chat client is ready // do NOT automatically connect... rather wait for the connect command. that.parent_window = window.parent; window.addEventListener("message", that.receiveCommand, false); that.sendEvent({ type: "event", name: "booted" }); console.log("Messenger booted in embedded mode"); } else { console.log("Messenger booted in stand-alone mode"); // this is a stand-alone client. connect immediately. that.connect(user); } return that; } }; (function () { // your page initialization code here // the DOM will be available here Botkit.boot(); })();