Custom web-chat background image - botframework

I am trying to make my own chatbot but am unsure of how to change the background image to my own jpg.
I have tried to place the code in the <body> and inside the styleOptions but none of my methods work.
Below is my html file:
<body style = "background-image: url('CorpBotOrchestrator/Images/whatsapp.jpg');">
<div id="webchat" role="main">Loading...</div>
<script>
styleOptions: {
bubbleFromUserBackground: 'LightBlue',
hideUploadButton: true,
botAvatarImage: 'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0',
//make the speech bubbles round
bubbleBorderRadius: 20,
bubbleFromUserBorderRadius: 20,
}
}, document.getElementById('webchat'));
})().catch(err => console.error(err));
</script>
</body>
Thank you in advance!

You will want to instantiate your web chat in the following way to change the background image of the activities window. Be aware that, in the BotFramework-WebChat styleSet object, there is activity which represents the individual messages, cards, etc., that are sent, and there is activities which represents the window of scrolling messages. It is the latter we will be working with.
Also, be aware, that because you are directly specifying a DOM element and property, albeit via web chat, should some aspect of web chat receive an update that changes the element or property used, this can cause a breaking change for you. Additionally, you will need to pass all the property values necessary as, generally, this strips all default values from the webchat element you are working with.
const styleSet = createStyleSet ( {
bubbleBackground: 'blue',
bubbleFromUserBackground: 'red',
bubbleBorderRadius: 18,
bubbleFromUserBorderRadius: 18,
} );
styleSet.activities = {
...styleSet.activities,
backgroundImage: "url('<someUrlLink>')";
}
window.WebChat.renderWebChat( {
directLine: [...],
styleSet
});
Hope of help!
EDIT
styleOptions can actually be passed in using the spread operator into styleSet. In this way, you can continue to use the ease of styleOptions for customizing and largely remain within best practices of Web Chat.
const styleOptions = {
bubbleBackground: 'blue',
bubbleFromUserBackground: 'red',
bubbleBorderRadius: 18,
bubbleFromUserBorderRadius: 18
}
const styleSet = createStyleSet ( {
...styleOptions,
} );
styleSet.activities = {
...styleSet.activities,
backgroundImage: "url('<someUrlLink>')";
}
window.WebChat.renderWebChat( {
directLine: [...],
styleSet
});

Related

Figma Plugin - help programmatically creating text style

I am trying to create Figma Text styles via a plugin that reads from my design tokens. The problem I am having is when setting the custom font, the promise to load it does not resolve, so it seems to stall the function.
Am I missing something here?
async function createNewTextStyle(token) {
// Style does not yet exist, so create it
const newStyle = figma.createTextStyle();
// the new text style is preloaded with Roboto, so we need to load that
await figma.loadFontAsync(newStyle.fontName);
// This is the font i want to set my text style to.
// it seems that this promise never resolves (or errors).
await figma.loadFontAsync({
family: 'SF Pro Text',
style: 'Regular',
});
// Set the properties of the text style
newStyle.fontName = {
family: 'SF Pro Text',
style: 'Regular',
};
newStyle.name = designToken.name;
newStyle.fontSize = designToken.value;
newStyle.lineHeight = { value: designToken.lineHeight, unit: 'PIXELS' };
}
Hmmm... it looks like you're missing the .then callback that's usually used to handle a promise resolution.
Also, your variable name designToken is not defined in your code, but you're using token (from your function parameters).
Try this in your plugin:
async function createNewTextStyle(token) {
// Style does not yet exist, so create it
const newStyle = figma.createTextStyle();
// the new text style is preloaded with Roboto, so we need to load that
await figma.loadFontAsync(newStyle.fontName);
// This is the font i want to set my text style to.
figma.loadFontAsync({
family: 'SF Pro Text',
style: 'Regular',
}).then(() => {
// Set the properties of the text style
newStyle.fontName = {
family: 'SF Pro Text',
style: 'Regular',
};
newStyle.name = token.name;
newStyle.fontSize = token.value;
newStyle.lineHeight = { value: token.lineHeight, unit: 'PIXELS' };
});
}

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.

Squareup not loading iframes for Waterfox/IE11, Silent Error

