mirror of
https://github.com/Mibew/mibew.git
synced 2024-11-15 16:44:11 +03:00
Completely rewrite invitations
This commit is contained in:
parent
a2db90289a
commit
3994b924de
@ -334,14 +334,6 @@
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Compile and concatenate JavaScript files related to invite application -->
|
||||
<target name="invite_app_js" depends="default_app_js" description="Build JavaScript files related to invite application">
|
||||
<antcall target="app_js">
|
||||
<param name="app_name" value="invite" />
|
||||
</antcall>
|
||||
<echo>Invite JavaScript application built.</echo>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- Compile and concatenate JavaScript files related to users application -->
|
||||
<target name="users_app_js" depends="default_app_js" description="Build JavaScript files related to users application">
|
||||
@ -430,7 +422,7 @@
|
||||
|
||||
|
||||
<!-- Build all project -->
|
||||
<target name="all" depends="chat_app_js,invite_app_js,thread_log_app_js,users_app_js,styles_all" description="Build everything">
|
||||
<target name="all" depends="chat_app_js,thread_log_app_js,users_app_js,styles_all" description="Build everything">
|
||||
<echo>Mibew Messenger built.</echo>
|
||||
</target>
|
||||
|
||||
|
@ -47,6 +47,24 @@ if (get_remote_level($_SERVER['HTTP_USER_AGENT']) == 'old') {
|
||||
exit;
|
||||
}
|
||||
|
||||
if (verifyparam("act", "/^(invitation)$/", "default") == 'invitation') {
|
||||
// Check if user invited to chat
|
||||
$invitation_state = invitation_state($_SESSION['visitorid']);
|
||||
|
||||
if ($invitation_state['invited'] && $invitation_state['threadid']) {
|
||||
$thread = Thread::load($invitation_state['threadid']);
|
||||
|
||||
// Prepare page
|
||||
$page = setup_invitation_view($thread);
|
||||
|
||||
// Build js application options
|
||||
$page['invitationOptions'] = json_encode($page['invitation']);
|
||||
// Expand page
|
||||
expand("styles/dialogs", getchatstyle(), "chat.tpl");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if( !isset($_GET['token']) || !isset($_GET['thread']) ) {
|
||||
|
||||
$thread = NULL;
|
||||
@ -107,8 +125,7 @@ if( !isset($_GET['token']) || !isset($_GET['thread']) ) {
|
||||
// Get invitation info
|
||||
if (Settings::get('enabletracking')) {
|
||||
$invitation_state = invitation_state($_SESSION['visitorid']);
|
||||
$visitor_is_invited = $invitation_state['invited']
|
||||
&& !$invitation_state['threadid'];
|
||||
$visitor_is_invited = $invitation_state['invited'];
|
||||
} else {
|
||||
$visitor_is_invited = false;
|
||||
}
|
||||
|
@ -986,17 +986,3 @@ table.awaiting .no-threads, table.awaiting .no-visitors {
|
||||
float:left;
|
||||
padding-left:10px;
|
||||
}
|
||||
|
||||
/* invitation wait */
|
||||
|
||||
.ajaxWait {
|
||||
z-index: -1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(images/ajax-loader.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 6.7 KiB |
@ -42,6 +42,7 @@ $dbtables = array(
|
||||
"dtmmodified" => "int NOT NULL DEFAULT 0",
|
||||
"lrevision" => "int NOT NULL DEFAULT 0",
|
||||
"istate" => "int NOT NULL DEFAULT 0",
|
||||
"invitationstate" => "int NOT NULL DEFAULT 0",
|
||||
"ltoken" => "int NOT NULL",
|
||||
"remote" => "varchar(255)",
|
||||
"referer" => "text",
|
||||
@ -167,15 +168,12 @@ $dbtables = array(
|
||||
|
||||
"${mysqlprefix}chatsitevisitor" => array(
|
||||
"visitorid" => "INT NOT NULL auto_increment PRIMARY KEY",
|
||||
"userid" => "varchar(64) NOT NULL",
|
||||
"username" => "varchar(255)",
|
||||
"userid" => "varchar(255) NOT NULL",
|
||||
"username" => "varchar(64)",
|
||||
"firsttime" => "int NOT NULL DEFAULT 0",
|
||||
"lasttime" => "int NOT NULL DEFAULT 0",
|
||||
"entry" => "text NOT NULL",
|
||||
"details" => "text NOT NULL",
|
||||
"invited" => "tinyint(1) NOT NULL DEFAULT 0",
|
||||
"invitationtime" => "int NOT NULL DEFAULT 0",
|
||||
"invitedby" => "INT references ${mysqlprefix}chatoperator(operatorid) on delete set null",
|
||||
"invitations" => "INT NOT NULL DEFAULT 0",
|
||||
"chats" => "INT NOT NULL DEFAULT 0",
|
||||
"threadid" => "INT references ${mysqlprefix}chatthread(threadid) on delete set null"
|
||||
@ -233,7 +231,7 @@ $dbtables_indexes = array(
|
||||
$memtables = array();
|
||||
|
||||
$dbtables_can_update = array(
|
||||
"${mysqlprefix}chatthread" => array("agentId", "userTyping", "agentTyping", "messageCount", "nextagent", "shownmessageid", "userid", "userAgent", "groupid", "dtmchatstarted"),
|
||||
"${mysqlprefix}chatthread" => array("agentId", "userTyping", "agentTyping", "messageCount", "nextagent", "shownmessageid", "userid", "userAgent", "groupid", "dtmchatstarted", "invitationstate"),
|
||||
"${mysqlprefix}chatthreadstatistics" => array(),
|
||||
"${mysqlprefix}requestbuffer" => array("requestid", "requestkey", "request"),
|
||||
"${mysqlprefix}chatmessage" => array("agentId"),
|
||||
|
@ -128,6 +128,10 @@ if ($act == "silentcreateall") {
|
||||
runsql("ALTER TABLE ${mysqlprefix}chatthread ADD userid varchar(255) DEFAULT \"\"", $link);
|
||||
}
|
||||
|
||||
if (in_array("${mysqlprefix}chatthread.invitationstate", $absent_columns)) {
|
||||
runsql("ALTER TABLE ${mysqlprefix}chatthread ADD invitationstate int NOT NULL DEFAULT 0 AFTER istate", $link);
|
||||
}
|
||||
|
||||
if (in_array("${mysqlprefix}chatoperator.iperm", $absent_columns)) {
|
||||
runsql("ALTER TABLE ${mysqlprefix}chatoperator ADD iperm int DEFAULT 65535", $link);
|
||||
}
|
||||
|
@ -5,5 +5,5 @@
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a,d){var c=a.Application;c.addRegions({mainRegion:"#main-region"});c.addInitializer(function(b){a.PluginOptions=b.plugins||{};a.Objects.server=new a.Server(d.extend({interactionType:MibewAPIChatInteraction},b.server));a.Objects.Models.page=new a.Models.Page(b.page);switch(b.startFrom){case "chat":c.Chat.start(b.chatOptions);break;case "survey":c.Survey.start(b.surveyOptions);break;case "leaveMessage":c.LeaveMessage.start(b.leaveMessageOptions);break;default:throw Error("Dont know how to start!");
|
||||
}});c.on("start",function(){a.Objects.server.runUpdater()})})(Mibew,_);
|
||||
(function(b,d){var c=b.Application;c.addRegions({mainRegion:"#main-region"});c.addInitializer(function(a){b.PluginOptions=a.plugins||{};b.Objects.server=new b.Server(d.extend({interactionType:MibewAPIChatInteraction},a.server));b.Objects.Models.page=new b.Models.Page(a.page);switch(a.startFrom){case "chat":c.Chat.start(a.chatOptions);break;case "survey":c.Survey.start(a.surveyOptions);break;case "leaveMessage":c.LeaveMessage.start(a.leaveMessageOptions);break;case "invitation":c.Invitation.start(a.invitationOptions);
|
||||
break;default:throw Error("Dont know how to start!");}});c.on("start",function(){b.Objects.server.runUpdater()})})(Mibew,_);
|
||||
|
@ -0,0 +1,8 @@
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a,b){a.Layouts.Invitation=b.Marionette.Layout.extend({template:Handlebars.templates.invitation_layout,regions:{messagesRegion:{selector:"#invitation-messages-region",regionType:a.Regions.Messages}}})})(Mibew,Backbone);
|
10
src/messenger/webim/js/compiled/chat/modules/invitation.js
Normal file
10
src/messenger/webim/js/compiled/chat/modules/invitation.js
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a){var d=[],e=a.Application,b=e.module("Invitation",{startWithParent:!1});b.addInitializer(function(f){var c=a.Objects,b=a.Objects.Models;b.thread=new a.Models.Thread(f.thread);b.user=new a.Models.ChatUser(f.user);c.invitationLayout=new a.Layouts.Invitation;e.mainRegion.show(c.invitationLayout);c.Collections.messages=new a.Collections.Messages;c.invitationLayout.messagesRegion.show(new a.Views.MessagesCollection({collection:c.Collections.messages}));d.push(c.server.callFunctionsPeriodically(function(){var b=
|
||||
a.Objects.Models.thread;return[{"function":"update",arguments:{"return":{},references:{},threadId:b.get("id"),token:b.get("token"),lastId:b.get("lastId"),typed:!1,user:!0}}]},function(){}))});b.on("start",function(){a.Objects.server.restartUpdater()});b.addFinalizer(function(){a.Objects.invitationLayout.close();for(var b=0;b<d.length;b++)a.Objects.server.stopCallFunctionsPeriodically(d[b]);a.Objects.Collections.messages.finalize();delete a.Objects.invitationLayout;delete a.Objects.Models.thread;delete a.Objects.Models.user;
|
||||
delete a.Objects.Collections.messages})})(Mibew);
|
@ -341,6 +341,13 @@ disableInput:function(){this.ui.message.attr("disabled","disabled")},clearInput:
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a,b){a.Layouts.Invitation=b.Marionette.Layout.extend({template:Handlebars.templates.invitation_layout,regions:{messagesRegion:{selector:"#invitation-messages-region",regionType:a.Regions.Messages}}})})(Mibew,Backbone);
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a,b){a.Layouts.LeaveMessage=b.Marionette.Layout.extend({template:Handlebars.templates.leave_message_layout,regions:{leaveMessageFormRegion:"#content-wrapper",descriptionRegion:"#description-region"},serializeData:function(){return{page:a.Objects.Models.page.toJSON()}}})})(Mibew,Backbone);
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
@ -368,6 +375,15 @@ delete a.Objects.Collections.messages;delete a.Objects.Collections.controls;dele
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a){var d=[],e=a.Application,b=e.module("Invitation",{startWithParent:!1});b.addInitializer(function(f){var c=a.Objects,b=a.Objects.Models;b.thread=new a.Models.Thread(f.thread);b.user=new a.Models.ChatUser(f.user);c.invitationLayout=new a.Layouts.Invitation;e.mainRegion.show(c.invitationLayout);c.Collections.messages=new a.Collections.Messages;c.invitationLayout.messagesRegion.show(new a.Views.MessagesCollection({collection:c.Collections.messages}));d.push(c.server.callFunctionsPeriodically(function(){var b=
|
||||
a.Objects.Models.thread;return[{"function":"update",arguments:{"return":{},references:{},threadId:b.get("id"),token:b.get("token"),lastId:b.get("lastId"),typed:!1,user:!0}}]},function(){}))});b.on("start",function(){a.Objects.server.restartUpdater()});b.addFinalizer(function(){a.Objects.invitationLayout.close();for(var b=0;b<d.length;b++)a.Objects.server.stopCallFunctionsPeriodically(d[b]);a.Objects.Collections.messages.finalize();delete a.Objects.invitationLayout;delete a.Objects.Models.thread;delete a.Objects.Models.user;
|
||||
delete a.Objects.Collections.messages})})(Mibew);
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a){var e=a.Application,f=e.module("LeaveMessage",{startWithParent:!1});f.addInitializer(function(d){var b=a.Objects,c=a.Objects.Models;d.page&&c.page.set(d.page);b.leaveMessageLayout=new a.Layouts.LeaveMessage;e.mainRegion.show(b.leaveMessageLayout);c.leaveMessageForm=new a.Models.LeaveMessageForm(d.leaveMessageForm);b.leaveMessageLayout.leaveMessageFormRegion.show(new a.Views.LeaveMessageForm({model:c.leaveMessageForm}));b.leaveMessageLayout.descriptionRegion.show(new a.Views.LeaveMessageDescription);
|
||||
c.leaveMessageForm.on("submit:complete",function(){b.leaveMessageLayout.leaveMessageFormRegion.close();b.leaveMessageLayout.descriptionRegion.close();b.leaveMessageLayout.descriptionRegion.show(new a.Views.LeaveMessageSentDescription)})});f.addFinalizer(function(){a.Objects.leaveMessageLayout.close();delete a.Objects.Models.leaveMessageForm})})(Mibew);
|
||||
/*
|
||||
@ -383,5 +399,5 @@ c.leaveMessageForm.on("submit:complete",function(){b.leaveMessageLayout.leaveMes
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a,d){var c=a.Application;c.addRegions({mainRegion:"#main-region"});c.addInitializer(function(b){a.PluginOptions=b.plugins||{};a.Objects.server=new a.Server(d.extend({interactionType:MibewAPIChatInteraction},b.server));a.Objects.Models.page=new a.Models.Page(b.page);switch(b.startFrom){case "chat":c.Chat.start(b.chatOptions);break;case "survey":c.Survey.start(b.surveyOptions);break;case "leaveMessage":c.LeaveMessage.start(b.leaveMessageOptions);break;default:throw Error("Dont know how to start!");
|
||||
}});c.on("start",function(){a.Objects.server.runUpdater()})})(Mibew,_);
|
||||
(function(b,d){var c=b.Application;c.addRegions({mainRegion:"#main-region"});c.addInitializer(function(a){b.PluginOptions=a.plugins||{};b.Objects.server=new b.Server(d.extend({interactionType:MibewAPIChatInteraction},a.server));b.Objects.Models.page=new b.Models.Page(a.page);switch(a.startFrom){case "chat":c.Chat.start(a.chatOptions);break;case "survey":c.Survey.start(a.surveyOptions);break;case "leaveMessage":c.LeaveMessage.start(a.leaveMessageOptions);break;case "invitation":c.Invitation.start(a.invitationOptions);
|
||||
break;default:throw Error("Dont know how to start!");}});c.on("start",function(){b.Objects.server.runUpdater()})})(Mibew,_);
|
||||
|
@ -5,4 +5,4 @@
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a){a.Models.Thread=a.Models.Base.extend({defaults:{id:0,token:0,lastId:0,state:null},STATE_QUEUE:0,STATE_WAITING:1,STATE_CHATTING:2,STATE_CLOSED:3,STATE_LOADING:4,STATE_LEFT:5})})(Mibew);
|
||||
(function(a){a.Models.Thread=a.Models.Base.extend({defaults:{id:0,token:0,lastId:0,state:null},STATE_QUEUE:0,STATE_WAITING:1,STATE_CHATTING:2,STATE_CLOSED:3,STATE_LOADING:4,STATE_LEFT:5,STATE_INVITED:6})})(Mibew);
|
||||
|
@ -87,7 +87,7 @@ b.Utils.playSound=function(a){c("body").append('<audio autoplay style="display:
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(a){a.Models.Thread=a.Models.Base.extend({defaults:{id:0,token:0,lastId:0,state:null},STATE_QUEUE:0,STATE_WAITING:1,STATE_CHATTING:2,STATE_CLOSED:3,STATE_LOADING:4,STATE_LEFT:5})})(Mibew);
|
||||
(function(a){a.Models.Thread=a.Models.Base.extend({defaults:{id:0,token:0,lastId:0,state:null},STATE_QUEUE:0,STATE_WAITING:1,STATE_CHATTING:2,STATE_CLOSED:3,STATE_LOADING:4,STATE_LEFT:5,STATE_INVITED:6})})(Mibew);
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
|
@ -1,9 +0,0 @@
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(c,a,e){a=new a.Marionette.Application;a.addInitializer(function(a){var d=new c.Server(e.extend({interactionType:MibewAPIInviteInteraction},a.server));d.callFunctionsPeriodically(function(){return[{"function":"invitationState",arguments:{"return":{invited:"invited",threadId:"threadId"},references:{},visitorId:a.visitorId}}]},function(b){0==b.errorCode&&(b.invited||window.close(),b.threadId&&(window.name="ImCenter"+b.threadId,window.location=a.chatLink+"?thread="+b.threadId))});d.runUpdater();
|
||||
c.Objects.server=d});c.Application=a})(Mibew,Backbone,_);
|
@ -1,8 +0,0 @@
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
MibewAPIInviteInteraction=function(){this.obligatoryArguments={"*":{"return":{},references:{},visitorId:null},result:{errorCode:0}};this.reservedFunctionNames=["result"]};MibewAPIInviteInteraction.prototype=new MibewAPIInteraction;
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
MibewAPIInviteInteraction=function(){this.obligatoryArguments={"*":{"return":{},references:{},visitorId:null},result:{errorCode:0}};this.reservedFunctionNames=["result"]};MibewAPIInviteInteraction.prototype=new MibewAPIInteraction;
|
||||
/*
|
||||
Copyright 2005-2013 the original author or authors.
|
||||
Licensed under the Apache License, Version 2.0 (the "License").
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
(function(c,a,e){a=new a.Marionette.Application;a.addInitializer(function(a){var d=new c.Server(e.extend({interactionType:MibewAPIInviteInteraction},a.server));d.callFunctionsPeriodically(function(){return[{"function":"invitationState",arguments:{"return":{invited:"invited",threadId:"threadId"},references:{},visitorId:a.visitorId}}]},function(b){0==b.errorCode&&(b.invited||window.close(),b.threadId&&(window.name="ImCenter"+b.threadId,window.location=a.chatLink+"?thread="+b.threadId))});d.runUpdater();
|
||||
c.Objects.server=d});c.Application=a})(Mibew,Backbone,_);
|
@ -12,6 +12,6 @@ return b.join("&")};a.Widget.prototype.sendToServer=function(b){for(var c in b)i
|
||||
this.loadScript(f));for(var h in b)b.hasOwnProperty(h)&&(h in this.handlersDependences||(this.handlersDependences[h]=b[h]));for(c=0;c<d.length;c++){var g=d[c];if(this.canRunHandler(g))a.APIFunctions[g](e);else g in this.handlers||(this.handlers[g]=function(){a.APIFunctions[g](e)})}this.cleanUpAfterRequest();window.setTimeout(function(){j.makeRequest()},this.requestTimeout)};a.Widget.prototype.cleanUpAfterRequest=function(){document.getElementsByTagName("head")[0].removeChild(document.getElementById("responseScript"))};
|
||||
a.Widget.prototype.loadScript=function(b){var c=this,a=this.doLoadScript(this.requestedScripts[b].url,b);a.onload=function(){c.scriptReady(b)};a.onreadystatechange=function(){("complete"==this.readyState||"loaded"==this.readyState)&&c.scriptReady(b)}};a.Widget.prototype.doLoadScript=function(b,c){var a=document.createElement("script");a.setAttribute("type","text/javascript");a.setAttribute("src",b);a.setAttribute("id",c);document.getElementsByTagName("head")[0].appendChild(a);return a};a.Widget.prototype.scriptReady=
|
||||
function(b){this.requestedScripts[b].status="ready";for(var a in this.handlers)this.handlers.hasOwnProperty(a)&&this.canRunHandler(a)&&(this.handlers[a](),delete this.handlers[a])};a.Widget.prototype.canRunHandler=function(b){b=this.handlersDependences[b];for(var a=0;a<b.length;a++)if("ready"!=this.requestedScripts[b[a]].status)return!1;return!0};a.Widget.init=function(b){a.Objects.widget=new a.Widget(b);a.Objects.widget.makeRequest()};a.Utils={};a.Utils.createCookie=function(b,a){var d=/([^\.]+\.[^\.]+)$/.exec(document.location.hostname)[1];
|
||||
document.cookie=""+b+"="+a+"; path=/; "+(d?"domain="+d+";":"")};a.Utils.readCookie=function(b){var a=document.cookie.split("; ");b+="=";for(var d=!1,e=0;e<a.length;e++)if(-1!=a[e].indexOf(b)){d=a[e].substr(b.length);break}return d};a.APIFunctions={};a.APIFunctions.updateUserId=function(b){a.Utils.createCookie(a.Objects.widget.visitorCookieName,b.user.id)};a.APIFunctions.inviteOnResponse=function(b){var a=b.invitation.message,d=b.invitation.operator,e=b.invitation.avatar;b='<div id="mibewinvitationpopup"><div id="mibewinvitationclose"><a href="javascript:void(0);" onclick="Mibew.Invitation.reject();">×</a></div>';
|
||||
d&&(b+='<h1 onclick="Mibew.Invitation.accept();">'+d+"</h1>");e&&(b+='<img id="mibewinvitationavatar" src="'+e+'" title="'+d+'" alt="'+d+'" onclick="Mibew.Invitation.accept();" />');b=b+('<p onclick="Mibew.Invitation.accept();">'+a+"</p>")+'<div style="clear: both;"></div></div>';if(a=document.getElementById("mibewinvitation"))a.innerHTML=b};a.Invitation={};a.Invitation.hide=function(){var a=document.getElementById("mibewinvitationpopup");a&&(a.style.display="none")};a.Invitation.accept=function(){document.getElementById("mibewAgentButton")&&
|
||||
(document.getElementById("mibewAgentButton").onclick(),a.Invitation.hide())};a.Invitation.reject=function(){a.Objects.widget.sendToServer({invitation_rejected:1});a.Invitation.hide()}})(Mibew);
|
||||
document.cookie=""+b+"="+a+"; path=/; "+(d?"domain="+d+";":"")};a.Utils.readCookie=function(b){var a=document.cookie.split("; ");b+="=";for(var d=!1,e=0;e<a.length;e++)if(-1!=a[e].indexOf(b)){d=a[e].substr(b.length);break}return d};a.APIFunctions={};a.APIFunctions.updateUserId=function(b){a.Utils.createCookie(a.Objects.widget.visitorCookieName,b.user.id)};a.APIFunctions.inviteOnResponse=function(b){var a=b.invitation.operator,d=b.invitation.avatar,e=b.invitation.url;b='<div id="mibewinvitationpopup" style="display: none;"><div id="mibewinvitationclose"><a href="javascript:void(0);" onclick="Mibew.Invitation.reject();">×</a></div>';
|
||||
a&&(b+='<h1 onclick="Mibew.Invitation.accept();">'+a+"</h1>");d&&(b+='<img id="mibewinvitationavatar" src="'+d+'" title="'+a+'" alt="'+a+'" onclick="Mibew.Invitation.accept();" />');e&&(b+='<iframe id="mibewinvitationframe" src="'+e+'" onload="Mibew.Invitation.show();"></iframe>');b+='<div style="clear: both;"></div></div>';if(a=document.getElementById("mibewinvitation"))a.innerHTML=b};a.Invitation={};a.Invitation.hide=function(){var a=document.getElementById("mibewinvitationpopup");a&&a.parentNode.removeChild(a)};
|
||||
a.Invitation.show=function(){var a=document.getElementById("mibewinvitationpopup");a&&(a.style.display="block")};a.Invitation.accept=function(){document.getElementById("mibewAgentButton")&&(document.getElementById("mibewAgentButton").onclick(),a.Invitation.hide())};a.Invitation.reject=function(){a.Objects.widget.sendToServer({invitation_rejected:1});a.Invitation.hide()}})(Mibew);
|
||||
|
@ -40,6 +40,9 @@
|
||||
case 'leaveMessage':
|
||||
app.LeaveMessage.start(options.leaveMessageOptions);
|
||||
break;
|
||||
case 'invitation':
|
||||
app.Invitation.start(options.invitationOptions);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Dont know how to start!');
|
||||
break;
|
||||
|
36
src/messenger/webim/js/source/chat/layouts/invitation.js
Normal file
36
src/messenger/webim/js/source/chat/layouts/invitation.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @preserve Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
(function(Mibew, Backbone){
|
||||
|
||||
/**
|
||||
* Represents invitation layout
|
||||
*/
|
||||
Mibew.Layouts.Invitation = Backbone.Marionette.Layout.extend(
|
||||
/** @lends Mibew.Layouts.Invitation.prototype */
|
||||
{
|
||||
/**
|
||||
* Template function
|
||||
* @type Function
|
||||
*/
|
||||
template: Handlebars.templates.invitation_layout,
|
||||
|
||||
/**
|
||||
* Regions list
|
||||
* @type Object
|
||||
*/
|
||||
regions: {
|
||||
messagesRegion: {
|
||||
selector: '#invitation-messages-region',
|
||||
regionType: Mibew.Regions.Messages
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
})(Mibew, Backbone);
|
114
src/messenger/webim/js/source/chat/modules/invitation.js
Normal file
114
src/messenger/webim/js/source/chat/modules/invitation.js
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @preserve Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
(function(Mibew){
|
||||
|
||||
/**
|
||||
* Contains ids of periodically called functions
|
||||
* @type Array
|
||||
*/
|
||||
var periodicallyCalled = [];
|
||||
|
||||
|
||||
// Create shortcut for Application object
|
||||
var app = Mibew.Application;
|
||||
|
||||
// Create Invite module
|
||||
var invitation = app.module('Invitation', {startWithParent: false});
|
||||
|
||||
// Add module initializer
|
||||
invitation.addInitializer(function(options) {
|
||||
// Create some shortcuts
|
||||
var objs = Mibew.Objects;
|
||||
var models = Mibew.Objects.Models;
|
||||
|
||||
// Initialize Thread and User
|
||||
models.thread = new Mibew.Models.Thread(options.thread);
|
||||
models.user = new Mibew.Models.ChatUser(options.user);
|
||||
|
||||
// Create instance of the Invitation layout
|
||||
objs.invitationLayout = new Mibew.Layouts.Invitation();
|
||||
|
||||
// Show layout at page
|
||||
app.mainRegion.show(objs.invitationLayout);
|
||||
|
||||
// Initialize Messages area
|
||||
// Create messages collection and store it
|
||||
objs.Collections.messages = new Mibew.Collections.Messages();
|
||||
|
||||
// Display messages
|
||||
objs.invitationLayout.messagesRegion.show(new Mibew.Views.MessagesCollection({
|
||||
collection: objs.Collections.messages
|
||||
}));
|
||||
|
||||
|
||||
// Periodically call update function at the server side
|
||||
periodicallyCalled.push(
|
||||
objs.server.callFunctionsPeriodically(
|
||||
function() {
|
||||
// Get thread object
|
||||
var thread = Mibew.Objects.Models.thread;
|
||||
|
||||
// Build functions list
|
||||
return [
|
||||
{
|
||||
"function": "update",
|
||||
"arguments": {
|
||||
"return": {},
|
||||
"references": {},
|
||||
"threadId": thread.get('id'),
|
||||
"token": thread.get('token'),
|
||||
"lastId": thread.get('lastId'),
|
||||
"typed": false,
|
||||
"user": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
function() {}
|
||||
)
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
invitation.on('start', function() {
|
||||
// Restart server updater because module just started and there are no
|
||||
// reasons to wait refresh time to get results of previous request
|
||||
Mibew.Objects.server.restartUpdater();
|
||||
})
|
||||
|
||||
// Add module finalizer
|
||||
invitation.addFinalizer(function() {
|
||||
// Close layout
|
||||
Mibew.Objects.invitationLayout.close();
|
||||
|
||||
|
||||
// Stop call functions periodically
|
||||
for (var i = 0; i < periodicallyCalled.length; i++) {
|
||||
Mibew.Objects.server.stopCallFunctionsPeriodically(
|
||||
periodicallyCalled[i]
|
||||
);
|
||||
}
|
||||
|
||||
// Run collections finalizers
|
||||
// Finalize messages collection
|
||||
Mibew.Objects.Collections.messages.finalize();
|
||||
|
||||
// Clean up memory
|
||||
// Delete layout
|
||||
delete Mibew.Objects.invitationLayout;
|
||||
|
||||
// Delete models
|
||||
delete Mibew.Objects.Models.thread;
|
||||
delete Mibew.Objects.Models.user;
|
||||
|
||||
// Delete collections
|
||||
delete Mibew.Objects.Collections.messages;
|
||||
});
|
||||
|
||||
})(Mibew);
|
@ -70,7 +70,11 @@
|
||||
/**
|
||||
* User left message without starting a conversation
|
||||
*/
|
||||
STATE_LEFT: 5
|
||||
STATE_LEFT: 5,
|
||||
/**
|
||||
* Visitor was invited to chat by operator
|
||||
*/
|
||||
STATE_INVITED: 6
|
||||
|
||||
/** End of thread state constants */
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
/**
|
||||
* @preserve Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
(function(Mibew, Backbone, _){
|
||||
|
||||
// Create application instance
|
||||
var App = new Backbone.Marionette.Application();
|
||||
|
||||
// Initialize application
|
||||
App.addInitializer(function(options){
|
||||
|
||||
// Initialize Server
|
||||
var server = new Mibew.Server(_.extend(
|
||||
{
|
||||
'interactionType': MibewAPIInviteInteraction
|
||||
},
|
||||
options.server
|
||||
));
|
||||
|
||||
// Periodically call update function at the server side
|
||||
server.callFunctionsPeriodically(
|
||||
function() {
|
||||
// Build functions list
|
||||
return [
|
||||
{
|
||||
"function": "invitationState",
|
||||
"arguments": {
|
||||
"return": {
|
||||
'invited': 'invited',
|
||||
'threadId': 'threadId'
|
||||
},
|
||||
"references": {},
|
||||
"visitorId": options.visitorId
|
||||
}
|
||||
}
|
||||
];
|
||||
},
|
||||
function(args) {
|
||||
if (args.errorCode == 0) {
|
||||
if (!args.invited) {
|
||||
// Visitor not invited any more.
|
||||
// Invitation vindow should be closed.
|
||||
window.close();
|
||||
}
|
||||
if (args.threadId) {
|
||||
// Invitation accepted.
|
||||
// Redirect agent to chat page
|
||||
window.name = 'ImCenter' + args.threadId;
|
||||
window.location= options.chatLink
|
||||
+ '?thread=' + args.threadId;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
server.runUpdater();
|
||||
Mibew.Objects.server = server;
|
||||
});
|
||||
|
||||
Mibew.Application = App;
|
||||
|
||||
})(Mibew, Backbone, _);
|
@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @preserve Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License").
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents Invitation waiting Window to core interaction type
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
MibewAPIInviteInteraction = function() {
|
||||
this.obligatoryArguments = {
|
||||
'*': {
|
||||
'return': {},
|
||||
'references': {},
|
||||
'visitorId': null
|
||||
},
|
||||
'result': {
|
||||
'errorCode': 0
|
||||
}
|
||||
};
|
||||
|
||||
this.reservedFunctionNames = [
|
||||
'result'
|
||||
];
|
||||
}
|
||||
MibewAPIInviteInteraction.prototype = new MibewAPIInteraction();
|
@ -380,28 +380,36 @@ var Mibew = {};
|
||||
* @param {Object} response Data passed from server
|
||||
*/
|
||||
Mibew.APIFunctions.inviteOnResponse = function(response) {
|
||||
var message = response.invitation.message;
|
||||
var operator = response.invitation.operator;
|
||||
var avatar = response.invitation.avatar;
|
||||
var url = response.invitation.url;
|
||||
|
||||
var popuptext = '<div id="mibewinvitationpopup">';
|
||||
var popuptext = '<div id="mibewinvitationpopup" style="display: none;">';
|
||||
popuptext += '<div id="mibewinvitationclose">'
|
||||
+ '<a href="javascript:void(0);" onclick="Mibew.Invitation.reject();">'
|
||||
+ '×</a></div>';
|
||||
|
||||
// Add operator name
|
||||
if (operator) {
|
||||
popuptext += '<h1 onclick="Mibew.Invitation.accept();">'
|
||||
+ operator
|
||||
+ '</h1>';
|
||||
}
|
||||
|
||||
// Add operator avatar
|
||||
if (avatar) {
|
||||
popuptext += '<img id="mibewinvitationavatar" src="' + avatar
|
||||
+ '" title="' + operator
|
||||
+ '" alt="' + operator
|
||||
+ '" onclick="Mibew.Invitation.accept();" />';
|
||||
}
|
||||
popuptext += '<p onclick="Mibew.Invitation.accept();">'
|
||||
+ message
|
||||
+ '</p>';
|
||||
|
||||
// Translate message from the thread related with invitation into iframe
|
||||
if (url) {
|
||||
popuptext += '<iframe id="mibewinvitationframe" src="' + url
|
||||
+ '" onload="Mibew.Invitation.show();"></iframe>';
|
||||
}
|
||||
|
||||
popuptext += '<div style="clear: both;"></div></div>';
|
||||
|
||||
var invitationdiv = document.getElementById("mibewinvitation");
|
||||
@ -416,12 +424,22 @@ var Mibew = {};
|
||||
Mibew.Invitation = {};
|
||||
|
||||
/**
|
||||
* Hide invitation popup
|
||||
* Hide invitation popup and remove it from DOM
|
||||
*/
|
||||
Mibew.Invitation.hide = function() {
|
||||
var invitationPopup = document.getElementById('mibewinvitationpopup');
|
||||
if (invitationPopup) {
|
||||
invitationPopup.style.display = 'none';
|
||||
invitationPopup.parentNode.removeChild(invitationPopup);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display invitation popup
|
||||
*/
|
||||
Mibew.Invitation.show = function() {
|
||||
var invitationPopup = document.getElementById('mibewinvitationpopup');
|
||||
if (invitationPopup) {
|
||||
invitationPopup.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,8 +642,30 @@ function chat_start_for_user($group_id, $visitor_id, $visitor_name, $referrer, $
|
||||
die("number of connections from your IP is exceeded, try again later");
|
||||
}
|
||||
|
||||
// Create thread
|
||||
$thread = Thread::create();
|
||||
// Check if visitor was invited to chat
|
||||
$is_invited = false;
|
||||
if (Settings::get('enabletracking')) {
|
||||
$invitation_state = invitation_state($_SESSION['visitorid']);
|
||||
if ($invitation_state['invited']) {
|
||||
$is_invited = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get thread object
|
||||
if ($is_invited) {
|
||||
// Get thread from invitation
|
||||
$thread = invitation_accept($_SESSION['visitorid']);
|
||||
if (! $thread) {
|
||||
die("Cannot start thread");
|
||||
}
|
||||
$thread->state = Thread::STATE_CHATTING;
|
||||
} else {
|
||||
// Create thread
|
||||
$thread = Thread::create();
|
||||
$thread->state = Thread::STATE_LOADING;
|
||||
}
|
||||
|
||||
// Update thread fields
|
||||
$thread->groupId = $group_id;
|
||||
$thread->userName = $visitor_name;
|
||||
$thread->remote = $remote_host;
|
||||
@ -651,36 +673,31 @@ function chat_start_for_user($group_id, $visitor_id, $visitor_name, $referrer, $
|
||||
$thread->locale = $current_locale;
|
||||
$thread->userId = $visitor_id;
|
||||
$thread->userAgent = $user_browser;
|
||||
$thread->state = Thread::STATE_LOADING;
|
||||
$thread->save();
|
||||
|
||||
$_SESSION['threadid'] = $thread->id;
|
||||
|
||||
// Check if invitation accept
|
||||
if (Settings::get('enabletracking')) {
|
||||
$operator = invitation_accept($_SESSION['visitorid'], $thread->id);
|
||||
if ($operator) {
|
||||
$operator = operator_by_id($operator);
|
||||
$operator_name = get_operator_name($operator);
|
||||
$thread->postMessage(
|
||||
Thread::KIND_FOR_AGENT,
|
||||
getstring2(
|
||||
'chat.visitor.invitation.accepted',
|
||||
array($operator_name)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Send some messages
|
||||
if ($referrer) {
|
||||
// Send several messages
|
||||
if ($is_invited) {
|
||||
$operator = operator_by_id($thread->agentId);
|
||||
$operator_name = get_operator_name($operator);
|
||||
$thread->postMessage(
|
||||
Thread::KIND_FOR_AGENT,
|
||||
getstring2('chat.came.from',array($referrer))
|
||||
getstring2(
|
||||
'chat.visitor.invitation.accepted',
|
||||
array($operator_name)
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if ($referrer) {
|
||||
$thread->postMessage(
|
||||
Thread::KIND_FOR_AGENT,
|
||||
getstring2('chat.came.from',array($referrer))
|
||||
);
|
||||
}
|
||||
|
||||
$thread->postMessage(Thread::KIND_INFO, getstring('chat.wait'));
|
||||
$thread->postMessage(Thread::KIND_INFO, getstring('chat.wait'));
|
||||
}
|
||||
|
||||
// TODO: May be move sending this message somewhere else?
|
||||
if ($info) {
|
||||
|
@ -61,6 +61,31 @@ Class Thread {
|
||||
* User left message without starting a conversation
|
||||
*/
|
||||
const STATE_LEFT = 5;
|
||||
/**
|
||||
* Visitor was invited to chat by operator
|
||||
*/
|
||||
const STATE_INVITED = 6;
|
||||
|
||||
/**
|
||||
* Visitor was not invited to chat
|
||||
*/
|
||||
const INVITATION_NOT_INVITED = 0;
|
||||
/**
|
||||
* Operator invited visitor and wait for reaction.
|
||||
*/
|
||||
const INVITATION_WAIT = 1;
|
||||
/**
|
||||
* Invitation was accepted by visitor
|
||||
*/
|
||||
const INVITATION_ACCEPTED = 2;
|
||||
/**
|
||||
* Invitation was rejected by visitor
|
||||
*/
|
||||
const INVITATION_REJECTED = 3;
|
||||
/**
|
||||
* Invitation was ignored by visitor. Invitation was automatically closed.
|
||||
*/
|
||||
const INVITATION_IGNORED = 4;
|
||||
|
||||
/**
|
||||
* Message sent by user
|
||||
@ -106,6 +131,8 @@ Class Thread {
|
||||
* - 'id': id of the thread
|
||||
* - 'lastRevision': last revision number
|
||||
* - 'state': state of the thread. See Thread::STATE_*
|
||||
* - 'invitationState': state of invitation. See INVITATION_* constants,
|
||||
* defined in libs/invitation.php
|
||||
* - 'lastToken': last chat token
|
||||
* - 'nextAgent': id of the next agent(agent that change current agent in the chat)
|
||||
* - 'groupId': id of the group related to the thread
|
||||
@ -138,6 +165,7 @@ Class Thread {
|
||||
|
||||
'lastRevision' => 'lrevision',
|
||||
'state' => 'istate',
|
||||
'invitationState' => 'invitationstate',
|
||||
'lastToken' => 'ltoken',
|
||||
|
||||
'nextAgent' => 'nextagent',
|
||||
|
@ -183,6 +183,7 @@ class UsersProcessor extends ClientSideProcessor {
|
||||
" from {chatthread} t left outer join {chatgroup} g on " .
|
||||
" t.groupid = g.groupid " .
|
||||
" where t.lrevision > :since " .
|
||||
" AND t.istate <> " . Thread::STATE_INVITED .
|
||||
($since == 0
|
||||
// Select only active threads at first time when lrevision = 0
|
||||
? " AND t.istate <> " . Thread::STATE_CLOSED .
|
||||
@ -377,19 +378,35 @@ class UsersProcessor extends ClientSideProcessor {
|
||||
// Load visitors list
|
||||
$db = Database::getInstance();
|
||||
// Load visitors
|
||||
$query = "SELECT visitorid, userid, username, firsttime, " .
|
||||
"lasttime,entry, details, invited, invitationtime, " .
|
||||
"invitedby, invitations, chats " .
|
||||
"FROM {chatsitevisitor} " .
|
||||
"WHERE threadid IS NULL " .
|
||||
"ORDER BY invited, lasttime DESC, invitations";
|
||||
$query = "SELECT v.visitorid, " .
|
||||
"v.userid, " .
|
||||
"v.username, " .
|
||||
"v.firsttime, " .
|
||||
"v.lasttime, " .
|
||||
"v.entry, " .
|
||||
"v.details, " .
|
||||
"t.invitationstate, " .
|
||||
"t.dtmcreated AS invitationtime, " .
|
||||
"t.agentId AS invitedby, " .
|
||||
"v.invitations, " .
|
||||
"v.chats " .
|
||||
"FROM {chatsitevisitor} v " .
|
||||
"LEFT OUTER JOIN {chatthread} t " .
|
||||
"ON t.threadid = v.threadid " .
|
||||
"WHERE v.threadid IS NULL " .
|
||||
"OR (t.istate = :state_invited " .
|
||||
"AND t.invitationstate = :invitation_wait)" .
|
||||
"ORDER BY t.invitationstate, v.lasttime DESC, v.invitations";
|
||||
$query .= (Settings::get('visitors_limit') == '0')
|
||||
? ""
|
||||
: " LIMIT " . Settings::get('visitors_limit');
|
||||
|
||||
$rows = $db->query(
|
||||
$query,
|
||||
NULL,
|
||||
array(
|
||||
':state_invited' => Thread::STATE_INVITED,
|
||||
':invitation_wait' => Thread::INVITATION_WAIT
|
||||
),
|
||||
array('return_rows' => Database::RETURN_ALL_ROWS)
|
||||
);
|
||||
|
||||
@ -410,6 +427,7 @@ class UsersProcessor extends ClientSideProcessor {
|
||||
}
|
||||
|
||||
// Get invitation info
|
||||
$row['invited'] = ($row['invitationstate'] == Thread::INVITATION_WAIT);
|
||||
if ($row['invited']) {
|
||||
$agent_name = get_operator_name(
|
||||
operator_by_id($row['invitedby'])
|
||||
|
@ -15,71 +15,193 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function invitation_state($visitorid)
|
||||
{
|
||||
/**
|
||||
* Check invitation state for specified visitior
|
||||
*
|
||||
* @param int $visitor_id ID of the visitor to check
|
||||
* @return array Array of invitation info. It contains following items:
|
||||
* - 'invited': boolean, indicates if the visitor was invited by an operator;
|
||||
* - 'threadid': int, ID of the thread, related with visitor or boolean false
|
||||
* if visitor with specfied ID does not exist.
|
||||
*/
|
||||
function invitation_state($visitor_id) {
|
||||
$db = Database::getInstance();
|
||||
$result = $db->query(
|
||||
"select invited, threadid from {chatsitevisitor} where visitorid = ?",
|
||||
array($visitorid),
|
||||
$db_result = $db->query(
|
||||
"SELECT t.threadid, t.invitationstate, t.istate " .
|
||||
"FROM {chatsitevisitor} v, {chatthread} t " .
|
||||
"WHERE visitorid = ? " .
|
||||
"AND t.threadid = v.threadid",
|
||||
array($visitor_id),
|
||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||
);
|
||||
if (!$result) {
|
||||
$result['invited'] = 0;
|
||||
$result['threadid'] = 0;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
function invitation_invite($visitorid, $operatorid)
|
||||
{
|
||||
if (!invitation_check($visitorid)) {
|
||||
$db = Database::getInstance();
|
||||
$db->query(
|
||||
"update {chatsitevisitor} set invited = 1, invitedby = :operatorid, " .
|
||||
"invitationtime = :now, invitations = invitations + 1 where visitorid = :visitorid",
|
||||
array(
|
||||
':operatorid' => $operatorid,
|
||||
':visitorid' => $visitorid,
|
||||
':now' => time()
|
||||
)
|
||||
);
|
||||
return invitation_check($visitorid);
|
||||
$ret = array();
|
||||
if (!$db_result) {
|
||||
$ret['invited'] = false;
|
||||
$ret['threadid'] = false;
|
||||
} else {
|
||||
return FALSE;
|
||||
$ret['invited'] = ($db_result['istate'] == Thread::STATE_INVITED)
|
||||
&& ($db_result['invitationstate'] == Thread::INVITATION_WAIT);
|
||||
$ret['threadid'] = $db_result['threadid'];
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function invitation_check($visitorid)
|
||||
{
|
||||
$db = Database::getInstance();
|
||||
$result = $db->query(
|
||||
"select invitedby from {chatsitevisitor} where invited and visitorid = ? " .
|
||||
" and lasttime < invitationtime and threadid is null",
|
||||
array($visitorid),
|
||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||
);
|
||||
return ($result && isset($result['invitedby']) && $result['invitedby']) ? $result['invitedby'] : FALSE;
|
||||
}
|
||||
/**
|
||||
* Invite visitor by operator
|
||||
*
|
||||
* @global string $current_locale Current locale code
|
||||
* @param int $visitor_id ID of the visitor, who must be invited.
|
||||
* @param array $operator Info for operator who invite the visitor
|
||||
* @return Thread|boolean Thread object related with invitation or boolean
|
||||
* false on failure
|
||||
*/
|
||||
function invitation_invite($visitor_id, $operator) {
|
||||
global $current_locale;
|
||||
|
||||
// The visitor already invited
|
||||
if (invitation_check($visitor_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get visitor info
|
||||
$visitor = track_get_visitor_by_id($visitor_id);
|
||||
|
||||
// Get last page visited by the visitor
|
||||
$visitor_path = track_get_path($visitor);
|
||||
ksort($visitor_path);
|
||||
$last_visited_page = array_pop($visitor_path);
|
||||
|
||||
// Get visitor details
|
||||
$visitor_details = track_retrieve_details($visitor);
|
||||
|
||||
// Get some operator's info
|
||||
$operator_name = get_operator_name($operator);
|
||||
|
||||
// Create thread for invitation
|
||||
$thread = Thread::create();
|
||||
if (! $thread) {
|
||||
// Something went wrong
|
||||
return false;
|
||||
}
|
||||
// Populate thread and save it
|
||||
$thread->agentId = $operator['operatorid'];
|
||||
$thread->agentName = $operator_name;
|
||||
$thread->userName = $visitor['username'];
|
||||
$thread->remote = $visitor_details['remote_host'];
|
||||
$thread->referer = $last_visited_page;
|
||||
// User's locale is unknown, set operator locale to the thread
|
||||
$thread->locale = $current_locale;
|
||||
$thread->userId = $visitor['userid'];
|
||||
$thread->userAgent = $visitor_details['user_agent'];
|
||||
$thread->state = Thread::STATE_INVITED;
|
||||
$thread->invitationState = Thread::INVITATION_WAIT;
|
||||
$thread->save();
|
||||
|
||||
function invitation_accept($visitorid, $threadid)
|
||||
{
|
||||
$db = Database::getInstance();
|
||||
$db->query(
|
||||
"update {chatsitevisitor} set threadid = ?, chats = chats + 1 where visitorid = ?",
|
||||
array($threadid, $visitorid)
|
||||
"UPDATE {chatsitevisitor} set " .
|
||||
"invitations = invitations + 1, " .
|
||||
"threadid = :thread_id " .
|
||||
"WHERE visitorid = :visitor_id",
|
||||
array(
|
||||
':thread_id' => $thread->id,
|
||||
':visitor_id' => $visitor_id
|
||||
)
|
||||
);
|
||||
|
||||
// Send some messages
|
||||
$thread->postMessage(
|
||||
Thread::KIND_FOR_AGENT,
|
||||
getlocal2(
|
||||
'chat.visitor.invitation.sent',
|
||||
array($operator_name, $last_visited_page)
|
||||
)
|
||||
);
|
||||
$thread->postMessage(
|
||||
Thread::KIND_AGENT,
|
||||
getlocal("invitation.message"),
|
||||
$operator_name
|
||||
);
|
||||
|
||||
return $thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if visitor already invited
|
||||
*
|
||||
* @param int $visitor_id ID of the visitor to check
|
||||
* @return int|boolean ID of the operator who invite the visitor or boolean
|
||||
* false if the visitor was not invited.
|
||||
*/
|
||||
function invitation_check($visitor_id) {
|
||||
$db = Database::getInstance();
|
||||
$result = $db->query(
|
||||
"select invitedby from {chatsitevisitor} where visitorid = ?",
|
||||
array($visitorid),
|
||||
"SELECT t.agentId AS invitedby " .
|
||||
"FROM {chatsitevisitor} v, {chatthread} t " .
|
||||
"WHERE v.threadid = t.threadid " .
|
||||
"AND v.visitorid = :visitor_id " .
|
||||
// Check only for new invitations. Refactor this place later
|
||||
"AND v.lasttime < t.dtmcreated " .
|
||||
"AND t.istate = :state_invited " .
|
||||
"AND t.invitationstate = :invitation_wait ",
|
||||
array(
|
||||
':visitor_id' => $visitor_id,
|
||||
':state_invited' => Thread::STATE_INVITED,
|
||||
':invitation_wait' => Thread::INVITATION_WAIT
|
||||
),
|
||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||
);
|
||||
return empty($result['invitedby']) ? false : $result['invitedby'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invitation was accepted by visitor
|
||||
*
|
||||
* @param int $visitor_id ID of the visitor who accept invitation
|
||||
* @return Thread|boolean Thread object or boolean false on failure
|
||||
*/
|
||||
function invitation_accept($visitor_id) {
|
||||
// Check if visitor was invited
|
||||
$invitation_state = invitation_state($visitor_id);
|
||||
if (! $invitation_state['invited']) {
|
||||
// Visitor was not invited
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get thread related with the visitor
|
||||
$db = Database::getInstance();
|
||||
$result = $db->query(
|
||||
"SELECT threadid FROM {chatsitevisitor} WHERE visitorid = :visitor_id",
|
||||
array(':visitor_id' => $visitor_id),
|
||||
array('return_rows' => Database::RETURN_ONE_ROW)
|
||||
);
|
||||
|
||||
if ($result && isset($result['invitedby']) && $result['invitedby']) {
|
||||
return $result['invitedby'];
|
||||
} else {
|
||||
return FALSE;
|
||||
if (empty($result['threadid'])) {
|
||||
// Something went wrong. There is no thread related with the visitor.
|
||||
return false;
|
||||
}
|
||||
|
||||
$thread = Thread::load($result['threadid']);
|
||||
if (! $thread) {
|
||||
// Something went wrong. Cannot load thread.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update thread info
|
||||
$thread->state = Thread::STATE_LOADING;
|
||||
$thread->invitationState = Thread::INVITATION_ACCEPTED;
|
||||
$thread->save();
|
||||
|
||||
// Update visitor info
|
||||
$db->query(
|
||||
"UPDATE {chatsitevisitor} SET chats = chats + 1 " .
|
||||
"WHERE visitorid = :visitor_id",
|
||||
array(':visitor_id' => $visitor_id)
|
||||
);
|
||||
|
||||
return $thread;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,12 +210,30 @@ function invitation_accept($visitorid, $threadid)
|
||||
* @param int $visitor_id ID of the visitor
|
||||
*/
|
||||
function invitation_reject($visitor_id) {
|
||||
$visitor = track_get_visitor_by_id($visitor_id);
|
||||
|
||||
// Send message to operator
|
||||
$thread = Thread::load($visitor['threadid']);
|
||||
if ($thread) {
|
||||
$thread->postMessage(
|
||||
Thread::KIND_FOR_AGENT,
|
||||
getlocal('chat.visitor.invitation.rejected')
|
||||
);
|
||||
}
|
||||
|
||||
$db = Database::getInstance();
|
||||
$db->query(
|
||||
"UPDATE {chatsitevisitor} SET invited = 0, " .
|
||||
"invitationtime = NULL, invitedby = NULL " .
|
||||
"WHERE visitorid = ?",
|
||||
array($visitor_id)
|
||||
"UPDATE {chatsitevisitor} v, {chatthread} t SET " .
|
||||
"v.threadid = NULL, " .
|
||||
"t.invitationstate = :invitation_rejected, " .
|
||||
"t.istate = :state_closed " .
|
||||
"WHERE t.threadid = v.threadid " .
|
||||
"AND visitorid = :visitor_id",
|
||||
array(
|
||||
':invitation_rejected' => Thread::INVITATION_REJECTED,
|
||||
':state_closed' => Thread::STATE_CLOSED,
|
||||
':visitor_id' => $visitor_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -105,14 +245,56 @@ function invitation_close_old() {
|
||||
|
||||
// Remove old invitations
|
||||
$db->query(
|
||||
"UPDATE {chatsitevisitor} SET invited = 0, " .
|
||||
"invitationtime = NULL, invitedby = NULL".
|
||||
" WHERE threadid IS NULL AND (:now - invitationtime) > :lifetime",
|
||||
"UPDATE {chatsitevisitor} v, {chatthread} t SET " .
|
||||
"t.invitationstate = :invitation_ignored, " .
|
||||
"t.istate = :state_closed, " .
|
||||
"v.threadid = NULL " .
|
||||
"WHERE t.istate = :state_invited " .
|
||||
"AND t.invitationstate = :invitation_wait " .
|
||||
"AND (:now - t.dtmcreated) > :lifetime",
|
||||
array(
|
||||
':invitation_ignored' => Thread::INVITATION_IGNORED,
|
||||
':invitation_wait' => Thread::INVITATION_WAIT,
|
||||
':state_closed' => Thread::STATE_CLOSED,
|
||||
':state_invited' => Thread::STATE_INVITED,
|
||||
':lifetime' => Settings::get('invitation_lifetime'),
|
||||
':now' => time()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare data to dispaly invitation
|
||||
*
|
||||
* @param Thread $thread Thread object related with invitation
|
||||
* @return array Array of invitation data
|
||||
*/
|
||||
function setup_invitation_view(Thread $thread) {
|
||||
$data = array();
|
||||
|
||||
// Set refresh frequency
|
||||
$data['frequency'] = Settings::get('updatefrequency_chat');
|
||||
|
||||
// Load JavaScript plugins and JavaScripts, CSS files required by them
|
||||
$data = array_merge_recursive($data, get_plugins_data('client_chat_window'));
|
||||
|
||||
// Create some empty arrays
|
||||
$data['invitation'] = array();
|
||||
|
||||
$data['invitation']['thread'] = array(
|
||||
'id' => $thread->id,
|
||||
'token' => $thread->lastToken
|
||||
);
|
||||
|
||||
$data['invitation']['user'] = array(
|
||||
'name' => htmlspecialchars(topage($thread->userName)),
|
||||
'canChangeName' => false,
|
||||
'isAgent' => false
|
||||
);
|
||||
|
||||
$data['startFrom'] = 'invitation';
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
?>
|
@ -81,6 +81,8 @@ chat.thread.state_wait_for_another_agent=Waiting for operator
|
||||
chat.visitor.email=E-Mail: {0}
|
||||
chat.visitor.info=Info: {0}
|
||||
chat.visitor.invitation.accepted=Visitor accepted invitation from operator {0}
|
||||
chat.visitor.invitation.rejected=Visitor rejected invitation
|
||||
chat.visitor.invitation.sent=Operator {0} invites visitor at {1} page
|
||||
chat.wait=Thank you for contacting us. An operator will be with you shortly.
|
||||
chat.window.chatting_with=You are chatting with:
|
||||
chat.window.close_title=Close chat
|
||||
|
@ -81,6 +81,8 @@ chat.thread.state_wait_for_another_agent=
|
||||
chat.visitor.email=E-Mail: {0}
|
||||
chat.visitor.info=Î Ïîñåòèòåëå: {0}
|
||||
chat.visitor.invitation.accepted=Ïîñåòèòåëü ïðèíÿë ïðèãëàøåíèå îò îïåðàòîðà {0}
|
||||
chat.visitor.invitation.rejected=Ïîñåòèòåëü îòêëîíèë ïðèãëàøåíèå
|
||||
chat.visitor.invitation.sent=Îïåðàòîð {0} ïðèãëàñèë ïîñåòèòåëÿ íà ñòðàíèöå {1}
|
||||
chat.wait=Ïîæàëóéñòà, ïîäîæäèòå íåìíîãî, ê Âàì ïðèñîåäèíèòñÿ îïåðàòîð..
|
||||
chat.window.chatting_with=Âû îáùàåòåñü ñ:
|
||||
chat.window.close_title=Çàêðûòü äèàëîã
|
||||
|
@ -17,20 +17,23 @@
|
||||
|
||||
require_once('../libs/init.php');
|
||||
require_once('../libs/invitation.php');
|
||||
require_once('../libs/track.php');
|
||||
require_once('../libs/operator.php');
|
||||
require_once('../libs/classes/thread.php');
|
||||
|
||||
$operator = check_login();
|
||||
|
||||
$visitorid = verifyparam("visitor", "/^\d{1,8}$/");
|
||||
|
||||
if (!invitation_invite($visitorid, $operator['operatorid'])) {
|
||||
$thread = invitation_invite($visitorid, $operator);
|
||||
if (!$thread) {
|
||||
die("Invitation failed!");
|
||||
}
|
||||
|
||||
$page = array();
|
||||
$page['visitor'] = $visitorid;
|
||||
$page['frequency'] = Settings::get('updatefrequency_operator');
|
||||
// Open chat window for operator
|
||||
$redirect_to = $webimroot .
|
||||
'/operator/agent.php?thread=' . $thread->id .
|
||||
'&token=' . $thread->lastToken;
|
||||
header('Location: ' . $redirect_to);
|
||||
|
||||
start_html_output();
|
||||
require('../view/invite.php');
|
||||
?>
|
@ -459,4 +459,41 @@ ul li {
|
||||
top: 200px;
|
||||
left: 250px;
|
||||
}
|
||||
/* ----- */
|
||||
/* ----- */
|
||||
|
||||
/* Invitations */
|
||||
#invitation-messages-region {
|
||||
height: 150px;
|
||||
min-height: 150px;
|
||||
width: 398px;
|
||||
overflow-y: auto;
|
||||
padding: 0px;
|
||||
font: normal 10px Tahoma;
|
||||
line-height: 1.8em;
|
||||
color: #999;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
#invitation-messages-region .minf {
|
||||
font-size: 1.1em;
|
||||
color: #7BAA0F;
|
||||
}
|
||||
#invitation-messages-region .mhidden,
|
||||
#invitation-messages-region .mevent {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
#invitation-messages-region .nagent {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
#invitation-messages-region .nuser {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
color: #DA251D;
|
||||
}
|
||||
#invitation-messages-region .magent,
|
||||
#invitation-messages-region .muser {
|
||||
font-size: 1.1em;
|
||||
color: #000;
|
||||
}
|
||||
/* ----- */
|
||||
|
@ -0,0 +1 @@
|
||||
<div id="invitation-messages-region"></div>
|
@ -27,13 +27,13 @@ d;d={hash:{},data:c};return q((b=f.apply,b?b.call(a,a.message,"urlReplace, nl2br
|
||||
a.helpers;c=c||{};var p,r="function",h=this.escapeExpression,l=f.helperMissing,k=this;a='<div id="message">\n';if((b=f["if"].call(d,(p=d.user,null==p||!1===p?p:p.canPost),{hash:{},inverse:k.noop,fn:k.program(1,function(){return'\n <div class="bgc"><div class="bgl"><div class="bgr">\n <textarea id="message-input" class="message" tabindex="0" rows="4" cols="10"></textarea>\n </div></div></div>\n'},c),data:c}))||0===b)a+=b;a+='\n</div>\n\n<div id="send">\n';if((b=f["if"].call(d,(p=d.user,
|
||||
null==p||!1===p?p:p.canPost),{hash:{},inverse:k.noop,fn:k.program(3,function(a,c){var j,e,b;j='\n <div id="postmessage">\n <div id="predefined-wrapper">\n ';if((b=f["if"].call(a,(e=a.user,null==e||!1===e?e:e.isAgent),{hash:{},inverse:k.noop,fn:k.program(4,g,c),data:c}))||0===b)j+=b;b={hash:{},data:c};j=j+'\n </div>\n <a href="javascript:void(0)" id="send-message" title="'+(h((e=f.L10n,e?e.call(a,"chat.window.send_message",b):l.call(a,"L10n","chat.window.send_message",
|
||||
b)))+'">');b={hash:{},data:c};return j+=h((e=f.L10n,e?e.call(a,"chat.window.send_message_short_and_shortcut",b):l.call(a,"L10n","chat.window.send_message_short_and_shortcut",b)))+"</a>\n </div>\n"},c),data:c}))||0===b)a+=b;return a+'\n</div>\n<div class="clear"></div>'});s.chat_status_base=r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};a=this.escapeExpression;(f=f.title)?f=f.call(d,{hash:{},data:c}):(f=d.title,f="function"===typeof f?f.apply(d):f);return a(f)});
|
||||
s.chat_status_message=r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};a=this.escapeExpression;(f=f.message)?f=f.call(d,{hash:{},data:c}):(f=d.message,f="function"===typeof f?f.apply(d):f);return a(f)});s.chat_status_typing=r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};var g;a=f.helperMissing;b=this.escapeExpression;c={hash:{},data:c};return b((g=f.L10n,g?g.call(d,"typing.remote",c):a.call(d,"L10n","typing.remote",c)))});s.leave_message_description=
|
||||
r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};var g,q=f.helperMissing,p=this.escapeExpression;b={hash:{},data:c};a='<div class="buttons">\n <a href="javascript:window.close();" title="'+(p((g=f.L10n,g?g.call(d,"leavemessage.close",b):q.call(d,"L10n","leavemessage.close",b)))+'">\n <img class="tpl-image iclosewin" src="'+p((g=(g=d.page,null==g||!1===g?g:g.webimRoot),"function"===typeof g?g.apply(d):g))+'/images/free.gif" alt="');b={hash:{},data:c};a+=
|
||||
p((g=f.L10n,g?g.call(d,"leavemessage.close",b):q.call(d,"L10n","leavemessage.close",b)))+'" />\n </a>\n</div>\n<div class="messagetxt">';b={hash:{},data:c};return a+=p((g=f.L10n,g?g.call(d,"leavemessage.descr",b):q.call(d,"L10n","leavemessage.descr",b)))+"</div>"});s.leave_message_form=r(function(a,d,f,b,c){function g(e,a){var c,b;c='<input type="hidden" name="group" value="';(b=f.groupId)?b=b.call(e,{hash:{},data:a}):(b=e.groupId,b=typeof b===k?b.apply(e):b);return c+=m(b)+'"/>'}function q(e,
|
||||
a){var c,b,j;c=""+('\n <option value="'+m((b=e.id,typeof b===k?b.apply(e):b))+'" ');if((j=f["if"].call(e,e.selected,{hash:{},inverse:n.noop,fn:n.program(6,p,a),data:a}))||0===j)c+=j;return c+=">"+m((b=e.name,typeof b===k?b.apply(e):b))+"</option>\n "}function p(){return'selected="selected"'}function r(e,a){var b;return(b=f["if"].call(e,e.selected,{hash:{},inverse:n.noop,fn:n.program(9,h,a),data:a}))||0===b?b:""}function h(e){var a;return m((a=e.description,
|
||||
typeof a===k?a.apply(e):a))}this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};var l,k="function",m=this.escapeExpression,n=this,j=f.helperMissing;a=""+('<form name="leaveMessageForm" method="post" action="">\n <input type="hidden" name="style" value="'+m((l=(l=d.page,null==l||!1===l?l:l.style),typeof l===k?l.apply(d):l))+'"/>\n <input type="hidden" name="info" value="');(b=f.info)?b=b.call(d,{hash:{},data:c}):(b=d.info,b=typeof b===k?b.apply(d):b);a+=m(b)+'"/>\n <input type="hidden" name="referrer" value="';
|
||||
(b=f.referrer)?b=b.call(d,{hash:{},data:c}):(b=d.referrer,b=typeof b===k?b.apply(d):b);a+=m(b)+'"/>\n ';if((b=f.unless.call(d,d.groups,{hash:{},inverse:n.noop,fn:n.program(1,function(e,a){var b;return(b=f["if"].call(e,e.groupId,{hash:{},inverse:n.noop,fn:n.program(2,g,a),data:a}))||0===b?b:""},c),data:c}))||0===b)a+=b;b={hash:{},data:c};a=a+'\n\n <div class="errors"></div>\n\n <table cellspacing="1" cellpadding="5" border="0" class="form">\n <tr>\n <td><strong>'+(m((l=f.L10n,
|
||||
l?l.call(d,"form.field.email",b):j.call(d,"L10n","form.field.email",b)))+':</strong></td>\n <td><input type="text" name="email" size="50" value="');(b=f.email)?b=b.call(d,{hash:{},data:c}):(b=d.email,b=typeof b===k?b.apply(d):b);a+=m(b)+'" class="username"/></td>\n </tr>\n <tr>\n <td><strong>';b={hash:{},data:c};a+=m((l=f.L10n,l?l.call(d,"form.field.name",b):j.call(d,"L10n","form.field.name",b)))+':</strong></td>\n <td><input type="text" name="name" size="50" value="';
|
||||
s.chat_status_message=r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};a=this.escapeExpression;(f=f.message)?f=f.call(d,{hash:{},data:c}):(f=d.message,f="function"===typeof f?f.apply(d):f);return a(f)});s.chat_status_typing=r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};var g;a=f.helperMissing;b=this.escapeExpression;c={hash:{},data:c};return b((g=f.L10n,g?g.call(d,"typing.remote",c):a.call(d,"L10n","typing.remote",c)))});s.invitation_layout=
|
||||
r(function(){this.compilerInfo=[3,">= 1.0.0-rc.4"];return'<div id="invitation-messages-region"></div>'});s.leave_message_description=r(function(a,d,f,b,c){this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};var g,q=f.helperMissing,p=this.escapeExpression;b={hash:{},data:c};a='<div class="buttons">\n <a href="javascript:window.close();" title="'+(p((g=f.L10n,g?g.call(d,"leavemessage.close",b):q.call(d,"L10n","leavemessage.close",b)))+'">\n <img class="tpl-image iclosewin" src="'+
|
||||
p((g=(g=d.page,null==g||!1===g?g:g.webimRoot),"function"===typeof g?g.apply(d):g))+'/images/free.gif" alt="');b={hash:{},data:c};a+=p((g=f.L10n,g?g.call(d,"leavemessage.close",b):q.call(d,"L10n","leavemessage.close",b)))+'" />\n </a>\n</div>\n<div class="messagetxt">';b={hash:{},data:c};return a+=p((g=f.L10n,g?g.call(d,"leavemessage.descr",b):q.call(d,"L10n","leavemessage.descr",b)))+"</div>"});s.leave_message_form=r(function(a,d,f,b,c){function g(e,a){var c,b;c='<input type="hidden" name="group" value="';
|
||||
(b=f.groupId)?b=b.call(e,{hash:{},data:a}):(b=e.groupId,b=typeof b===k?b.apply(e):b);return c+=m(b)+'"/>'}function q(e,a){var c,b,j;c=""+('\n <option value="'+m((b=e.id,typeof b===k?b.apply(e):b))+'" ');if((j=f["if"].call(e,e.selected,{hash:{},inverse:n.noop,fn:n.program(6,p,a),data:a}))||0===j)c+=j;return c+=">"+m((b=e.name,typeof b===k?b.apply(e):b))+"</option>\n "}function p(){return'selected="selected"'}function r(e,a){var b;return(b=f["if"].call(e,e.selected,
|
||||
{hash:{},inverse:n.noop,fn:n.program(9,h,a),data:a}))||0===b?b:""}function h(e){var a;return m((a=e.description,typeof a===k?a.apply(e):a))}this.compilerInfo=[3,">= 1.0.0-rc.4"];f=f||a.helpers;c=c||{};var l,k="function",m=this.escapeExpression,n=this,j=f.helperMissing;a=""+('<form name="leaveMessageForm" method="post" action="">\n <input type="hidden" name="style" value="'+m((l=(l=d.page,null==l||!1===l?l:l.style),typeof l===k?l.apply(d):l))+'"/>\n <input type="hidden" name="info" value="');
|
||||
(b=f.info)?b=b.call(d,{hash:{},data:c}):(b=d.info,b=typeof b===k?b.apply(d):b);a+=m(b)+'"/>\n <input type="hidden" name="referrer" value="';(b=f.referrer)?b=b.call(d,{hash:{},data:c}):(b=d.referrer,b=typeof b===k?b.apply(d):b);a+=m(b)+'"/>\n ';if((b=f.unless.call(d,d.groups,{hash:{},inverse:n.noop,fn:n.program(1,function(e,a){var b;return(b=f["if"].call(e,e.groupId,{hash:{},inverse:n.noop,fn:n.program(2,g,a),data:a}))||0===b?b:""},c),data:c}))||0===b)a+=b;b={hash:{},data:c};a=a+'\n\n <div class="errors"></div>\n\n <table cellspacing="1" cellpadding="5" border="0" class="form">\n <tr>\n <td><strong>'+
|
||||
(m((l=f.L10n,l?l.call(d,"form.field.email",b):j.call(d,"L10n","form.field.email",b)))+':</strong></td>\n <td><input type="text" name="email" size="50" value="');(b=f.email)?b=b.call(d,{hash:{},data:c}):(b=d.email,b=typeof b===k?b.apply(d):b);a+=m(b)+'" class="username"/></td>\n </tr>\n <tr>\n <td><strong>';b={hash:{},data:c};a+=m((l=f.L10n,l?l.call(d,"form.field.name",b):j.call(d,"L10n","form.field.name",b)))+':</strong></td>\n <td><input type="text" name="name" size="50" value="';
|
||||
(b=f.name)?b=b.call(d,{hash:{},data:c}):(b=d.name,b=typeof b===k?b.apply(d):b);a+=m(b)+'" class="username"/></td>\n </tr>\n ';if((b=f["if"].call(d,d.groups,{hash:{},inverse:n.noop,fn:n.program(4,function(e,a){var b,c,d;d={hash:{},data:a};b='\n <tr>\n <td class="text"><strong>'+(m((c=f.L10n,c?c.call(e,"form.field.department",d):j.call(e,"L10n","form.field.department",d)))+'</strong></td>\n <td>\n <select name="group" style="min-width:200px;">\n ');
|
||||
if((d=f.each.call(e,e.groups,{hash:{},inverse:n.noop,fn:n.program(5,q,a),data:a}))||0===d)b+=d;b+='\n </select>\n </td>\n </tr>\n <tr>\n <td class="text"><strong>';d={hash:{},data:a};b+=m((c=f.L10n,c?c.call(e,"form.field.department.description",d):j.call(e,"L10n","form.field.department.description",d)))+'</strong></td>\n <td class="text" id="groupDescription">\n ';if((d=f.each.call(e,e.groups,{hash:{},inverse:n.noop,fn:n.program(8,
|
||||
r,a),data:a}))||0===d)b+=d;return b+="\n </td>\n </tr>\n "},c),data:c}))||0===b)a+=b;a+="\n <tr>\n <td><strong>";b={hash:{},data:c};a+=m((l=f.L10n,l?l.call(d,"form.field.message",b):j.call(d,"L10n","form.field.message",b)))+':</strong></td>\n <td valign="top">\n <textarea name="message" tabindex="0" cols="40" rows="5">';(b=f.message)?b=b.call(d,{hash:{},data:c}):(b=d.message,b=typeof b===k?b.apply(d):b);a+=m(b)+"</textarea>\n </td>\n </tr>\n ";
|
||||
|
@ -103,6 +103,9 @@
|
||||
${if:leaveMessageOptions}
|
||||
leaveMessageOptions: ${page:leaveMessageOptions},
|
||||
${endif:leaveMessageOptions}
|
||||
${if:invitationOptions}
|
||||
invitationOptions: ${page:invitationOptions},
|
||||
${endif:invitationOptions}
|
||||
startFrom: "${page:startFrom}",
|
||||
plugins: ${page:js_plugin_options}
|
||||
});
|
||||
|
@ -80,3 +80,10 @@
|
||||
cursor: pointer !important;
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
#mibewinvitationframe {
|
||||
width: 398px;
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
$page['title'] = getlocal("invitation.title");
|
||||
|
||||
function tpl_header() { global $page, $webimroot;
|
||||
?>
|
||||
|
||||
<!-- External libs -->
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/libs/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/libs/json2.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/libs/underscore-min.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/libs/backbone-min.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/libs/backbone.marionette.min.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/libs/handlebars.js"></script>
|
||||
|
||||
<!-- Application files -->
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/compiled/mibewapi.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/compiled/default_app.js"></script>
|
||||
<script type="text/javascript" src="<?php echo $webimroot ?>/js/compiled/invite_app.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
jQuery(document).ready(function(){
|
||||
Mibew.Application.start({
|
||||
server: {
|
||||
url: "<?php echo $webimroot ?>/operator/invitationstate.php",
|
||||
requestsFrequency: <?php echo $page['frequency'] ?>
|
||||
},
|
||||
|
||||
visitorId: "<?php echo $page['visitor'] ?>",
|
||||
|
||||
chatLink: "<?php echo $webimroot ?>/operator/agent.php"
|
||||
});
|
||||
});
|
||||
//--></script>
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
function tpl_content() { global $page, $webimroot;
|
||||
?>
|
||||
|
||||
<?php echo getlocal("invitation.sent"); ?>
|
||||
|
||||
<div class="ajaxWait"></div>
|
||||
|
||||
<?php
|
||||
} /* content */
|
||||
|
||||
require_once('inc_main.php');
|
||||
?>
|
@ -71,9 +71,12 @@ if (Settings::get('enabletracking') == '1') {
|
||||
$operatorName = ($locale == $home_locale)
|
||||
? $operator['vclocalename']
|
||||
: $operator['vccommonname'];
|
||||
$response['data']['invitation']['operator'] = htmlspecialchars($operatorName);
|
||||
$response['data']['invitation']['message'] = getlocal("invitation.message");
|
||||
$response['data']['invitation']['avatar'] = htmlspecialchars($operator['vcavatar']);
|
||||
$response['data']['invitation'] = array(
|
||||
'operator' => htmlspecialchars($operatorName),
|
||||
'avatar' => htmlspecialchars($operator['vcavatar']),
|
||||
'url' => get_app_location(true, is_secure_request())
|
||||
. '/client.php?act=invitation'
|
||||
);
|
||||
}
|
||||
|
||||
// Check if visitor reject invitation
|
||||
|
Loading…
Reference in New Issue
Block a user