Directline with Polyfill ES5 in IE - javascript

I am currently having an issue with the botchat framework from Microsoft.
In essence, they are saying that for the framework to work in I.E., all you have to do is change the script for their webchat-es5.js version. However, this still does not work at all in IE. I am using IE 11. All other browsers work fine, except IE.
Could someone please point me in the right direction so that I may have this ChatBot actually work in IE?
Here is the code I am using for all of this stuff:
Relevant HTML:
<div id="webchat" role="main" style="position: absolutel bottom:0; left:0; width:100%; height:100%;"></div>
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat-es5.js"></script>
Relevant JavaScript:
const styleOptions =
{
accent: '#0063B1',
backgroundColor: 'White; border:2px solid #23447e; border-radius: 25px; padding-top:20px',
cardEmphasisBackgroundColor: '#F0F0F0',
paddingRegular: 10,
paddingWide: 10 * 2,
subtle: '#767676',
bubbleBackground: '#CCCCCC',
bubbleBorder: 'solid 1px #E6E6E6',
bubbleBorderRadius: 10,
bubbleFromUserBackground: '#0084ff',
bubbleFromUserBorder: 'solid 1px #E6E6E6',
bubbleFromUserBorderRadius: 10,
bubbleFromUserTextColor: 'White',
bubbleImageHeight: 100, //240,
bubbleMaxWidth: 480, // screen width = 600px
bubbleMinHeight: 40,
bubbleMinWidth: 250, // min screen width = 300px, Edge requires 372px (https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13621468/)
bubbleTextColor: 'Black',
// Send box
hideSendBox: false,
hideUploadButton: false,
microphoneButtonColorOnDictate: '#F33',
sendBoxBackground: 'White',
sendBoxButtonColor: '#767676',
sendBoxButtonColorOnDisabled: '#CCC',
sendBoxButtonColorOnFocus: '#333',
sendBoxButtonColorOnHover: '#333',
sendBoxHeight: 40,
sendBoxMaxHeight: 200,
sendBoxTextColor: 'Black',
sendBoxBorderBottom: '',
sendBoxBorderLeft: '2px solid #23447e; border-radius: 25px',
sendBoxBorderRight: '2px solid #23447e; border-radius: 25px',
sendBoxBorderTop: '2px solid #23447e; border-radius: 25px',
sendBoxPlaceholderColor: '#23447e',
sendBoxTextWrap: false,
typingAnimationBackgroundImage: 'https://support.signal.org/hc/article_attachments/360016877511/typing-animation-3x.gif',
spinnerAnimationBackgroundImage: 'https://support.signal.org/hc/article_attachments/360016877511/typing-animation-3x.gif',
avatarSize: 80,
botAvatarImage: 'https://s3.gifyu.com/images/oie_3BXuLVEkv2Ad.gif',
userAvatarImage: 'https://i.ibb.co/5xz4X4P/kissclipart-generic-person-icon-clipart-computer-icons-person-96a092499db1d0d3.png',
botAvatarInitials: '',
userAvatarInitials: ''
};
const token = 'MY TOKEN SECRET IS HERE';
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
value: { language: window.navigator.language }
}
});
}
return next(action);
});
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
styleOptions
}, document.getElementById("webchat"));
I've also tried their other version of rendering/creating the webchat :
window.fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' })
.then(function (res) {
return res.json();
})
.then(function (json) {
const token = json.token;
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({
token: token
})
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
});
With this instantiated version, it still doesn't work in IE, and in other browsers, it loads the MockBot from GitHub instead of my own chatbot.

Arrow functions in IE11 are not supported, so you store middleware is causing the problem. Take a look at the code snippet below.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Full-featured bundle with ES5 polyfills</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--
This CDN points to the latest official release of Web Chat. If you need to test against Web Chat's latest bits, please refer to pointing to Web Chat's MyGet feed:
https://github.com/microsoft/BotFramework-WebChat#how-to-test-with-web-chats-latest-bits
-->
<script src="https://cdn.botframework.com/botframework-webchat/latest/webchat-es5.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>
// This code is modified to run in browser without async and Promise support
window.fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' })
.then(function (res) {
return res.json();
})
.then(function (json) {
const token = json.token;
const store = window.WebChat.createStore(
{},
function(store) {
return function(next) {
return function(action) {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
store.dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
value: { language: window.navigator.language }
}
});
}
return next(action);
}
}
}
);
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({
token: token
}),
store: store
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
});
</script>
</body>
</html>
Hope this helps!