I've confirmed that Square's code now works with pages served as application/xhtml+xml and with the exact same code Chrome works though Waterfox (and Firefox) do not load the iframes for the form fields. I've verified this in the DOM (they're not hidden, the original placeholder elements are still there).
Chrome requests the f.js file, Gecko browsers do not.
The placeholder elements that the iframe elements are supposed to replace are still in the DOM.
There are no error messages in the developer consoles in Waterfox 56, Firefox 64, Chrome 71 or Opera 12.1.
I've disabled prototypes for testing.
The browsers yield the same results for local and live testing.
The var sqPaymentForm = new SqPaymentForm(...); object is different for Gecko browsers.
What Gecko has for sqPaymentForm:
_handleDomContentLoaded
clientController
env
errorLogger
options
What Gecko does not have for sqPaymentForm:
build
_handleDomContentLoaded
Ironically I have limited access to IE11. I won't have time to setup the Mac until later on Friday mid-afternoon. Here are a couple cropped screenshots:
Firefox 56
IE 11
Here is the sqPaymentForm object (with obvious basic obfuscation):
var sqPaymentForm = new SqPaymentForm(
{
applicationId: 'sandbox-abc',
locationId: 'CBASEE123',
applePay: {elementId: 'sq-apple-pay'},
callbacks:
{
methodsSupported: function (methods)
{
if (methods.applePay && methods.applePay === true) {var element = document.getElementById('pay-button-area'); element.style.display = 'block';}
},
cardNonceResponseReceived: function(errors, nonce, cardData)
{
if (errors)
{
var errorDiv = document.getElementById('errors');
errorDiv.innerHTML = '';
errors.forEach(function(error) {var p = document.createElement('p'); p.innerHTML = error.message; errorDiv.appendChild(p);});
}
else
{
id_('card-nonce-submit').setAttribute('disabled','true');
id_('card_brand').value = cardData.card_brand;
id_('cc_end').value = cardData.last_4;
id_('cc_month').value = cardData.exp_month;
id_('cc_year').value = cardData.exp_year;
id_('zip').value = cardData.billing_postal_code;
document.getElementById('card-nonce').value = nonce;
payment_submit();
}
},
unsupportedBrowserDetected: function() {console.log('Error: unsupported browser.');},
createPaymentRequest: function ()
{
return {currencyCode: 'USD', countryCode: 'US', requestShippingAddress: false, total: {amount: '1.00', label: 'JAB Creations', pending: false},lineItems: [{amount: '1.00', label: 'Subtotal', pending: false},{amount: '0.00', label: 'Tax', pending: false}]};
},
},
cardNumber: {elementId: 'sq-card-number', placeholder: '0000 0000 0000 0000'},
cvv: {elementId: 'sq-cvv', placeholder: 'CVV'},
env: {},
excludeCanvas: {},
expirationDate: {elementId: 'sq-expiration-date', placeholder: 'MM/YY'},
inputClass: 'sq-input',
inputStyles: [
// Because this object provides no value for mediaMaxWidth or mediaMinWidth, these styles apply for screens of all sizes, unless overridden by another/ input style below.
{
backgroundColor: 'transparent',
color: ($('input[type="text"]').length > 0) ? window.getComputedStyle($('input[type="text"]')[0]).getPropertyValue('color') : '#fff',
fontFamily: 'sans-serif',//localStorage.getItem('input_style_font-family')
fontSize: '18px',//localStorage.getItem('input_style_font-size'),
fontWeight: 'bold',//localStorage.getItem('input_style_font-weight')
lineHeight: '18px',//localStorage.getItem('input_style_line-height'),
padding: '0'
},
// These styles are applied to inputs ONLY when the screen width is 400px
// or smaller. Note that because it doesn't specify a value for padding,
// the padding value in the previous object is preserved.
{
mediaMaxWidth: '400px',
fontSize: '48px',
lineHeight: '18px'
}],
maxTouchPoints: {},
inputEventReceived: function(inputEvent)
{
switch (inputEvent.eventType)
{
case 'focusClassAdded':
// Handle as desired
console.log(document.getElementsByClassName('sq-input--focus')[0]);
break;
case 'focusClassRemoved':
// Handle as desired
console.log(document.getElementsByClassName('sq-input--focus')[0]);
break;
case 'errorClassAdded':
// Handle as desired
break;
case 'errorClassRemoved':
// Handle as desired
break;
case 'cardBrandChanged':
// Handle as desired
break;
case 'postalCodeChanged':
// Handle as desired
break;
}
},
postalCode: {elementId: 'sq-postal-code', placeholder: 'Postal Code'}
});
How do I get the other browsers to load the iframe form fields? This certainly seems like a bug and I'm happy to report back any information that would help with troubleshooting.
Update 1
Running for (i in SqPaymentForm) {console.log('SqPaymentForm.'+i);} reveals the SqPaymentForm object in a different light. The SqPaymentForm.isSupportedBrowser function returns f() (from the only (JavaScript) request from the Square server) however the other browsers return the following:
SqPaymentForm.isSupportedBrowser
()
​length: 0
​name: "bound "
​<prototype>: function ()
I'm focusing my efforts on determining how browsers are "supported" by the convolutedly minimized code from Square.
Update 2
The SqPaymentForm.isSupportedBrowser() function returns true in Chrome and Waterfox. Going off of this documentation (https://docs.connect.squareup.com/payments/sqpaymentform/setup#step-4-render-sqpaymentform) I receive the following error:
paymentForm is not defined.
There is some ambiguity in the troubleshooting I did though after roughly an hour I decided to use setTimeout:
setTimeout(function()
{
sqPaymentForm.build();
sqPaymentForm.recalculateSize();
},2000);
...and it worked. So apparently either the Square developers specifically test with Chrome and/or Chrome will either wait until the method exists and execute it or it's load-related timing is somehow better.
So I would like to now ask: how do I adjust my code to not require having to rely on setTimeout?

How to get a client side editor when working with MVC version of Kendo UI Grid?

Well, I'm really stuck here. This example by Telerik shows how to change a field when editing to whatever you need. Exactly,
columns: [
{ field: "Category", title: "Category", width: "180px", editor: categoryDropDownEditor, template: "#=Category.CategoryName#" },
],
...where "categoryDropDownEditor" is a client side function that does the trick.
In MVC version there seems to be nothing of the kind. Is there? I keep believing that it should. I just do not need to traverse partial HTML from server each time I need to decorate an input field. And this is seemingly what "EditorTemplate", the only one available for MVC, does.
OK. In case anyone will bump into the same. I ended up with this "too elegant" a solution:
.Events(e => e.Edit("editing"))
this line in grid initialization routine (server side) calls the named dynamic method (client side):
function editing(e) {
var input = e.container.find("input[name=Regex]");
var textbox = $(document.createElement('textarea')).attr({
id: input.id,
}).width(input.width()).height(input.height()).val(input.val());
input.hide();
textbox.insertAfter(input);
textbox.focus(function () {
/*to make this flexible, I'm storing the current width & height in an attribute*/
$(this).attr('data-defaultwidth', $(this).width());
$(this).attr('data-defaultheight', $(this).height());
$(this).animate({
width: 400
}, 'slow');
$(this).animate({
height: 300
}, 'slow');
}).blur(function () {
/* lookup the original width */
var w = $(this).attr('data-defaultwidth');
var h = $(this).attr('data-defaultheight');
$(this).animate({
width: w
}, 'slow');
$(this).animate({
height: h
}, 'slow');
input.val(textbox.val());
input.trigger('change');
});
}
End tada, although it's a pure hack.

fullcalendar not showing correctly in laravel 4.2

I'm using Laravel framework and I'm very new to it.
Right now I'm trying to put in the Fullcalendar plugin, which I've done it before in other frameworks (Codeigniter, Play framework) and it worked amazingly.
However in Laravel, it doesn't seem to work like how it suppose to. The calendar doesn't show correctly, the prev and next buttons not show up, and the events not showing.
Please help
Here is my code. I'm using mockup events on the frontend.
$('#schedule').fullCalendar({
header: {
right: '',
center: '',
left: 'prev,next title weekNumber'
},
titleFormat: "D MMMM YYYY [(สัปดาห์ที่ 1 ของ 12)]",
defaultView: 'agendaWeek',
aspectRatio: 1,
events: events,
eventRender: function(event, element) {
var content = '<div class="fc-title">'+event.title+'</div>';
content += '<div class="fc-desc">'+event.description+'</div>'
element.find('.fc-content').html(content);
},
eventMouseover: function(event, jsEvent, view) {
$(this).append('<div class="event-hover"><div class="hover-pointer"></div><div>'+event.hoverContent+'</div></div>')
},
eventMouseout: function( event, jsEvent, view ) {
$('.event-hover').remove();
}
});
I've now found an answer to this.
It's not because of laravel.
I've added the fullcalendar.print.css into it that's why the css was messed up. So I've now removed it and it works perfect.
Thanks anyway for all the help

Resources