3 angular.module("motion", ["ngAnimate", "ngAria", "ngMessages", "ngMaterial", "ngResource", "ngSanitize", "ngCsv", "ngEmbed", "ui.router", "LocalStorageModule", "ngRateIt", "flow"]).constant("STORAGE_PREFIX", "motion_chat").constant("STORAGE_VISITOR", "visitor").constant("STORAGE_LAYOUT", "layout").directive("ngEnter", function() {
4 return function(e, n, t) {
5 n.bind("keydown keypress", function(n) {
6 13 === n.which && (e.$apply(function() {
8 }), n.preventDefault())
16 function e(e, n, t, i, o, r, a, s, l, c, d) {
18 n.settings.online ? r.go("app.online") : r.go("app.offline")
22 n.visitor && n.visitor.interaction && n.visitor.interaction.id && l.chatInteraction.get({
23 id: n.visitor.interaction.id
24 }).$promise.then(function(e) {
25 delete k.errors.getInteraction, e.closed && (n.visitor.interaction.closed = !0, s.set(c, n.visitor), "unmanaged" === e.disposition ? r.go("app.unmanaged") : r.go("app.closing"))
26 }).catch(function(e) {
35 r.go("app.unmanaged");
45 k.errors[e] = n.data, x()
50 var t = b[0].emojioneArea.getText();
51 e && 13 === e.keyCode && e.shiftKey || e && 13 !== e.keyCode || "" !== t && f(_.merge({
57 l.chatWebsite.notify(e).$promise.then(function(e) {
58 delete k.errors.chatMessageError, _.isNil(n.visitor.interaction) && (n.visitor.interaction = {
60 }, s.set(c, n.visitor)), b[0].emojioneArea.setText(""), x()
61 }).catch(g("chatMessageError"))
65 n.visitor && n.visitor.interaction && n.visitor.interaction.id && l.chatInteraction.getMessages({
66 intid: n.visitor.interaction.id,
68 }).$promise.then(function(e) {
69 if (delete k.errors.interaction, e.count) {
70 T = e.rows[e.count - 1].id;
71 for (var n = 0; n < e.rows.length; n++) k.messages.push(e.rows[n]), "out" !== e.rows[n].direction || e.rows[n].read || h(e.rows[n].id);
74 }).catch(function(e) {
80 r.go("app.unmanaged");
89 return l.chatMessage.update({
92 }).$promise.catch(function(e) {
99 var e = o[0].getElementsByClassName("chat-messages")[0];
100 e && (e.scrollTop = e.scrollHeight)
103 var b, y, w, T, k = this;
104 k.errors = {}, k.messages = [], k.emojiOptions = {
110 }, k.$onInit = function() {
111 n.loading = !1, n.settings.showMenu = !0, n.visitor = s.get(c) || {}, n.layout = s.get(d) || {}, k.replyMessage = "", n.visitor.interaction && n.visitor.interaction.closed ? (s.remove(c), m()) : (u(), y = i(v, 2e3), w = i(u, 3e3)), b = $("#emojionearea").emojioneArea({
112 placeholder: "Type a message",
114 keyup: function(e, n) {
119 }, k.reply = p, k.fileAdded = function(e) {
120 var t = new FormData;
121 t.append("file", e.file), a.post(n.settings.remote + "/api/chat/interactions/" + n.visitor.interaction.id + "/attachment_upload?token=" + n.settings.token, t, {
122 transformRequest: angular.identity,
124 "Content-Type": void 0
126 }).then(function(e) {
127 (e = e.data).id ? (delete k.errors.sendAttachment, f(_.merge({
128 body: '<a href="' + n.settings.remote + "/api/chat/interactions/" + n.visitor.interaction.id + "/attachment_download?attachId=" + e.id + "&token=" + n.settings.token + '" target="_blank">' + e.name + "</a>",
130 }, n.visitor))) : g("sendAttachment")
131 }, g("sendAttachment"))
132 }, e.$on("$destroy", function() {
133 i.cancel(y), i.cancel(w), y = null, w = null
134 }), n.$on("$download", function(e, n) {
135 n && n(_.values(k.messages))
138 e.$inject = ["$scope", "$rootScope", "$timeout", "$interval", "$document", "$state", "$http", "localStorageService", "api", "STORAGE_VISITOR", "STORAGE_LAYOUT"], angular.module("motion").controller("ChatController", e)
143 function e(e, n, t, i, o, r) {
145 n.settings.online ? t.go("app.online") : t.go("app.offline")
149 d.form = {}, d.upColor = null, d.downColor = null, d.userForm.$setPristine(), d.userForm.$setUntouched(), i.remove(r), n.enableDownload = !1
162 d.$onInit = function() {
163 d.visitor = i.get(r) || {}, i.remove(r), delete n.visitor.interaction
164 }, d.submit = function() {
165 n.loading = !0, d.visitor.interaction && d.visitor.interaction.id ? o.chatInteraction.close(_.merge({
166 id: d.visitor.interaction.id,
167 ratingType: n.settings.ratingType
168 }, d.form)).$promise.then(function(e) {
169 delete d.errors.submit
170 }).then(s).then(a).catch(l("submit")).finally(c) : (c(), l("submit"))
171 }, d.skip = function() {
173 }, d.form = {}, d.errors = {}
175 e.$inject = ["$scope", "$rootScope", "$state", "localStorageService", "api", "STORAGE_VISITOR"], angular.module("motion").controller("ClosingController", e)
180 function e(e, n, t, i, o, r, a, s, l, c, d) {
182 o.go(n.settings.online ? "app.online" : "app.offline")
186 t.parent.postMessage({
192 n.layout.up = e, s.set(c, n.layout), u(e ? "show" : "hide")
195 p.$onInit = function() {
196 n.visitor = s.get(d) || {}, n.layout = s.get(c) || {
198 }, g(!!n.layout.up), m()
199 }, p.close = function() {
200 var e = s.get(d).interaction;
202 var n = r.confirm().parent(angular.element(document.querySelector("#chat-app"))).clickOutsideToClose(!0).title("Do you wanto to close the interaction?").ok("Ok").cancel("Cancel");
203 r.show(n).then(function() {
204 return l.chatInteraction.update({
207 closedAt: moment().format("YYYY-MM-DD HH:mm:ss")
211 }).catch(function(e) {
212 console.error("keep open", e)
215 }, p.toggle = g, p.download = function(e) {
217 t = s.get(d).interaction;
218 return t && t.id && l.chatInteraction.getMessages({
220 }).$promise.then(function(e) {
221 n.resolve(_.map(e.rows, function(e) {
223 sender: "in" === e.direction ? "Visitor" + e.ContactId : e.UserId ? "Agent" + e.UserId : "System",
225 createdAt: moment(e.createdAt).format("MM/DD/YYYY HH:mm:ss")
228 }).catch(function(e) {
231 }, p.getHeaderShape = function() {
232 return "rounded" === n.settings.header_shape ? "15px" : "0px"
233 }, window.addEventListener("message", function(e) {
234 g("show" === e.data.evt)
237 e.$inject = ["$scope", "$rootScope", "$window", "$http", "$state", "$mdDialog", "$q", "localStorageService", "api", "STORAGE_LAYOUT", "STORAGE_VISITOR"], angular.module("motion").controller("IndexController", e)
244 baseUrl: e.settings.remote + "/api/"
248 token: e.settings.token
250 return t.chatWebsite = n(t.baseUrl + "chat/websites/:id", i, {
253 url: t.baseUrl + "chat/websites/:id/notify"
257 url: t.baseUrl + "chat/websites/:id/offline"
261 url: t.baseUrl + "chat/websites/:id/fields"
263 }), t.chatInteraction = n(t.baseUrl + "chat/interactions/:id", i, {
266 url: t.baseUrl + "chat/interactions/:id"
270 url: t.baseUrl + "chat/interactions/:id/close"
274 url: t.baseUrl + "chat/interactions/:intid/my_messages"
278 url: t.baseUrl + "chat/interactions/:id/attachment_upload",
280 "Content-Type": void 0
282 transformRequest: angular.identity
284 downloadAttachment: {
286 url: t.baseUrl + "chat/interactions/:id/attachment_download"
288 }), t.chatMessage = n(t.baseUrl + "chat/messages/:id", i, {
291 url: t.baseUrl + "chat/messages/:id"
295 e.$inject = ["$rootScope", "$resource"], angular.module("motion").factory("api", e)
305 }, _.forIn(t, function(n, t) {
306 "" === n || _.isNil(n) || ("true" === n && (n = !0), "false" === n && (n = !1), e.settings[t] = n)
310 function n(e, n, t, i, o, r) {
311 t.html5Mode(!0), i.defaults.headers.get || (i.defaults.headers.get = {}), i.defaults.headers.get["If-Modified-Since"] = "Mon, 26 Jul 1997 05:00:00 GMT", i.defaults.headers.get["Cache-Control"] = "no-cache", i.defaults.headers.get.Pragma = "no-cache", o.setPrefix(r), e.state("app", {
314 }).state("app.waiting", {
316 templateUrl: "app/waiting/index.html",
317 controller: "WaitingController as vm"
318 }).state("app.online", {
320 templateUrl: "app/online/index.html",
321 controller: "OnlineController as vm"
322 }).state("app.offline", {
324 templateUrl: "app/offline/index.html",
325 controller: "OfflineController as vm"
326 }).state("app.chat", {
328 templateUrl: "app/chat/index.html",
329 controller: "ChatController as vm"
330 }).state("app.unmanaged", {
332 templateUrl: "app/unmanaged/index.html",
333 controller: "UnmanagedController as vm"
334 }).state("app.closing", {
336 templateUrl: "app/closing/index.html",
337 controller: "ClosingController as vm"
340 e.$inject = ["$rootScope", "$location"], n.$inject = ["$stateProvider", "$urlRouterProvider", "$locationProvider", "$httpProvider", "localStorageServiceProvider", "STORAGE_PREFIX"], angular.module("motion").config(n).run(e)
345 function e(e, n, t, i, o, r, a, s, l, c) {
357 return "Anonymous" + _.random(1, 1e6)
361 g.$onInit = function() {
364 mapKeyOffline: "firstName",
366 }, n.settings.showMenu = !1, s.chatWebsite.getFields({
369 }).$promise.then(function(e) {
370 e.count && (p = e.fromKey, g.fields = e.rows)
371 }).catch(function(e) {
374 }, g.submit = function() {
375 for (var e = 0; e < g.fields.length; e++) {
377 t.props && g.form.hasOwnProperty(t.props.title) && (_.isNil(t.cmField) || (g.visitor[t.cmField] = _.isArray(g.form[t.props.title]) ? g.form[t.props.title].join() : g.form[t.props.title]), e === p && (_.isNil(n.settings.mapKeyOffline) || (g.visitor.mapKeyOffline = n.settings.mapKeyOffline, g.visitor.from = _.isArray(g.form[t.props.title]) ? g.form[t.props.title].join() : g.form[t.props.title])))
379 n.loading = !0, s.chatWebsite.offline(_.merge({
381 }, g.visitor)).$promise.then(function(e) {
382 delete g.errors.submit, g.form = {}, g.userForm.$setPristine(), g.userForm.$setUntouched(), n.$emit("hide")
383 }).catch(d("submit")).finally(m)
384 }, g.toggle = function(e, n) {
385 g.form[e] || (g.form[e] = []);
386 var t = g.form[e].indexOf(n);
387 t > -1 ? g.form[e].splice(t, 1) : g.form[e].push(n)
388 }, g.exists = function(e, n) {
389 return g.form[e] || (g.form[e] = []), g.form[e].indexOf(n) > -1
390 }, g.form = {}, g.errors = {}, g.userForm = {}
392 e.$inject = ["$scope", "$rootScope", "$state", "$window", "$timeout", "localStorageService", "$http", "api", "STORAGE_PREFIX", "STORAGE_VISITOR"], angular.module("motion").controller("OfflineController", e)
397 function e(e, n, t, i, o, r, a, s, l, c) {
399 n.settings.enableCustomerWriting ? t.go("app.chat") : t.go("app.waiting")
403 g.disableItem = !0, s.chatWebsite.notify(e).$promise.then(function(e) {
404 delete g.errors.chatMessageError, g.visitor.message = {
406 }, g.visitor.interaction = {
408 }, r.set(c, g.visitor), g.disableItem = !1, d()
409 }).catch(function(e) {
410 g.disableItem = !1, console.error(e)
415 return "Anonymous" + _.random(1, 1e6)
419 g.$onInit = function() {
420 r.get(c) && (g.visitor = r.get(c)), g.visitor && g.visitor.interaction ? g.visitor.interaction.UserId ? t.go("app.chat") : t.go("app.waiting") : (g.visitor = {
424 }, n.settings.showMenu = !1, r.set(c, g.visitor), s.chatWebsite.getFields({
427 }).$promise.then(function(e) {
428 e.count && (p = e.fromKey, g.fields = e.rows)
429 }).catch(function(e) {
432 }, g.submit = function() {
433 for (var e = "", t = 0; t < g.fields.length; t++) {
435 i.props && g.form.hasOwnProperty(i.props.title) && (_.isNil(i.variable) || (g.visitor[i.variable] = _.isArray(g.form[i.props.title]) ? g.form[i.props.title].join() : g.form[i.props.title]), _.isNil(i.cmField) || (g.visitor[i.cmField] = _.isArray(g.form[i.props.title]) ? g.form[i.props.title].join() : g.form[i.props.title]), t === p && (_.isNil(n.settings.mapKey) || (g.visitor.mapKey = n.settings.mapKey, g.visitor.from = _.isArray(g.form[i.props.title]) ? g.form[i.props.title].join() : g.form[i.props.title])), e += i.props.title + ": " + g.form[i.props.title] + "\n")
439 referer: n.settings.referer,
440 customerIp: n.settings.customerIp
442 }, g.toggle = function(e, n) {
443 g.form[e] || (g.form[e] = []);
444 var t = g.form[e].indexOf(n);
445 t > -1 ? g.form[e].splice(t, 1) : g.form[e].push(n)
446 }, g.exists = function(e, n) {
447 return g.form[e] || (g.form[e] = []), g.form[e].indexOf(n) > -1
448 }, g.form = {}, g.errors = {}, g.userForm = {}, g.disableItem = !1
450 e.$inject = ["$scope", "$rootScope", "$state", "$window", "$timeout", "localStorageService", "$http", "api", "STORAGE_PREFIX", "STORAGE_VISITOR"], angular.module("motion").controller("OnlineController", e)
455 function e(e, n, t, i, o, r) {
457 n.settings.online ? t.go("app.online") : t.go("app.offline")
461 d.form = {}, d.upColor = null, d.downColor = null, d.userForm.$setPristine(), d.userForm.$setUntouched(), i.remove(r), n.enableDownload = !1, n.$emit("hide")
474 d.form = {}, d.errors = {}, d.$onInit = function() {
475 d.visitor = i.get(r) || {}, i.remove(r)
476 }, d.submit = function() {
477 n.loading = !0, d.visitor.interaction && d.visitor.interaction.id ? o.chatInteraction.update({
478 id: d.visitor.interaction.id,
480 }).$promise.then(function(e) {
481 delete d.errors.submit
482 }).then(s).then(a).catch(l("submit")).finally(c) : (c(), l("submit"))
483 }, d.skip = function() {
487 e.$inject = ["$scope", "$rootScope", "$state", "localStorageService", "api", "STORAGE_VISITOR"], angular.module("motion").controller("UnmanagedController", e)
492 function e(e, n, t, i, o, r, a, s, l, c) {
494 l.chatInteraction.get({
495 id: g.visitor.interaction.id
496 }).$promise.then(function(e) {
497 e.closed && (g.visitor.interaction.closed = !0, s.set(c, g.visitor), "unmanaged" === e.disposition && i.go("app.unmanaged")), e.UserId && (g.visitor.interaction.UserId = e.UserId, s.set(c, g.visitor), i.go("app.chat"))
498 }).catch(function(e) {
504 i.go("app.unmanaged");
513 if (g.visitor && g.visitor.interaction && g.visitor.interaction.id && !p) {
515 var n = new XMLHttpRequest;
516 n.open("PUT", e.settings.remote + "/api/chat/interactions/" + g.visitor.interaction.id + "/abandon?token=" + e.settings.token, !1), n.setRequestHeader("Content-type", "application/json; charset=utf-8"), n.send(JSON.stringify({
519 id: g.visitor.interaction.id
522 id: g.visitor.message.id
524 disposition: "abandoned",
526 closedAt: moment().format("YYYY-MM-DD HH:mm:ss")
527 })), 4 === n.readyState && 200 === n.status && s.remove(c)
532 g.$onInit = function() {
533 g.visitor && g.visitor.interaction && g.visitor.interaction.id && (u = t(d, 3e3))
534 }, g.visitor = s.get(c) || {}, n.$on("$destroy", function() {
535 a.removeEventListener("beforeunload", m), a.removeEventListener("unload", m), t.cancel(u)
536 }), a.addEventListener("beforeunload", m), a.addEventListener("unload", m)
538 e.$inject = ["$rootScope", "$scope", "$interval", "$state", "$transitions", "$q", "$window", "localStorageService", "api", "STORAGE_VISITOR"], angular.module("motion").controller("WaitingController", e)
539 }(), angular.module("motion").run(["$templateCache", function(e) {
541 e.put("app/chat/index.html", '\x3c!-- CHAT CONTENT --\x3e\n<md-content class="chat-messages">\n <div layout="row" ng-if="!$first" ng-repeat="(key, message) in vm.messages track by message.id" class="md-padding message-row" ng-class="{\'in\': message.direction === \'in\', \'out\': message.direction === \'out\' && message.UserId, \'auto\': message.direction === \'out\' && !message.UserId}">\n <img ng-if="message.direction ===\'out\' && !message.UserId" src="assets/images/avatars/robot0.png" class="avatar" alt="system" />\n <img ng-if="message.direction ===\'out\' && message.UserId" ng-src="{{settings.remote}}/api/{{settings.showAgentAvatar ? \'users/\' + visitor.interaction.UserId + \'/avatar\' : \'chat/websites/\' + settings.id + \'/avatar\'}}?token={{settings.token}}" class="avatar" alt="agent" />\n <img ng-if="message.direction ===\'in\'" src="assets/images/avatars/customer0.png" class="avatar" alt="customer" />\n\n <div class="bubble">\n <div class="time secondary-text">\n <span>\n {{message.direction === \'out\' ? (message.UserId ? (settings.agentAlias || \'Agent\') + message.UserId : \'System\') : (vm.visitor.from || \'Visitor\' + message.ContactId)}} - {{message.createdAt | date : \'h:mm\'}}\n </span>\n </div>\n <div ng-class="{\'in\': message.direction === \'in\', \'out\': message.direction ===\'out\' && message.UserId, \'auto\': message.direction ===\'out\' && !message.UserId}">\n <div ng-if="message.AttachmentId" ng-bind-html="message.body" class="message"></div>\n <div ng-if="!message.AttachmentId" ng-bind-html="message.body | embed:vm.emojiOptions" class="message"></div>\n </div>\n </div>\n\n </div>\n\n \x3c!-- CHAT ERROR --\x3e\n <div class="chat-error" ng-repeat="error in vm.errors" layout="row" layout-align="center end" layout-margin>\n <i class="mdi mdi-alert mdi-24px mdi-light"></i>\n <md-tooltip md-direction="top">{{error.message || \'Service temporarily unavailable.\'}}</md-tooltip>\n <span class="chat-error-message">{{error.message || \'Service temporarily unavailable.\'}}</span>\n </div>\n \x3c!-- CHAT ERROR --\x3e\n<md-content>\n\x3c!-- / CHAT CONTENT --\x3e\n\n\x3c!-- CHAT FOOTER --\x3e\n<div class="chat-footer" layout="row" layout-align="center center">\n <input type="text" id="emojionearea"/>\n\n <div layout="row" layout-align="end center">\n <md-button ng-if="settings.enableCustomerAttachment" class="md-fab md-mini md-warn" type="button" flow-init flow-btn flow-file-added="vm.fileAdded($file, $event, $flow)">\n <i class="mdi mdi-attachment mdi-24px mdi-light"></i>\n </md-button>\n </div>\n</div>\n\x3c!-- / CHAT FOOTER--\x3e\n'), e.put("app/closing/index.html", '\x3c!-- CHAT CONTENT --\x3e\n<md-content class="chat-online">\n \x3c!-- CHAT ERROR --\x3e\n <div class="chat-error" ng-repeat="error in vm.errors" layout="row" layout-margin>\n <i class="mdi mdi-alert mdi-24px mdi-light"></i>\n <md-tooltip md-direction="top">{{error.message || \'Service temporarily unavailable.\'}}</md-tooltip>\n <span class="chat-error-message">{{error.message || \'Service temporarily unavailable.\'}}</span>\n </div>\n \x3c!-- CHAT ERROR --\x3e\n\n <md-content layout="row" layout-align="center end">\n <span class="input-title">{{ settings.closingMessage }}</span>\n </md-content>\n\n <form name="vm.userForm" layout="column" novalidate>\n <md-input-container ng-if="settings.enableRating" class="md-block" ng-switch="settings.ratingType" md-no-float>\n \x3c!-- START thumb rating --\x3e\n <md-radio-group name="ratingValue" ng-switch-when="thumb" ng-model="vm.form.ratingValue" ng-change="vm.upColor = vm.form.ratingValue ? \'green\' : null; vm.downColor = !vm.form.ratingValue ? \'red\' : null;" layout="row" layout-align="center center">\n <md-radio-button ng-value="1" class="thumb">\n <div class="{{vm.upColor}}">\n <i class="mdi mdi-48px mdi-thumb-up-outline"></i>\n </div>\n </md-radio-button>\n <md-radio-button ng-value="0" class="thumb">\n <div class="{{vm.downColor}}">\n <i class="mdi mdi-48px mdi-thumb-down-outline"></i>\n </div>\n </md-radio-button>\n </md-radio-group>\n \x3c!-- END thumb rating --\x3e\n\n \x3c!-- START star rating --\x3e\n <div ng-switch-when="star" layout="row" layout-align="center center">\n <ng-rate-it name="ratingValue" ng-model="vm.form.ratingValue" min="0" max="settings.ratingStarsNumber" step="1" star-width="32" star-height="32" class="bigstar rate" resetable="false"></ng-rate-it>\n </div>\n \x3c!-- END star rating --\x3e\n </md-input-container>\n\n <md-input-container ng-if="settings.enableFeedback" class="md-block" md-no-float>\n \x3c!-- START textarea --\x3e\n <span class="input-title">Feedback</span>\n <textarea name="message" ng-model="vm.form.ratingMessage" md-maxlength="150" rows="2"></textarea>\n \x3c!-- END textarea --\x3e\n </md-input-container>\n\n <md-input-container class="md-block" ng-if="settings.forwardTranscript" md-no-float>\n <span ng-if="settings.forwardTranscriptMessage" class="input-title">{{settings.forwardTranscriptMessage}}</span>\n <span ng-if="!settings.forwardTranscriptMessage" class="input-title">Email</span>\n \x3c!-- START email --\x3e\n <input type="email" name="mailTranscript" ng-model="vm.form.mailTranscript">\n <div ng-messages="vm.userForm[\'mailTranscript\'].$error" ng-show="vm.userForm[\'mailTranscript\'].$touched" role="alert">\n <div ng-message="email">\n <span>Email must be a valid e-mail address</span>\n </div>\n </div>\n \x3c!-- END email --\x3e\n </md-input-container>\n\n <div layout="row" layout-align="center center">\n <md-button class="md-raised" ng-if="settings.enableRating || settings.enableFeedback || settings.forwardTranscript" ng-click="vm.submit()" ng-disabled="vm.userForm.$invalid" ng-style="{\'background-color\': \'{{settings.color_button}}\'}">{{settings.closingMessageButton}}</md-button>\n <md-button class="md-raised" ng-style="{\'background-color\': \'{{settings.color_button}}\'}" ng-click="vm.skip()">{{settings.skipMessageButton}}</md-button>\n </div>\n </form>\n\n <md-content layout="row" layout-align="center end">\n <span class="input-title">{{ (settings.custom && !settings.defaultWhiteLabel) ? settings.whiteLabel : \'Powered By XCALLY\' }}</span>\n </md-content>\n\n</md-content>\n\x3c!-- / CHAT CONTENT --\x3e\n'), e.put("app/offline/index.html", '\x3c!-- CHAT CONTENT --\x3e\n<md-content class="chat-online">\n <form ng-if="vm.fields.length" name="vm.userForm" layout="column" novalidate>\n <div ng-repeat="field in ::vm.fields | orderBy:\'index\'" layout="column">\n <span class="input-title">{{field.props.title + (field.config.required ? \'*\' : \'\')}}</span>\n\n <span style="font-size: 13px; line-height: 14px; color: grey;">\n <div ng-bind-html="field.props.helpText | embed:{linkTarget:\'_blank\'}"></div>\n </span>\n\n \x3c!-- CHAT ERROR --\x3e\n <div class="chat-error" ng-repeat="error in vm.errors" layout="row" layout-margin>\n <i class="mdi mdi-alert mdi-24px mdi-light"></i>\n <md-tooltip md-direction="top">{{error.message || \'Service temporarily unavailable.\'}}</md-tooltip>\n <span class="chat-error-message">{{error.message || \'Service temporarily unavailable.\'}}</span>\n </div>\n \x3c!-- CHAT ERROR --\x3e\n\n <md-input-container class="md-block" ng-switch="field.type">\n \x3c!-- START label --\x3e\n <div ng-switch-when="label">\n <md-content flex layout-padding layout="row" layout-align="center center">\n <span class="input-title">{{field.value}}</span>\n </md-content>\n </div>\n \x3c!-- END label --\x3e\n\n \x3c!-- START textinput --\x3e\n <div ng-switch-when="input">\n <input name="{{field.props.title}}" ng-model="vm.form[field.props.title]" type="{{field.config.type}}" ng-required="field.config.required">\n </div>\n \x3c!-- END textinput --\x3e\n\n \x3c!-- START textarea --\x3e\n <div ng-switch-when="textarea">\n <textarea name="{{field.props.title}}" ng-model="vm.form[field.props.title]" md-maxlength="150" rows="3"></textarea>\n </div>\n \x3c!-- END textarea --\x3e\n\n \x3c!-- START select --\x3e\n <div ng-switch-when="chooseFromList">\n <md-select name="{{field.props.title}}"ng-model="vm.form[field.props.title]" ng-required="field.config.required">\n <md-option ng-repeat="option in ::field.options" ng-value="option.value">{{option.value}}</md-option>\n </md-select>\n </div>\n \x3c!-- END select --\x3e\n\n \x3c!-- START radio --\x3e\n <div ng-switch-when="multipleChoices" layout="{{field.config.direction === \'vertical\' ? \'row\' : \'column\'}}">\n <md-radio-group name="{{field.props.title}}" ng-model="vm.form[field.props.title]" ng-required="field.config.required" layout="{{field.config.direction === \'vertical\' ? \'row\' : \'column\'}}">\n <md-radio-button ng-repeat="option in ::field.options" value="{{option.value}}" class="md-primary">{{option.value}}</md-radio-button>\n </md-radio-group>\n </div>\n \x3c!-- END radio --\x3e\n\n \x3c!-- START checkbox --\x3e\n <div ng-switch-when="checkboxes" layout="{{field.config.direction === \'vertical\' ? \'row\' : \'column\'}}">\n <div layout="{{field.config.direction === \'vertical\' ? \'column\' : \'row\'}}">\n <md-checkbox\n md-no-ink\n aria-label="{{field.props.title}}"\n ng-repeat="option in ::field.options"\n ng-checked="vm.exists(field.props.title, option.value)"\n ng-disabled="!vm.exists(field.props.title, option.value) && field.config.maxSelections === vm.form[field.props.title].length"\n ng-click="vm.toggle(field.props.title, option.value)"\n flex>\n {{option.value}}\n </md-checkbox>\n </div>\n </div>\n \x3c!-- END checkbox --\x3e\n\n \x3c!-- START agreement --\x3e\n <div ng-switch-when="agreement" layout="column">\n <md-checkbox md-no-ink ng-model="vm.form[field.props.title]" aria-label="{{field.props.title}}" ng-required="field.config.required">\n {{field.options[0].value}}\n </md-checkbox>\n </div>\n \x3c!-- END agreement --\x3e\n </md-input-container>\n </div>\n\n <md-button ng-click="vm.submit()" class="md-raised" ng-disabled="vm.userForm.$invalid || vm.userForm.$pristine" ng-style="{\'background-color\': \'{{settings.color_button}}\'}">{{settings.offline_chat_button}}</md-button>\n </form>\n\n <md-content layout="row" layout-align="center end">\n <span class="input-title">{{ (settings.custom && !settings.defaultWhiteLabel) ? settings.whiteLabel : \'Powered By XCALLY\' }}</span>\n </md-content>\n</md-content>\n\x3c!-- / CHAT CONTENT --\x3e\n'), e.put("app/online/index.html", '\x3c!-- CHAT CONTENT --\x3e\n<md-content class="chat-online">\n <form ng-if="vm.fields.length" name="vm.userForm" layout="column" novalidate>\n <div ng-repeat="field in ::vm.fields | orderBy:\'index\'" layout="column">\n <span class="input-title">{{field.props.title + (field.config.required ? \'*\' : \'\')}}</span>\n\n <span style="font-size: 13px; line-height: 14px; color: grey;">\n <div ng-bind-html="field.props.helpText | embed:{linkTarget:\'_blank\'}"></div>\n </span>\n\n <md-input-container ng-switch="field.type">\n \x3c!-- START label --\x3e\n <div ng-switch-when="label">\n <md-content flex layout-padding layout="row" layout-align="center center">\n <span class="input-title">{{field.value}}</span>\n </md-content>\n </div>\n \x3c!-- END label --\x3e\n\n \x3c!-- START textinput --\x3e\n <div ng-switch-when="input">\n <input name="{{field.props.title}}" ng-model="vm.form[field.props.title]" placeholder="{{field.config.placeholder}}" type="text" ng-required="field.config.required">\n </div>\n \x3c!-- END textinput --\x3e\n\n \x3c!-- START textarea --\x3e\n <div ng-switch-when="textarea">\n <textarea name="{{field.props.title}}" ng-model="vm.form[field.props.title]" md-maxlength="150" rows="5"></textarea>\n </div>\n \x3c!-- END textarea --\x3e\n\n \x3c!-- START select --\x3e\n <div ng-switch-when="chooseFromList">\n <md-select md-ink-ripple="false" name="{{field.props.title}}" ng-model="vm.form[field.props.title]" placeholder="{{field.config.placeholder}}" ng-required="field.config.required">\n <md-option ng-repeat="option in ::field.options" ng-value="option.value">{{option.value}}</md-option>\n </md-select>\n </div>\n \x3c!-- END select --\x3e\n\n \x3c!-- START radio --\x3e\n <div ng-switch-when="multipleChoices">\n <md-radio-group md-no-ink name="{{field.props.title}}" ng-model="vm.form[field.props.title]" ng-required="field.config.required" layout="{{field.config.direction === \'vertical\' ? \'row\' : \'column\'}}">\n <md-radio-button ng-repeat="option in ::field.options" ng-value="option.value" class="md-primary">{{option.value}}</md-radio-button>\n </md-radio-group>\n </div>\n \x3c!-- END radio --\x3e\n\n \x3c!-- START checkbox --\x3e\n <div ng-switch-when="checkboxes" layout="{{field.config.direction === \'vertical\' ? \'row\' : \'column\'}}">\n <md-checkbox\n md-no-ink\n aria-label="{{field.props.title}}"\n ng-repeat="option in ::field.options"\n ng-checked="vm.exists(field.props.title, option.value)"\n ng-disabled="!vm.exists(field.props.title, option.value) && field.config.maxSelections === vm.form[field.props.title].length"\n ng-required="vm.getSelected()"\n ng-click="vm.toggle(field.props.title, option.value)">\n {{option.value}}\n </md-checkbox>\n </div>\n \x3c!-- END checkbox --\x3e\n\n \x3c!-- START agreement --\x3e\n <div ng-switch-when="agreement" layout="{{field.config.direction === \'vertical\' ? \'row\' : \'column\'}}">\n <md-checkbox md-no-ink ng-model="vm.form[field.props.title]" aria-label="{{field.props.title}}" ng-required="field.config.required">\n {{field.options[0].value}}\n </md-checkbox>\n </div>\n \x3c!-- END agreement --\x3e\n\n <div ng-messages="vm.userForm[field.props.title].$error" ng-show="vm.userForm[field.props.title].$touched" role="alert">\n <div ng-message="required">\n <span>Required Field</span>\n </div>\n </div>\n </md-input-container>\n </div>\n\n <md-button class="md-raised" ng-click="vm.submit()" ng-disabled="vm.userForm.$invalid || vm.userForm.$pristine || vm.disableItem" ng-style="{\'background-color\': \'{{settings.color_button}}\'}">{{settings.start_chat_button}}</md-button>\n </form>\n\n <md-content layout="row" layout-align="center end">\n <span class="input-title">{{ (settings.custom && !settings.defaultWhiteLabel) ? settings.whiteLabel : \'Powered By XCALLY\' }}</span>\n </md-content>\n</md-content>\n\x3c!-- / CHAT CONTENT --\x3e\n'), e.put("app/unmanaged/index.html", '\x3c!-- CHAT CONTENT --\x3e\n<md-content class="chat-unmanaged">\n \x3c!-- CHAT ERROR --\x3e\n <div class="chat-error" ng-repeat="error in vm.errors" layout="row" layout-margin>\n <i class="mdi mdi-alert mdi-24px mdi-light"></i>\n <md-tooltip md-direction="top">{{error.message || \'Service temporarily unavailable.\'}}</md-tooltip>\n <span class="chat-error-message">{{error.message || \'Service temporarily unavailable.\'}}</span>\n </div>\n \x3c!-- CHAT ERROR --\x3e\n\n <md-content layout="row" layout-margin>\n <span class="input-title">{{ settings.unmanagedMessage }}</span>\n </md-content>\n\n <form name="vm.userForm" layout="column" layout-margin novalidate>\n <span class="input-title">Note</span>\n\n <md-input-container ng-if="settings.enableUnmanagedNote" class="md-block" md-no-float>\n \x3c!-- START textarea --\x3e\n <textarea name="note" ng-model="vm.form.note" md-maxlength="150" rows="3"></textarea>\n \x3c!-- END textarea --\x3e\n </md-input-container>\n\n <div layout="row" layout-align="center center">\n <md-button ng-if="settings.enableUnmanagedNote" ng-click="vm.submit()" class="md-raised" ng-disabled="vm.userForm.$invalid" ng-style="{\'background-color\': \'{{settings.color_button}}\'}">{{settings.sendUnmanaged}}</md-button>\n <md-button class="md-raised" ng-style="{\'background-color\': \'{{settings.color_button}}\'}" ng-click="vm.skip()">{{settings.skipUnmanaged}}</md-button>\n </div>\n </form>\n\n <md-content layout="row" layout-align="center end">\n <span class="input-title">{{ (settings.custom && !settings.defaultWhiteLabel) ? settings.whiteLabel : \'Powered By XCALLY\' }}</span>\n </md-content>\n</md-content>\n\x3c!-- / CHAT CONTENT --\x3e\n'), e.put("app/waiting/index.html", '\x3c!-- WAITING CONTENT --\x3e\n<md-content id="waiting" layout="column" layout-align="center center">\n <div layout="row" layout-align="center center" class="sk-fading-circle" flex="10">\n <div class="sk-circle1 sk-circle"></div>\n <div class="sk-circle2 sk-circle"></div>\n <div class="sk-circle3 sk-circle"></div>\n <div class="sk-circle4 sk-circle"></div>\n <div class="sk-circle5 sk-circle"></div>\n <div class="sk-circle6 sk-circle"></div>\n <div class="sk-circle7 sk-circle"></div>\n <div class="sk-circle8 sk-circle"></div>\n <div class="sk-circle9 sk-circle"></div>\n <div class="sk-circle10 sk-circle"></div>\n <div class="sk-circle11 sk-circle"></div>\n <div class="sk-circle12 sk-circle"></div>\n </div>\n <div layout="row" layout-align="center end" class="title" flex>\n <span class="input-title">{{settings.waitingTitle}}</span>\n </div>\n <div layout="row" layout-align="center start" class="subtitle" flex>\n <span class="input-title">{{settings.waitingMessage}}</span>\n </div>\n</md-content>\n\x3c!-- / WAITING CONTENT --\x3e\n')