Inline support Chat implementation - ajax

We are creating a live chat support system. Currently if the visitor clicks on live chat button, a new window opens up and user can talk their. What I am trying to accomplish is to open the chat window inline like this link:
http://anantgarg.com/chat/sampleb.php
Please note that we are building support chat system not peer chat system as the above link intends.
The problem we are facing here is that how we'll be able to access the database which is located on different server (our server) and not on the server where our client's website is located. The above solution can work fine if we are on the same server.
So, please suggest on how to overcome this hurdle.
Thanks.

I think, for solve your task you may use WebSockets, it support cross-domain connections.
In your case, you may write chat client side and place it on cliet's website, but request from it weill processed by your server with DB access.
Extend
Of course you can use JSON with WebSockets just as JSON with AJAX. WebSockets is transport - JSON is content passed with this transport.
I write this code when reserarch WebSockets (chat lietn side):
function connect(){
var socket;
var host = window.location.host;
var wsUrl = "ws://" + host + "/connect";
try{
var socket = new WebSocket(wsUrl);
message('<p class="event">Socket Status: '+socket.readyState);
socket.onopen = function(){
message('<p class="event">Socket Status: '+socket.readyState+' (open)');
//Run "Ping-Pong" for support connection
setTimeout(pingPong, 5000);
}
socket.onmessage = function(msg){
//Parse server answer from string to JSON object
var answer = JSON.parse(msg.data);
if (answer.type == 'message') {
message('<p class="message">'+answer.user+': '+answer.message);
}
}
socket.onclose = function(){
message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');
}
} catch(exception){
message('<p>Error'+exception);
}
function send(){
var text = $('#text').val();
if(text==""){
message('<p class="warning">Please enter a message');
return ;
}
try{
//Send data via JSON
socket.send('{"type": "message", "message":'+JSON.stringify(text)+'}');
} catch(exception){
message('<p class="warning">');
}
$('#text').val("");
}
var token = 0;
function pingPong()
{
token++;
try{
var msg = {'type': 'ping', 'token': token};
socket.send(JSON.stringify(msg));
setTimeout(pingPong, 5000);
} catch(exception){
message('<p class="warning">');
}
}
function message(msg){
$('#chatLog').append(msg+'</p>');
}//End message()
$('#text').keypress(function(event) {
if (event.keyCode == '13') {
send();
}
});
$('#disconnect').click(function(){
socket.close();
});
}
$(document).ready(function() {
if(!("WebSocket" in window)){
$('#chatLog, input, button, #examples').fadeOut("fast");
$('<p>Oh no, you need a browser that supports WebSockets. How about Google Chrome?</p>').appendTo('#container');
}else{
//The user has WebSockets
connect();
}
});
</script>
<meta charset=utf-8 />
<style type="text/css">
body{font-family:Arial, Helvetica, sans-serif;}
#container{
border:5px solid grey;
width:800px;
margin:0 auto;
padding:10px;
}
#chatLog{
padding:5px;
border:1px solid black;
}
#chatLog p{margin:0;}
.event{color:#999;}
.warning{
font-weight:bold;
color:#CCC;
}
</style>
<title>WebSockets Client</title>
</head>
<body>
<div id="wrapper">
<div id="container">
<h1>WebSockets Client</h1>
<div id="chatLog">
</div>
<p id="examples">e.g. try 'hi', 'name', 'age', 'today'</p>
<input id="text" type="text" />
<button id="disconnect">Disconnect</button>
</div>
</div>
</body>
</html>​
Also you can use SocketIO library for it, but I dont sure for it cross-domain work.

Related

How to implement AutoComplete Text view in an adaptive card

I have a use case in which i have to show responses from an API to the user, as he types in the text view in the adaptive card, I have a Bot using Microsoft Bot Framework, my chat bot is currently working in a web client, but i want this functionality to also work on Microsoft Teams and other platforms (in which adaptive card is supported). Adaptive Card doesn't support AutoComplete view, its in there roadmap for now.
So here i am looking for a workaround to implement this functionality in my Bot.
If your main use case is Teams, then you have another option, but it will work only in Teams - it is to use a Task Module. Basically, Task Modules are a special kind of popup window in Teams. You have two options for what gets shown in a Task Module:
An Adaptive Card
Any custom web page, that is basically just being IFramed into the popup
So, you could look at using option 2 above, building anything you want into the web page, including "autocomplete". Later, if / when Adaptive Cards offers what you need, you could simply change out what gets shown to the user, from being your custom web page, to being the Adaptive Card.
You can read more about Task Modules, and how to get started, at What are Task Modules.
Of course, as I said, Task Modules only work in Teams, so it won't help your other scenarios, but perhaps you can use the regular Adaptive Cards there, and do the Task Module if you detect the client is using Microsoft Teams.
Although Adaptive Cards do not support autocomplete view as of now, instead of using Adaptive Cards, you can build our own component and use attachmentMiddleware to intercept those cards. You can add an input field with your autocomplete logic in your custom renderer.
Refer to this sample for the implementation of the above logic.
Code Sample:
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Custom attachment with GitHub Stargazers</title>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://unpkg.com/react#16.8.6/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16.8.6/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-redux#7.1.0/dist/react-redux.min.js"></script>
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script type="text/babel">
const GitHubRepositoryAttachment = props =>
<div style={{ fontFamily: '\'Calibri\', \'Helvetica Neue\', Arial, sans-serif', margin: 20, textAlign: 'center' }}>
<svg height="64" viewBox="0 0 16 16" version="1.1" width="64" aria-hidden="true"><path fillRule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
<p>
{ props.owner }/<br />{ props.repo }
</p>
</div>;
(async function () {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
const { ReactWebChat } = window.WebChat;
const attachmentMiddleware = () => next => card => {
switch (card.attachment.contentType) {
case 'application/vnd.microsoft.botframework.samples.github-repository':
return <GitHubRepositoryAttachment owner={ card.attachment.content.owner } repo={ card.attachment.content.repo } />;
default:
return next(card);
}
};
window.ReactDOM.render(
<ReactWebChat
attachmentMiddleware={ attachmentMiddleware }
directLine={ window.WebChat.createDirectLine({ token }) }
/>,
document.getElementById('webchat')
);
store.dispatch({
type: 'WEB_CHAT/SET_SEND_BOX',
payload: { text: 'sample:github-repository' }
});
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
Also, refer to this SO answer on Autocompletion with Botframework's Web Chat where you can add flexdatalist to WebChat's input field, but you also have to dispatch actions to WebChat's store to notify it of changes.
Hope this helps.

How to show the bot icon in the webchat?

I have an image for my bot, but it's not showing up in the webchat.
Is there any way to make it happen like the image in this link (https://cloud.githubusercontent.com/assets/979837/19395693/cbdf6ac2-91f3-11e6-8a48-ba533bf91dca.png) ?
My script for the bot is:
<script>
//Scrip for the webchat window
(function () {
var div = document.createElement("div");
document.getElementsByTagName('body')[0].appendChild(div);
div.outerHTML = "<div id='botDiv' style='height: 38px; position: fixed; bottom: 0; right: 1%; z-index: 1000; background-color: #fff'><div id='botTitleBar' style='height: 38px; width: 350px; position:fixed; cursor: pointer;'></div><iframe width='400px' height='600px' src='https://webchat.botframework.com/embed/xxx'></iframe></div>";
document.querySelector('body').addEventListener('click', function (e) {
e.target.matches = e.target.matches || e.target.msMatchesSelector;
if (e.target.matches('#botTitleBar')) {
var botDiv = document.querySelector('#botDiv');
botDiv.style.height = botDiv.style.height == '600px' ? '38px' : '600px';
};
});
}());
</script>
I would recommend you step away from the webchat channel iFrame option and utilize the BotFramework-WebChat tool, instead. The webchat channel is fine for simple deployments, but it isn't overly robust out-of-the-bot.
If you look over sample 04.b.display-user-bot-images-styling from the BotFramework-WebChat repo, you will see precisely how you can effect the bot/user avatars.
In short, you will include the web chat CDN into you html file, assign some basic styling for the web chat div, followed by the script that connects to and generates that actual web chat experience.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Avatar with images and initials</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--
For demonstration purposes, we are using the development branch of Web Chat at "/master/webchat.js".
When you are using Web Chat for production, you should use the latest stable release at "/latest/webchat.js",
or lock down on a specific version with the following format: "/4.1.0/webchat.js".
-->
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script>
(async function () {
// In this demo, we are using Direct Line token from MockBot.
// To talk to your bot, you should use the token exchanged using your Direct Line secret.
// You should never put the Direct Line secret in the browser or client app.
// https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
const styleOptions = {
botAvatarImage: 'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0',
botAvatarInitials: 'BF',
userAvatarImage: 'https://github.com/compulim.png?size=64',
userAvatarInitials: 'WC'
};
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
styleOptions
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
This option does require generating a direct line token. This is accomplished by passing your direct line secret to the direct line /tokens/generate api and receiving a token back. The generated token is tied to the particular session so, as such, provides a certain level of security. Please don't use your secret in this setting.
The below is a node.js example and can be run as an independent app or incorporated into your existing bot as a separate api call made while the html page / web chat is loading. It wouldn't be hard to recreate an equivalent dotnet version.
server.post('/directline/token', (req, res) => {
// userId must start with `dl_`
const userId = (req.body && req.body.id) ? req.body.id : `dl_${Date.now() + Math.random().toString(36) }`;
const options = {
method: 'POST',
uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
headers: {
'Authorization': `Bearer ${process.env.directLineSecret}`
},
json: {
User: {
Id: userId
}
}
};
request.post(options, (error, response, body) => {
if (!error && response.statusCode < 300) {
res.send({
token: body.token
});
} else {
res.status(500).send('Call to retrieve token from DirectLine failed');
}
});
});
Hope of help!

how to use connect-flash with ajax

I have a page with a form that posts edits to a local endpoint via AJAX ($.post). I want to display a message to the user whether it went good or bad. But I can't get it to work. Here's what I have so far:
jade template (excerpt)
if message
.alert.alert-danger= message
// Tab panes
.tab-content
#admin-tab-profile.tab-pane.active(role='tabpanel')
h3 Profil
form
include partials/admin/profile
main.js (excerpt)
app.post('/admin', function(req, res) {
var data = req.body;
// find profile
profile.findById(data._id, function(err, profile) {
// update
profile.summary.da = data.da;
profile.summary.en = data.en;
// save
profile.save(function(err) {
if (err) {
req.flash('loginMessage', 'Oops! Something went wrong.');
res.status(500).send( { message: req.flash('loginMessage') } );
}
console.log("profile sucessfully updated");
req.flash('loginMessage', 'Yes! Everythings good!');
res.status(200).send( { message: req.flash('loginMessage') } );
});
});
});
app.js (excerpt)
app.use(flash()); // use connect-flash for flash messages stored in session
So what am I doing wrong? Why is not shown status messages when posting data?
Well if your using ajax you don't have to use express flash messages, you can simply use ajax.success method:
$.ajax({
method:'post',
url: '/user/singup',
data: data,
success: function(msg) {
console.log('Success!!');
console.log(msg); // loginMessage from your code
},
error: function() {
console.log('Error!!');
}
})
And send the status code from your post method in express:
res.status(200).send({ message: 'loginMessage' });
I managed to do that. I made it same as here:
https://www.npmjs.com/package/express-messages
<body>
<%- messages('my_message_template', locals) %>
<div id="messages">
<% Object.keys(messages).forEach(function (type) { %>
<% messages[type].forEach(function (message) { %>
<div class="alert alert-<%= type%>">
<%= message %>
</div>
<% }) %>
<% }) %>
</div>
And in $.ajax({ success:... I put this line:
$('#messages').load(location.href + " #messages");
So if ajax action was successful, it refreshed the div that id = messages.
In express I have this line:
res.status(200).json({ messages: req.flash('success','Yes! Everythings good')});
In above link, it states <%= type %> (ejs) if message is success or error (ie) and for that the styling is ie:
<style>
.alert-success{
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
}
.alert-error{
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}
</style>
This colors the background to green if message is 'success' or red if it's 'error'

How to display error message of jquery dropzone

I use dropzone with CI, i don't know how to display error message and custom message when upload false, this is my script
Dropzone.autoDiscover = false;
try {
var myDropzone = new Dropzone("#adminform" , {
paramName: "filename", // The name that will be used to transfer the file
maxFilesize: 0.5, // MB
url: window.location.href,
addRemoveLinks : true,
dictDefaultMessage :
'<span class="bigger-150 bolder"><i class="ace-icon fa fa-caret-right red"></i> Drop files</span> to upload \
<span class="smaller-80 grey">(or click)</span> <br /> \
<i class="upload-icon ace-icon fa fa-cloud-upload blue fa-3x"></i>',
dictResponseError: 'Error while uploading file!',
//change the previewTemplate to use Bootstrap progress bars
previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-details\">\n <div class=\"dz-filename\"><span data-dz-name></span></div>\n <div class=\"dz-size\" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n <div class=\"progress progress-small progress-striped active\"><div class=\"progress-bar progress-bar-success\" data-dz-uploadprogress></div></div>\n <div class=\"dz-success-mark\"><span></span></div>\n <div class=\"dz-error-mark\"><span></span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n</div>",
});
}
catch(e) {
alert('Dropzone does not support older browsers!');
}
And PHP return 400:
$this->output->set_header("HTTP/1.0 400 Bad Request");
But when i hover image it's display [object Object] but message is:
dictResponseError: 'Error while uploading file!'
For anyone in need:
You can return a response message from the server using echo. Then in the js code add an error event handler
PHP
header("HTTP/1.0 400 Bad Request");
echo "Ups error message";
JS
this.on('error', function(file, response) {
$(file.previewElement).find('.dz-error-message').text(response);
});
For me this code finally worked, used as a dropzone option:
error: function(file, message) {
$(file.previewElement).addClass("dz-error").find('.dz-error-message').text(message.Message);
}
I used message.Message since the ASP.net WebAPI returns a JSON object, but not with the required "error" key.
You can simply echo back the message from server via PHP file
if($file_uploaded == true)
{
//perform operations on valid upload
} else {
//upload failed, echo back negative response to dropzone.js
$this->output->set_header("HTTP/1.0 400 Bad Request");
echo "Error uploading file";
}
While your HTML file can look like:
<script type="text/javascript">
Dropzone.options.myAwesomeDropzone = {
paramName: "icon_image", // The name that will be used to transfer the file
maxFilesize: 2, // MB
init: function() {
this.on("error", function(file, response) {
// do stuff here.
alert(response);
});
}
};
</script>
Hope it helps :)

Facebook login via Parse & Javascript

I want the facebook login/register box to be displayed after the user clicks a link, but it won't work. Parse is supposed to load the FB SDK with its own init function and is supposed to display the login box with another one of its own functions. I've copied and pasted that code directly from their documentation so I don't think it's a syntax problem. I've also tried initializing the Parse SDK in different places but it doesn't seem to matter. I know the jquery function is working because I've tested it with an alert function and it fires when I click the targeted link, but the login box won't show.
What do I need to fix?
>
<body>
<div id="fb-root"></div>
<script>
// Initialize the Parse SDK!
Parse.initialize("***********","***********");
window.fbAsyncInit = function() {
//initialize Facebook SDK via Parse
Parse.FacebookUtils.init({
appId : '***********', // App ID from the App DashboardD
channelUrl : '//http://spilot.koding.com/channel.html', // Channel File for x-domain communication
status : true, // check the login status upon init?
cookie : true, // set sessions cookies to allow your server to access the session?
xfbml : true // parse XFBML tags on this page?
});
// Additional initialization code such as adding Event Listeners goes here
// use Parse SDK to show Facebook login/registration box after user clicks link
$("a").click(function(){
Parse.FacebookUtils.logIn(null, {
success: function(user) {
if (!user.existed()) {
alert("User signed up and logged in through Facebook!");
} else {
alert("User logged in through Facebook!");
}
},
error: function(user, error) {
alert("User cancelled the Facebook login or did not fully authorize.");
}
});
});
// Load the SDK's source Asynchronously
// Note that the debug version is being actively developed and might
// contain some type checks that are overly strict.
// Please report such bugs using the bugs tool.
(function(d, debug){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all" + (debug ? "/debug" : "") + ".js";
ref.parentNode.insertBefore(js, ref);
}(document, /*debug*/ false));
</script>
<div id="header"></div>
<div id="findScene"><h1>Find</h1></div>
<div id="startScene"><h1>Host</h1></div>
<div id="footer"></div>
</body>
>
<script type="text/javascript">
// Initialize the Parse object first.
Parse.initialize("XXXXXXXXXX", "YYYYYYYYYYYYY");
window.fbAsyncInit = function() {
Parse.FacebookUtils.init({
appId : 'ZZZZZZZZZZZZZZZ',
status : true,
cookie : true,
xfbml : true
});
Parse.FacebookUtils.logIn(null, {
success: function(user) {
if (!user.existed()) {
alert("User signed up and logged in through Facebook!");
} else {
alert("User logged in through Facebook!");
}
},
error: function(user, error) {
alert("User cancelled the Facebook login or did not fully authorize.");
}
});
};
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document)); </script>

Resources