I have a bot which is on a web widget, i will have this bot integrated to a parent application, from which i am fetching user's employee code. I want to handle the use case in which if a user is already talking to my bot i.e already in a session , then user cannot open another window from any other system or browser and talk at the same time. I want to map user's employee code in a way that if the above scenario happens my bot informs the user that you are already in session.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Digital Assistant</title>
<link href="https://cdn.botframework.com/botframework-webchat/latest/botchat.css" rel="stylesheet" />
<style>
.example {
float: left;
margin-right: 20px;
width: 300px;
}
.example > h2 {
font-family: 'Segoe UI';
}
#BotChatGoesHere {
border: 1px solid #333;
right: 10px;
height: 100%;
position: absolute;
width: 100%;
bottom:10px;
}
.wc-header {
background-color: #107ad1;
box-shadow: 0 1px rgba(0, 0, 0, 0.2);
box-sizing: content-box;
color: #ffffff;
font-weight: 500;
height: 40px;
left: 0;
letter-spacing: 0.5px;
padding: 8px 8px 0 8px;
position: absolute;
right: 0;
top: 0;
z-index: 1;
background-image: url(https://example.com/ess/App_Themes/HomepageBlue/images/tab_bg.jpg);
}
.wc-header span{
text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em darkblue;
font-size: 24px;
padding: 0 15px;
}
.wc-time {
color: #999999;
margin-bottom: 10px; }
.wc-message-groups {
bottom: 50px;
left: 0;
transform: translateY(0);
outline: 0;
overflow-x: hidden;
overflow-y: scroll;
padding: 10px;
position: absolute;
right: 0;
top: 38px;
transition: transform 0.2s cubic-bezier(0, 0, 0.5, 1);
background:linear-gradient(64deg,#1c627d 0,#1c637e 11%,#1b677f 20%,#196c81 27.5%,#177283 33.7%,#157986 38.8%,#138089 43.3%,#10888c 47.3%,#0e918f 51.2%,#0c9892 55.3%,#09a095 59.9%,#07a798 65.2%,#06ad9a 71.6%,#04b19b 79.3%,#03b49d 88.7%,#03b59d 100%);
}
.wc-message-groups.no-header {
top: 0; }
.wc-videocall-image{
cursor: pointer;
float: right;
width: 30px;
height: 30px;
margin-right: 12px;
border-radius: 50%;
font-size: 18px;
text-align: center;
line-height: 32px;
background: #ff60a9;
}
.userimage {
float: right;
width: 35px;
height: 35px;
text-align: center;
margin-right: 8px;
padding: 0;
margin-top: 0;
}
.userimage img {
width: 100%;
border-radius: 50%;
}
.userimage img:hover{
transform: scale(1.5);
}
.wc-message-content {
border-radius: 5px 10px 5px;
text-transform: capitalize;
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.2);
padding: 8px;
word-break: break-word; }
.wc-message-from{
color:#ddd !important; }
.wc-message-from-me {
float: right;
margin-right: 6px; }
.wc-message-from-me.wc-message-from {
text-align: right; }
.wc-message-from-me .wc-message-content {
background-color: #107ad1;background-image: linear-gradient(#8bc4f3, #107ad1);
color: #ffffff; }
.wc-message-from-me svg.wc-message-callout path {
fill: #107ad1; }
.wc-message-from-me svg.wc-message-callout path.point-left {
display: none; }
/* from bot */
.wc-message-from-bot {
float: left;
margin-left: 8px; }
.wc-message-from-bot .wc-message-content {
background-color: #dcdcdc; background-image: linear-gradient(#d0caca, #efefef);
color: #000000; }
.wc-message-from-bot svg.wc-message-callout path {
fill: #dcdcdc; }
.wc-message-from-bot svg.wc-message-callout path.point-right {
display: none; }
.wc-message-from-bot svg.wc-message-callout {
left: -6px; }
</style>
</head>
<body>
<div id="BotChatGoesHere"></div>
<script src="https://cdn.botframework.com/botframework-webchat/latest/botchat.js"></script>
<!-- If you do not want to use Cognitive Services library, comment out the following line -->
<script src="https://cdn.botframework.com/botframework-webchat/latest/CognitiveServices.js"></script>
<script>
const params = BotChat.queryParams(location.search);
const user = {
id: params['userid'] || '5B6RnDTSIA4',
name: params['username'] || 'You',
usernametext:"You"
};
const bot = {
id: params['botid'] || 'mts-bot',
name: params['botname'] || 'ABC'
};
window.botchatDebug = params['debug'] && params['debug'] === 'true';
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'
};
BotChat.App({
bot: bot,
chatTitle:"NIIT Digital Assistant",
locale: params['locale'],
resize: 'detect',
sendTyping: true, // defaults to false. set to true to send 'typing' activities to bot (and other users) when user is typing
speechOptions: speechOptions,
user: user,
styleOptions,
directLine: {
domain: params['webchat.botframework.com'],
secret: params['s'],
token: params['t'],
webSocket: params['webSocket'] && params['webSocket'] === 'true' // defaults to true
}
}, document.getElementById('BotChatGoesHere'));
</script>
</body>
</html>
Unfortunately, there is not a built-in or easy way to do this. You're going to have to cobble together a few additional things to make this work and there isn't really a "standard" answer. However, here's a couple of ways I can think to do this:
Both
Both of my ideas have similar starting components:
Use the employee's code as their user id:
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({
token: 'YOUR_DIRECT_LINE_TOKEN'
}),
userID: <theEmployeeCode>
},
document.getElementById('webchat')
);
Send an Event on Each Page Load
Send an event that fires on each page load
In the bot, by userId, keep track of when each event was received. Something like:
{
<userId>: {
lastJoinEvent: <timeOfLastJoinEvent>
}
}
In the bot, when a join event is received, check if <userId>.lastJoinEvent exists and if it does, you'll want to allow unique sessions after a certain amount of time (say they talked to the bot on a different day), so you'll need some logic that says if <timeOfLastCurrentEvent> - <timeOfLastJoinEvent> > 1 hour (or something), don't send the "session already open" message.
Send Additional Data With Each Message
Generate a constant random id (GUID or random string of some kind) each time the page is loaded, and send that with the activity's ChannelData.
For each message the bot receives from that userId, store an object something like:
{
<userId>: {
lastRandomId: <generatedRandomId>
lastMessageTimestamp: <timeOfLastMessage>
}
}
On each message, update the lastRandomId and the lastMessageTimestamp
In your bot, on each message, check that for the userId, the received randomId matches the lastRandomId. If it does, you can ensure that they're in the same session, so no need to send the "session already open" message.
If they do not match, the sessions are unique. However, you'll want to allow unique sessions after a certain amount of time (say they talked to the bot on a different day), so you'll need some logic that says if <currentMessageTimestamp> - <lastMessageTimestamp> > 1 hour (or something), don't send the "session already open" message.
Now, the problem with this is that you need to make this check on every single message, which is an "expensive" check for something like this. If your bot doesn't have a lot of users and you don't scale it horizontally, you could just store this map in memory--otherwise, you'd need a more permanent storage solution. So, of the two, I'd recommend the first.
All that being said, I recommend against this because:
This can only work in clients that you can either 1) send events on load, or 2) send channelData with every message. So, this would work in Web Chat, but not Teams
This is not easy to implement
If you scale your bot horizontally, you can't store this in memory, which means you're making additional storage API calls fairly frequently. Not too bad for the first options, but rules out the second.
There may be other ways to do this, too, but this is all I can think of.
Related
In my code behind I have the following:
public void btnDoSomething_Click(object sender, EventArgs e)
{
if (sku.Peso == 0)
{
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "Validation",
"<script type='text/javascript'>alert('You can't do that!');</script>", false);
pnlSKU.Style.Remove("visibility");
pnlSKU.Style.Add("visibility", "visible");
}
else
//It does something...
pnlSKU.Style.Remove("visibility");
pnlSKU.Style.Add("visibility", "visible");
}
In my aspx I have the following inside the panel pnlSKU:
<asp:Panel ID="pnlSKU" runat="server" Style="visibility: hidden; overflow-x: auto overflow-y: scroll; border-right: black thin solid;
border-top: black thin solid; z-index: 200; left: 210px; border-left: black thin solid;
border-bottom: black thin solid; position: absolute; top: 28%; height: 500px;
background-color: white; width: 900px;">
The code in itself is very much longer but It doesn't matter at this point.
Everytime the condition is met the control panel dissapears completely even If I call the method add to the Style property and put "visible".
Any idea why is happening?
I want to underline a word with a round brace. This should be part of a C# Text but if it is easier in CSS, no problem. My problem is that the length of the Word can vary, so the bow must by calculated for each word.
My first idea was using CSS box-shadow:
CSS:
#test {
font-size: 50px;
background: transparent;
border-radius: 70px;
height: 65px;
width: 90px;
box-shadow: 0px 6px 0px -2px #00F;
font-family: sans-serif;
}
HTML:
<div id="test">Hey</div>
Unfortunately due to the dynamic Text sizes I can't calculate them.
Is there a smarter approach to this problem?
You don't need to calculate the width if you use span tags instead.
CSS:
.test {
font-size: 50px;
background: transparent;
border-radius: 70px;
height: 65px;
box-shadow: 0px 6px 0px -2px #00F;
font-family: sans-serif;
}
HTML:
<span id="test" class="test">Hey</span><br/>
<span class="test">Hey this is longer</span>
Working Fiddle: http://jsfiddle.net/Ge8Q3/
I found a different approach.
Working fiddle: http://jsfiddle.net/6pEQA/1/
I used javascript and made the width dynamic:
textWidth function taken from here.
$.fn.textWidth = function(){
var self = $(this),
children = self.contents(),
calculator = $('<span style="white-space:nowrap;" />'),
width;
children.wrap(calculator);
width = children.parent().width(); // parent = the calculator wrapper
children.unwrap();
return width;
};
$(document).ready(function(){
$('#test').css('width',$('#test').textWidth());
});
It also works with h1, div or span. You can check my fiddle. Because it is using span elements to calculate width of the element.
i have two popup windows in my Home Page (Default.aspx) like below :
apsx Code :
<div id="OffDiv">
</div>
<div id="TimerContainer">
<asp:Image ID="imgWhiteCircle" runat="server" ImageUrl="~/Images/WhiteCircle.png" />
<asp:Label ID="lblCountDown" runat="server" Text="60" Font-Bold="True" Font-Size="50px"
ForeColor="Black"></asp:Label>
</div>
css :
div#OffDiv
{
display: none;
position: fixed;
top: 0px;
right: 0px;
width: 100%;
height: 100%;
padding: 0px;
margin: 0px;
z-index: 90000;
background-color: black;
filter: alpha(opacity=30); /* internet explorer */
-khtml-opacity: 0.3; /* khtml, old safari */
-moz-opacity: 0.3; /* mozilla, netscape */
opacity: 0.3; /* fx, safari, opera */
}
div#TimerContainer
{
display: none;
position: absolute;
width: 110px;
height: 110px;
top: 200px;
left: 50%;
margin-left: -55px;
padding: 0px;
z-index: 90001;
}
#imgWhiteCircle
{
width: 110px;
}
#lblCountDown
{
position: absolute;
width: 70px;
height: 65px;
text-align: center;
top: 50%;
left: 50%;
margin-left: -35px;
margin-top: -32.5px;
}
JavaScript Code :
<script language="javascript" type="text/javascript">
$(function () {
var x = screen.availWidth;
$('div#OffDiv').css({ 'width': x });
var y = screen.availHeight;
$('div#OffDiv').css({ 'height': y });
$('div#OffDiv').css({ 'display': 'block' });
$('div#TimerContainer').css({ 'display': 'block' });
window.open('http://www.MyPoPUp1.com', '_blank', 'channelmode=no,directories=yes,location=no,resizable=yes,titlebar=yes,menubar=no,toolbar=no,scrollbars=yes,status=yes', false);
window.open('http://www.MyPoPUp2.com', '_blank', 'channelmode=no,directories=yes,location=no,resizable=yes,titlebar=yes,menubar=no,toolbar=no,scrollbars=yes,status=yes', false);
window.focus();
var sec = $('#TimerContainer span').text()
var timer = setInterval(function () {
$('#TimerContainer span').text(--sec);
if (sec == 0) {
clearInterval(timer);
$('div#OffDiv').css({ 'display': 'none' });
$('div#TimerContainer').css({ 'display': 'none' });
}
}, 1000);
}); //End Of $(function ()
</script>
as you see there is a countdown timer in parent window (starts from 60 seconds)
during this timer i do not want to let my users to close popup windows.
how can i do that?
or how can i show a message in parent window when user closes one of popup windows?
mean what is the way to make a connection between closing of popup windows and their parent window?
thanks in advance
This way you can get feedback whether the opened popup is closed or not.
var popup = window.open('http://www.google.com');
var timer = setInterval(function () {
if (popup.closed) {
alert('popup closed!');
clearInterval(timer);
}
}, 500);
Regards
The button I created from the JQuery theme builder is too big. How can I resize the button and text while keeping everything in the same proportion? Here is the button CSS:
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
See how all of the dimensions in the CSS are relative sizes? That means you can change the font-size on the element and everything else will get smaller too.
For example, if you have a button element like this (ripped straight from the ThemeRoller page):
<button id="button" class="ui-button ..." and so on>
<span class="ui-button-text">A button element</span>
</button>
then you can increase or decrease its size like this:
<!-- the font size has it! -->
<button id="button" class="ui-button ..." blah blah style="font-size: 1em;">
<span class="ui-button-text">A button element</span>
</button>
One of gridview's column is a "Content" column that can have few lines of text (it can be literal, textbox or label ).
In "default" mode i want it to show only the first line and a link button: "(more)" or "(read)".
Clicking on this link should expand the column and display full content.
What is the best way to do this?
Selecting first 10 characters of content text and using it as your link's text is better aproach. This will reduce size of data that retrieved from database like that :
SELECT ContentId, SUBSTRING(Content, 0, 10) AS Content
FROM ContentTable;
Then you can use template column for this column that includes a label and a link. Lbel for the description text, link for the details.
<asp:TemplateColumn>
<ItemTemplate>
<asp:Label
Text='<%# Eval("Content") %>'
runat="server"/>
<a href='<%# Eval("ContentId", "contentdetails.aspx?id={0}") %>'>More</a>
</ItemTemplate>
</asp:TemplateColumn>
This will help you.
http://www.asp.net/community/control-gallery/Item.aspx?i=1465
try this. http://mosesofegypt.net/post/BuildingjQueryAndASPNetAJAXEnabledControlsjQueryCollapsiblePanelExtenderPart2.aspx
Use the power of CSS!
Place this inside your gridview row. It will naturally push out the row to the height of your content, or the amount of rows required.
<div class="toggle">
<div class="toggle-header">
Toggle!
</div>
<div class="toggle-height">
<div class="toggle-transform">
<p>2nd line of text</p>
<p>3rd line</p>
<p>4th line</p>
<p>etc</p>
</div>
</div>
</div>
And use this CSS...
body {
font-family: sans-serif;
}
.toggle {
position: relative;
border: 2px solid #333;
border-radius: 3px;
margin: 5px;
width: 200px;
}
.toggle-header {
margin: 0;
padding: 10px;
background-color: #333;
color: white;
text-align: center;
cursor: pointer;
}
.toggle-height {
background-color: tomato;
overflow: hidden;
transition: max-height .6s ease;
max-height: 0;
}
.toggle:hover .toggle-height {
max-height: 1000px;
}
.toggle-transform {
padding: 5px;
color: white;
transition: transform .4s ease;
transform: translateY(-100%);
}
.toggle:hover .toggle-transform {
transform: translateY(0);
}
You may want to disguise the "toggle" with a textbox of your "(more)" line to expand the rest.
Let us know if it worked.