Related

Displaying image component from inside a list. How do you do this?

I hope you could help me out.
Before going through the code, let me quickly explain what I want:
I have two components that I use for uploading and displaying images. I have FileResourceService that is used for uploading, and FileResourceImage which is used for storing and displaying the data. These work together with a v-model called profilePictureFileResourceId which basically just ties the images to specific users on the page, depending on who is logged on.
When displaying the image on a template, it is very straightforward. I just grab the FileResourceImage component and tie it with the v-model.
<file-resource-image v-model="form.user.profilePictureFileResourceId" can-upload style="width: 100px; height: 100px;" />
That is all very easy, but I have some pages where I use tables that contain information about my users, and I would like for the user’s profile images to actually be displayed in the table. Here is an example of a list used for the table.
fields() {
return [
{
key: "email",
label: this.$t('email'),
sortable: true,
template: {type: 'email'}
},
{
key: "name",
label: this.$t('name'),
sortable: true
},
{
key: 'type',
label: this.$t('type'),
formatter: type => this.$t(`model.user.types.${type}`),
sortable: true,
sortByFormatted: true,
filterByFormatted: true
},
{
key: 'status',
label: this.$t('status'),
formatter: type => this.$t(`model.user.status.${type}`),
sortable: true,
sortByFormatted: true,
filterByFormatted: true
},
{
key: "actions",
template: {
type: 'actions',
head: [
{
icon: 'fa-plus',
text: 'createUser',
placement: 'left',
to: `/users/add`,
if: () => this.$refs.areaAuthorizer.fullControl
}
],
cell: [
{
icon: 'fa-edit',
to: data => `/users/${data.item.id}/edit`
}
]
}
I know that I cannot just make an array that looks like this:
fields() {
return [
{
<file-resource-image v-model="form.user.profilePictureFileResourceId" can-upload />
}
]
}
So how would you make the component display from within in the list? I believe it can be done with props, but I am totally lost at what to do.
By the way, these are the two components I use for uploading and display. I thought I might as well show them, so you can get an idea of what they do.
For upload:
import axios from '#/config/axios';
import utils from '#/utils/utils';
export const fileResourceService = {
getFileResource(fileResourceId) {
return axios.get(`file/${fileResourceId}`);
},
getFileResourceFileContent(fileResourceId) {
return axios.get(`file/${fileResourceId}/download`, {responseType: 'arraybuffer', timeout: 0});
},
downloadFileResource(fileResourceId) {
return fileResourceService.getPublicDownloadToken(fileResourceId)
.then(result => fileResourceService.downloadPublicTokenFile(result.data));
},
downloadPublicTokenFile(fileResourcePublicDownloadTokenId) {
const tempLink = document.createElement('a');
tempLink.style.display = 'none';
tempLink.href =
`${axios.defaults.baseURL}/file/public/${fileResourcePublicDownloadTokenId}/download`;
tempLink.setAttribute('download', '');
document.body.appendChild(tempLink);
tempLink.click();
setTimeout(() => document.body.removeChild(tempLink), 0);
},
getPublicDownloadToken(fileResourceId) {
return axios.get(`file/${fileResourceId}/public-download-token`);
},
postFileResource(fileResource, file) {
return axios.post(`file`, utils.toFormData([
{name: 'fileResource', type: 'json', data: fileResource},
{name: 'file', data: file}
]), {timeout: 0});
}
};
Then we have the component that is used for DISPLAYING the images:
<template>
<div :style="style" #click="upload" style="cursor: pointer;">
<div v-if="url === null">
<i class="fas fa-camera"></i>
</div>
<div v-if="canUpload" class="overlay">
<i class="fas fa-images"></i>
</div>
</div>
</template>
<script>
import {fileResourceService} from '#/services/file-resource';
import utils from '#/utils/utils';
export default {
model: {
prop: 'fileResourceId',
event: 'update:fileResourceId'
},
props: {
fileResourceId: String,
canUpload: Boolean,
defaultIcon: {
type: String,
default: 'fas fa-camera'
}
},
data() {
return {
url: null
};
},
computed: {
style() {
return {
backgroundImage: this.url && `url(${this.url})`,
backgroundSize: 'contain',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat'
};
}
},
methods: {
upload() {
if(this.canUpload) {
utils.openFileDialog()
.then(([file]) => fileResourceService.postFileResource({}, file))
.then(result => this.$emit('update:fileResourceId', result.data.id))
.catch(() => this.$bvModalExt.msgBoxError())
}
}
},
watch: {
fileResourceId: {
immediate: true,
handler() {
this.url = null;
if (this.fileResourceId) {
fileResourceService.getFileResourceFileContent(this.fileResourceId).then(result => {
const reader = new FileReader();
reader.onload = event => this.url = event.target.result;
reader.readAsDataURL(new Blob([result.data]));
});
}
}
}
}
};
</script>

Apexcharts not being styled correctly

I came across this issue when I wanted to center a Apexchart on my site.
I first tried flexbox with gave me an error as soon as I stated something like
flex-direction: row;
Error:
apexcharts attribute height: A negative value is not valid
When searching for this error I got the hint, that it could be about how I include the different files, but I can't find the correct way of doing this.
This is what my files look right now.
index.html:
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="/styles.css" />
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script data-main="/script.js" src="/require.js"></script>
<div class="piecontainer">
<div class="piewrapper">
<div class="piebox">
<div id="piecharttotal"></div>
</div>
</div>
</div>
script.js:
async function getSources(mode) {
let url = 'http://192.168.2.131:81/sources/?mode=' +mode ;
try {
let res = await fetch(url);
return await res.json();
} catch (error) {
console.log(error);
}
}
async function renderSources(mode, objectid) {
datasets = await getSources(mode);
var jsonset2 = [];
var jsoncat2 = [];
datasets.forEach(datas => {
jsonset2.push(datas[1]);
jsoncat2.push(datas[0]);
});
var optionspie = {
labels: jsoncat2,
chart: {
type: 'donut',
width: '30%',
stacked : false,
},
colors: ["#45CB85","#FB5607","#35A7FF","#FF1AFF","#FFAF54"],
series: jsonset2,
chartOptions: {
labels: jsoncat2
},
plotOptions: {
pie: {
donut: {
labels: {
show: true,
name: {
show: true,
},
value: {
show:true
},
total: {
show: true,
label: "Total"
}
}
}
}
}
}
var chart = new ApexCharts(document.querySelector(objectid), optionspie);
chart.render();
}
renderSources("total","#piecharttotal");
Nothing else I included. When I change the id-tag of #piecharttotal and put some text in the div, the text is perfectly in the middle, however if I dont, the chart is just on the left site (presumably without any styles)
Edit:
styles.css:
.piecontainer{
width: 100%;
height: 800px;
text-align: center;
background-color: #009879;
}
.piewrapper{
position: relative;
top:50%;
transform: translateY(-50%);
background-color: #82D173;
}

calling parent function from cellrenderer like emit on vuejs ag-grid-vue

i have implemented the ag-grid-vue on my project now i have a seperate component on one of the columns which is basically Actions , now the user can either edit view or delete depending on the selection, now for edit and delete it works just fine, the problem is when i am deleting a record i want the table to be re-rendered by fetching the updated data from the Api, for that i need to call some method in the parent, from the CellRenderer Component, let me show you the code
HTML
<ag-grid-vue
ref="agGridTable"
:components="components"
:gridOptions="gridOptions"
class="ag-theme-material w-100 my-4 ag-grid-table"
:columnDefs="columnDefs"
:defaultColDef="defaultColDef"
:rowData="accounts"
rowSelection="multiple"
colResizeDefault="shift"
:animateRows="true"
:floatingFilter="true"
:pagination="true"
:paginationPageSize="paginationPageSize"
:suppressPaginationPanel="true"
:enableRtl="$vs.rtl">
</ag-grid-vue>
JS
import CellRendererActions from "./CellRendererActions.vue"
components: {
AgGridVue,
vSelect,
CellRendererActions,
},
columnDefs: [
{
headerName: 'Account ID',
field: '0',
filter: true,
width: 225,
pinned: 'left'
},{
headerName: 'Account Name',
field: '1',
width: 250,
filter: true,
},
{
headerName: 'Upcoming Renewal Date',
field: '2',
filter: true,
width: 250,
},
{
headerName: 'Business Unit Name',
field: '3',
filter: true,
width: 200,
},
{
headerName: 'Account Producer',
field: '4',
filter: true,
width: 200,
},
{
headerName: 'Actions',
field: 'transactions',
width: 150,
cellRendererFramework: 'CellRendererActions',
},
],
components: {
CellRendererActions,
}
CellRenderer Component
<template>
<div :style="{'direction': $vs.rtl ? 'rtl' : 'ltr'}">
<feather-icon icon="Edit3Icon" svgClasses="h-5 w-5 mr-4 hover:text-primary cursor-pointer" #click="editRecord" />
<feather-icon icon="EyeIcon" svgClasses="h-5 w-5 mr-4 hover:text-danger cursor-pointer" #click="viewRecord" />
<feather-icon icon="Trash2Icon" svgClasses="h-5 w-5 hover:text-danger cursor-pointer" #click="confirmDeleteRecord" />
</div>
</template>
<script>
import { Auth } from "aws-amplify";
import { API } from "aws-amplify";
export default {
name: 'CellRendererActions',
methods: {
async deleteAccount(accountId) {
const apiName = "hidden";
const path = "/hidden?id="+accountId;
const myInit = {
headers: {
Authorization: `Bearer ${(await Auth.currentSession())
.getIdToken()
.getJwtToken()}`
}
};
return await API.get(apiName, path, myInit);
},
viewRecord(){
this.$router.push("/accounts/" + this.params.data[0]).catch(() => {})
},
editRecord() {
// console.log(this.params.data);
this.$router.push("hidden" + this.params.data[0]).catch(() => {})
/*
Below line will be for actual product
Currently it's commented due to demo purpose - Above url is for demo purpose
this.$router.push("hidden" + this.params.data.id).catch(() => {})
*/
},
confirmDeleteRecord() {
this.$vs.dialog({
type: 'confirm',
color: 'danger',
title: `Confirm Delete`,
text: `You are about to delete "${this.params.data[1]}"`,
accept: this.deleteRecord,
acceptText: "Delete"
})
},
deleteRecord() {
/* Below two lines are just for demo purpose */
this.$vs.loading({ color: this.colorLoading });
this.deleteAccount(this.params.data[0]).then(() => {
this.$vs.loading.close();
this.showDeleteSuccess()
});
/* UnComment below lines for enabling true flow if deleting user */
// this.$store.dispatch("userManagement/removeRecord", this.params.data.id)
// .then(() => { this.showDeleteSuccess() })
// .catch(err => { console.error(err) })
},
showDeleteSuccess() {
this.$vs.notify({
color: 'success',
title: 'User Deleted',
text: 'The selected user was successfully deleted'
})
}
}
}
</script>
now the component above is where i need to make the changes, i tried to use the reqgular vuejs emit and on but that didnt work any help?
2 ways to solve this -
1. cellRendererParams approach
You can use cellRendererParams like this -
cellRendererParams : {
action : this.doSomeAction.bind(this); // this is your parent component function
}
Now in your cell renderer component you can invoke this action
this.params.action(); // this should correspond to the object key in cellRendererParam
2. Using context gridOption
There is another way to solve this as described in this example
You basically setup context in your main grid component like this -
:context="context" (in template)
this.context = { componentParent: this };
Then in your component you can call parent component like this -
invokeParentMethod() {
this.params.context.componentParent.methodFromParent(
`Row: ${this.params.node.rowIndex}, Col: ${this.params.colDef.headerName}`
);
}
In my case #click event is being removed automatically.
Am I missing something?
<button #click="editRecord" >Click Me</button>
Actual Output:
<button >Click Me</button>

Microsoft Bot Framework speech recognition webchat integration

I have a problem with speech recognition integration into webchat. This is the code I use. It´s just the same code like here: https://github.com/microsoft/BotFramework-WebChat/blob/master/SPEECH.md#integrating-web-chat-into-your-page
But I always get the error: Uncaught SyntaxError: Unexpected identifier at line...
and line of error is: webSpeechPonyfillFactory: await createSpeechRecognitionOnlyPonyfillFactory({
Without speech recognition it´s all working. Do you have some idea?
const { createCognitiveServicesSpeechServicesPonyfillFactory, createDirectLine, renderWebChat } = window.WebChat;
const styleOptions = {
botAvatarInitials: 'Bot',
userAvatarInitials: 'You'
};
renderWebChat(
{
directLine: createDirectLine({
secret: 'FFFFFFFFFFFFFFFF'
}),
language: 'de-DE',
webSpeechPonyfillFactory: await createSpeechRecognitionOnlyPonyfillFactory({
region: 'westeurope',
subscriptionKey: 'FFFFFFFFFFFFFFFFFFFFFF'
}),
styleOptions
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
Try this :
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Cognitive Services Speech Services using JavaScript</title>
<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>
(async function () {
const styleOptions = {
botAvatarInitials: 'Bot',
userAvatarInitials: 'You'
};
window.WebChat.renderWebChat({
directLine: createDirectLine({
secret: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
}),
language: 'de-DE',
webSpeechPonyfillFactory: await createCognitiveServicesSpeechServicesPonyfillFactory({
region: 'westeurope',
subscriptionKey: 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
}),
styleOptions
}, document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>

Publisher div not showing in opentok cordova plugin in Ionic 3

I have implemented opentok cordova plugin inside my Ionic 3 app, I am able to make a video call and in one of my devices i can see the picture in picture style view which shows both the Divs but in my other device i am able to see only one div which has the video of the counterpart, I cannot see the div which has the video stream of the front camera.
Below is my code -
startVideoCall = (sessionData?: any) => {
this.callStarted = true;
this.sessionId = sessionData.sessionId;
this.token = sessionData.token;
var publisherOptions = {
insertMode: 'append',
showControls: true,
style: {
buttonDisplayMode: "on",
nameDisplayMode: "on",
},
width: 100,
height: 150
};
var subscriberOptions = {
insertMode: 'append',
insertDefaultUI: true,
showControls: true,
style: {
buttonDisplayMode: "on",
nameDisplayMode: "on",
},
width: this.platform.width(),
height: (this.platform.height() - 40)
};
this.session = OT.initSession(this.apiKey, this.sessionId);
this.publisher = OT.initPublisher('publisher', publisherOptions);
if (this.session && this.publisher) {
this.session.on({
streamCreated: (event: any) => {
this.callConnected = true;
this.subscriberObj = this.session.subscribe(event.stream, 'subscriber', subscriberOptions);
console.log("subscriberObj==================>", this.subscriberObj);
OT.updateViews();
},
streamDestroyed: (event: any) => {
console.log(`Stream ${event.stream.name} ended because ${event.reason}`);
this.session.disconnect();
OT.updateViews();
this.navCtrl.pop();
},
sessionConnected: (event: any) => {
console.log("sessionConnected " + event + "his.publisher==>", this.publisher);
if (!sessionData.isSubscriber) {
let player_ids = [];
player_ids.push(sessionData.userDetails.lastLoginDeviceToken);
this.oneSignal.sendNotification(player_ids, "Incoming Call", sessionData);
}
this.session.publish(this.publisher);
},
sessionDisconnected: (event: any) => {
console.log("The session disconnected. " + event.reason);
this.session.disconnect();
this.navCtrl.pop();
},
});
this.session.connect(this.token, (error: any) => {
if (error) {
console.log(`There was an error connecting to the session ${error}`);
}
});
}
}
Following is my HTML
<ion-content padding style="background-color: black;">
<div *ngIf="callStarted">
<div id="subscriber">
</div>
<div id="publisher">
</div>
</div>
<div>
<h4 *ngIf="!callConnected && !isIncomingCall" class="connecting-text">Connecting...</h4>
</div>
<div>
<h4 *ngIf="isIncomingCall" class="connecting-text">Incoming call</h4>
</div>
</ion-content>
<ion-footer class="controls-icon" *ngIf="showAcceptRejectButtons">
<ion-icon class="accept-circle-icon rippleEffect" (click)="acceptButtonCall()"></ion-icon>
<ion-icon class="reject-circle-icon rippleEffect" (click)="rejectButtonCall()"></ion-icon>
</ion-footer>
I can't get it working as i have found no documentations as such. I want to show both divs on both the device.

Categories

Resources