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.
I have a GridView in a div on my HTML-Code like this:
<div class="container" style="width: 80%; height: 800px; overflow: scroll">
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" PageSize="40" AllowSorting="True"
AutoGenerateSelectButton="True" EnableModelValidation="False" OnPageIndexChanging="GridView1_SelectedIndexChanged"
AutoGenerateColumns="false" OnSorting="GridView1_Sorting" CssClass="mydatagrid"
PagerStyle-CssClass="pager" HeaderStyle-CssClass="headerGrida1" RowStyle-CssClass="rows"
ShowHeaderWhenEmpty="true" Font-Size="X-Small" ForeColor="Black">
The div makes it already scrollable but I also need a fixed Header of the Grid. What I tried with CSS doesnt work out...
I tried thi for the container:
.container
{
overflow: scroll;
}
.container table th
{
position: relative;
}
.container table tbody
{
overflow: hidden;
}
</style>
And this with the Gird:
.headerGrida1
{
background-color: #4a708b;
font-family: Calibri;
color: White;
border: none 0px transparent;
height: 25px;
text-align: center;
font-size: 16px;
position: relative;
}
But nothing seems to work...
Below is the good solution that will fixed header with vertical and horizontal scroll bars
http://www.dotnetbull.com/2011/11/scrollable-gridview-with-fixed-headers.html
Isn't there a way to do t just with CSS?
That's what I get when switching Position=absolute or = fixed.
The only thing is that it has to be above the first row otherwise nobody would see the rwos anymore.
Maybe there is simple solution, too?
Another Problem is that he width of the header is now different to the columns
I've an aspx page and I want to disable that page dynamically on a IF condition.
Here, By the word 'Disable' I mean an exactly same condition when a pop-up or a Radwindow opens and the Parent page gets disabled and the user is not able to do anything to the parent page until the pop-up gets closed.
For Ajax or Rad Controls, I can set the 'Modal' attribute of the control to true to make Parent page disabled. But what to do for my required condition.
Any suggestion would be appreciated.
You achieve the disabled effect by adding a div that covers the page using Javascript or JQuery.
var documentHeight = $(document).height();
$("body").append("<div style='z-index: 100; background: lightgray; opacity: 0.5; width: 100%; height: " + documentHeight + "px; position: absolute; left: 0; top: 0;'></div>");
The caveat is that this isn't "secure", if that's what you're after (the user could "hack" the disabling pane using Firebug or similar).
You can use ModalPopupExtender, take a look at my sample. I use this concept in all my sites and works great for all types of browsers.
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="ConfirmDialogUserControl.ascx.cs"
Inherits="GP.Solutions.UserControls.ConfirmDialogUserControl" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<script type="text/javascript">
var _source;
var _popup;
function ShowConfirmDialog(source, message) {
this._source = source;
this._popup = $find('mdlPopup');
var displayDiv = document.getElementById('<%= ConfirmMessageDiv.ClientID %>');
displayDiv.innerText = message;
displayDiv.textContent = message;
this._popup.show();
}
function ConfirmDialogOk() {
this._popup.hide();
__doPostBack(this._source.name, '');
}
function ConfirmDialogCancel() {
this._popup.hide();
this._source = null;
this._popup = null;
}
</script>
<asp:Panel ID="pnlModal" runat="server" CssClass="modalPopup" style="display:none;">
<div class="modalHeader">
<div id="DivImage" runat="server"> </div>
<asp:Label ID="TitleLabel" runat="server" Text="" CssClass="modalTitle"></asp:Label>
</div>
<asp:Panel ID="pnlControls" runat="server" CssClass="modalContent">
<div id="ConfirmMessageDiv" runat="server"></div>
</asp:Panel>
<div class="modalControlsContainer">
<asp:Button ID="btnConfirmDialogOk" runat="server" CssClass="modalButton" Text="" />
<asp:Button ID="btnConfirmDialogCancel" runat="server" CssClass="modalButton" Text="" />
</div>
</asp:Panel>
<asp:ModalPopupExtender ID="ModalPopupExtender1" behaviorid="mdlPopup" runat="server" TargetControlID="pnlModal"
PopupControlID="pnlModal" OkControlID="btnConfirmDialogOk" OnOkScript="ConfirmDialogOk();" CancelControlID="btnConfirmDialogCancel"
OnCancelScript="ConfirmDialogCancel();" DynamicServicePath="" Enabled="True" BackgroundCssClass="modalBackground" DropShadow="true">
</asp:ModalPopupExtender>
Here is css code used in this case:
.modalBackground
{
background-color:Black;
filter:alpha(opacity=60);
opacity:0.6;
}
.modalPopup
{
background-color:White;
border: 1px solid green;
width:280px;
padding: 10px 10px 10px 10px;
}
.modalPopupFullWidth
{
background-color:White;
border: 1px solid green;
padding: 10px 10px 10px 10px;
}
.modalHeader
{
width:auto;
border: 1px solid silver;
height:25px;
background-color:#F2F2F2;
}
.modalTitle
{
color:Black;
font-size: 11px;
font-weight:bold;
position:relative;
left:30px;
top:-20px;
}
.modalImageInformation
{
background-image: url('information.png');
background-repeat: no-repeat;
width:26px;
height:26px;
border: 0;
}
.modalImageWarning
{
background-image: url('warning.png');
background-repeat: no-repeat;
width:26px;
height:26px;
border: 0;
}
.modalImageError
{
background-image: url('error.png');
background-repeat: no-repeat;
width:26px;
height:26px;
border: 0;
}
.modalImageQuestion
{
background-image: url('question.png');
background-repeat: no-repeat;
width:26px;
height:26px;
}
.modalImageSearch
{
background-image: url('search.png');
background-repeat: no-repeat;
width:26px;
height:26px;
}
.modalContent
{
padding-top:10px;
padding-bottom:0px;
}
.modalControlsContainer
{
margin-left:auto;
margin-right:auto;
text-align:center;
padding-top:5px;
}
.modalButton
{
background-image: url('button-113x28.png');
background-color:transparent;
width:113px;
height:28px;
border: 0px none transparent;
color: White;
font-size:11px;
cursor:pointer;
margin-top:10px;
margin-left:auto;
margin-right:auto;
text-align:center;
}
.hidden { display: none; }
.unhidden { display: block; }
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.