Not able to integrate AWS lex with web - amazon-lex

Here is my index.html file. I have required loading lex-web-ui.js and config.js files in script but still getting the error.
The error I am getting is ChatBotUiLoader is not defined
<html>
<head>
<title>My Parent Page</title>
</head>
<body>
<h1>Welcome to my parent page</h1>
<!-- loader script -->
<script src="./dist/lex-web-ui.js"></script>
<script>
/*
The loader library creates a global object named ChatBotUiLoader
It includes the IframeLoader constructor
An instance of IframeLoader has the load function which kicks off
the load process
*/
// options for the loader constructor
var loaderOptions = {
// you can put the chatbot UI config in a JSON file
configUrl: './config.json',
// the full page chatbot UI that will be iframed
iframeSrcPath: './chatbot-index.html#/?lexWebUiEmbed=true'
};
// The following statement instantiates the IframeLoader
var iframeLoader = new ChatBotUiLoader.IframeLoader(loaderOptions);
// chatbot UI config
// The loader can also obtain these values from other sources such
// as a JSON file or events. The configUrl variable in the
// loaderOptions above can be used to put these config values in a file
// instead of explicitly passing it as an argument.
var chatbotUiConfig = {
ui: {
// origin of the parent site where you are including the chatbot UI
// set to window.location.origin since hosting on same site
parentOrigin: window.location.origin,
},
iframe: {
// origin hosting the HTML file that will be embedded in the iframe
// set to window.location.origin since hosting on same site
iframeOrigin: window.location.origin,
},
cognito: {
// Your Cognito Pool Id - this is required to provide AWS credentials
poolId: 'xxx'
},
lex: {
// Lex Bot Name in your account
botName: 'xxx'
}
};
// Call the load function which returns a promise that is resolved
// once the component is loaded or is rejected if there is an error
iframeLoader.load(chatbotUiConfig)
.then(function () {
console.log('iframe loaded');
})
.catch(function (err) {
console.error(err);
});
</script>
</body>
</html>
I am trying to integrate AWS lex on my website. I am using this repo https://github.com/aws-samples/aws-lex-web-ui/tree/master/dist
But getting an error: ChatBotUiLoader is not defined. Can anyone help?
enter image description here

Simply, the error is that an instance of ChatBotUiLoader cannot be created as the library/script containing that object was not found within the scope of the page.
It could be that the demo application is broken but the fix is fairly simple.
You need to include the lex-web-ui-loader.js script file (and its dependencies) in your web page to resolve the issue.

Related

Handle url with .html extension in angular2 router?

We are working on a Angular2(created from angular-cli v1.0.0-beta.28.3) which connects to Salesforce via OAth's User-Agent Flow mechanism(https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_user_agent_oauth_flow.htm).
Here is the authentication code i've used in the code.
Here's the code which handles the callback after Authentication:
import { Component } from '#angular/core';
import { ForceService } from './force';
#Component({
template : ` `,
})
export class AuthComponent {
constructor(force : ForceService) {
var event = new CustomEvent("oauthCallback", {'detail': window.location.href});
window.opener.document.dispatchEvent(event);
window.close();
}
}
In Salesforce, we have something called Connected-App, where we configure the callback urls for the authentication. Callbacks url looks like below:
https://my.site.com/#/auth-callback. Angular2 router configuration uses useHash:true option as well.
Everything is working fine until the new requirement which needs only the callback url to point to something like this:
https://my.site.com/auth-callback.html
So the equivalent html code for above will be :
<html>
<script type="text/javascript">
var event = new CustomEvent("oauthCallback", {'detail': window.location.href});
window.opener.document.dispatchEvent(event);
window.close();
}
</script>
</html>
Problem, we face is after Authenticating, we are not able to access the access_token from the url and close the Authentication Window, since the routing is not properly redirecting to auth-callback.html. All we get is a blank screen with url changed to http://localhost:4200/#/access_token
Is there's a way to solve this issue without turning off useHash ?

Electron app: How do you use ipcRenderer.sendToHost()?

In the Electron documentation for the webview tag, the following example is given to show how to communicate between the renderer process and the web page hosted in the webview:
With sendToHost method and ipc-message event you can easily communicate between guest page and embedder page:
// In embedder page.
const webview = document.getElementById('foo')
webview.addEventListener('ipc-message', (event) => {
console.log(event.channel)
// Prints "pong"
})
webview.send('ping')
// In guest page.
const {ipcRenderer} = require('electron')
ipcRenderer.on('ping', () => {
ipcRenderer.sendToHost('pong')
})
However, in my guest web page (inside the webview), I get Uncaught ReferenceError: require is not defined when I try to require('electron'), as indicated in the docs.
Is there something else I need to do to be able to require the ipcRenderer module from the guest web page?
Electron version: 1.4.6
Note: I'm not sure if this is important or not, but the page running inside my webview is served from a local server. In my top-level page in the renderer process, I do something like: document.getElementById("webview").src = "http://localhost:1234/...";.
Edit: It looks like serving my web page from a local server does not change anything. I have the same error after trying with a static HTML file. It looks like the example in the docs simply doesn't work, or I'm understanding it wrong.
// Simple foo.html somewhere on my computer
<script>
const {ipcRenderer} = require('electron')
ipcRenderer.on('ping', () => {
ipcRenderer.sendToHost('pong')
})
</script>
// In embedder page, in renderer process
document.getElementById("webview").src = "file://path/to/foo.html";
Output from the embedded page (inside the webview):
Uncaught ReferenceError: require is not defined
EDIT
For security reasons, the preferred way to use require in renderer processes is to use preload to inject only the minimum node integration your page requires. See point 2) of Electron's security recommendations. A minimal example for ipcRenderer:
// main.ts
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
preload: './preload.js'
}
})
mainWindow.loadURL('https://my-website.com')
// preload.js
const { ipcRenderer } = require('electron')
window.sendToElectron= function (channel) {
ipcRenderer.send(channel)
}
In your webpage you can now use window.sendToElectron("ping").
If you're using <webview> inside the renderer process, you can use <webview src="page.html" preload="./preload.js" /> to achieve the same result. So, that's what I would use to answer my original question, and inside preload.js I would inject a function that calls ipcRenderer.sendToHost("pong") in the global window.
Old answer (bad for security)
I had missed a vital point in the webview docs. To be able to call require from the page embedded inside the webview, you need to set the nodeintegration attribute on the webview tag:
<webview id="webview" nodeintegration />

Ajax request not fired form partial page when the main page also has an ajax request

In my _layout.cshtml I have a partial view that includes js trough requirejs.
<script data-main="/Scripts/Search" src="/Scripts/require.js"></script>
In this js file I use the following to populate a knockout vm.
$.getJSON("/Search/Index", function (data) {
self.availableCities(data.AvailableCities);
});
This works well on all pages except when my main view also has an ajax request.
<script data-main="/Scripts/Index" src="/Scripts/require.js"></script>
$.getJSON("/Property/All", function (data) {
self.properties(data);
});
Here is my require config, it is the same for the partial and the main view.
require.config({
baseUrl: "/Scripts",
paths: {
"text": "text",
"knockout": "knockout-3.3.0",
"jquery": "jquery-2.1.3.min"
},
shim: {
"jquery": { exports: "$" }
}
});
When the main page has an ajax request only this request is fired, I am not sure how to fix this. It looks like a configuration issue, tested it in both Firefox an Chrome so it does not appear to be browser specific.
It turns out having multiple <script data-main="/Scripts/Search" src="/Scripts/require.js"></script> tags in one page isn't such a bright idea.
I figured it out after some more research,
this question has a good solution if you run into a similar problem.
Basically you need one 'main.js' file and add the other page components via the require logic.
Edit:
Doing this may result in the following knockout error:
Error: You cannot apply bindings multiple times to the same element.
To fix this I have used the following binding handler:
ko.bindingHandlers.stopBinding = {
init: function () {
return { controlsDescendantBindings: true };
}
};
To enable this binding handler on containerless elements use the following:
ko.virtualElements.allowedBindings.stopBinding = true;
Apply the following binding around the partial view. To prevent the main-page from binding to the elements in the partial.
<!-- ko stopBinding: true-->
<!-- /ko -->
Finally use ko.applyBinings on the partialview like this:
ko.applyBindings(new partialViewModel(), document.getElementById("your-partial"));

Insert a liferay portlet into PrimeFaces dialog

I'm using liferay 6.1, jsf 2 and primeface 4.0. I've two different project running on a liferay tomcat. I want to insert a portlet of "Project 1" into primefaces dialog of "project 2".
I tried by using ui:insert, but it takes the source path of current project. How to proceed in this scenario?
with ui:insert, you can insert html code, not a whole portlet!
So you should either:
Create a common xhtml page that could be visible from both portlets. This would require that you have both portlets in the same plugin project
In the dialog, instead of inserting code, you can include a link to another page of your portal, where a "project2" portlet is placed
I'm managed to fixed that issue.
Liferay provides a generate URL functionality of each portlet. So I created a URL for target portlet.
then pass that url to liferay pop up.
Here is my code :
<script type="text/javascript" charset="utf-8">
var url;
function createRenderURL() {
AUI().ready('liferay-portlet-url', function(A) {
var renderURL = Liferay.PortletURL.createRenderURL();
renderURL.setName("Banner");
renderURL .setPortletMode("view");
renderURL .setWindowState("pop_up");
renderURL.setPortletId("addUser_WAR_UserManagementportlet");
url = renderURL.toString();
showPopup(url);
});
}
function showPopup(url){
console.log("En el showPopup ");
AUI().ready('aui-dialog', 'aui-io', function(A) {
alert(url);
window.myDialog = new A.Dialog({
title: 'Banner',
width: 640,
centered: true
}).plug(A.Plugin.IO, {
uri: url
}).render();
});
}
Hope it will help to another. Thanks.

using SignalR with document onload instead of jquery onload

I have used the signalR chat app (as laid out in this tutorial http://sergiotapia.com/2011/09/signalr-with-mvc3-chat-app-build-asynchronous-real-time-persistant-connection-websites/) in a standalone test site and it all works great.
I'm now trying to incorporate it into my larger project.
Now unfortunately my larger project has a body onload function defined, so i don't use the standard jquery $(function () {}); syntax for executing stuff on page load. This hasn't been too much of an issue so far, most jquery plugins and scripts get executed in the function called by my body onload and its fine.
But for some reason, my signalR code just isn't executing.
Its the exact same code as laid out above, only its called on my body load.
The page loads, does a post to /signalr/negotiate (which returns the url and clientID)
In my sample app which works, it then does a continuous post to /signalr/connect
In my other app, it simply does a single get to the page im currently on.
Its not making the post to connect.
Is there a way to manually call this?
Here is the source of the page not working.
Please note that the reason im not referencing JQuery itself is because its loaded in my master page. JQuery is present.
<script src="/public/javascript/jquery.signalR.min.js">
<script src="/public/javascript/json2.js">
<script type="text/javascript" src="/signalr/hubs">
<div>
<input type="text" id="msg" />
<input type="button" id="broadcast" />
<ul id="messages"></ul>
</div>
<script type="text/javascript">
function ExecuteOnLoad() {
// Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) {
$('#messages').append('<li>' + message + '</li>');
};
$("#broadcast").click(function () {
// Call the chat method on the server
chat.send($('#msg').val());
});
// Start the connection
$.connection.hub.start();
}
</script>
EDIT : here is the chat hub
public class Chat : SignalR.Hubs.Hub
{
public void Send(string message)
{
//Call the addMessage method on all clients.
Clients.addMessage(message);
}
}
DOUBLE EDIT : ok, i've made a standard html page in my mvc project and wired up the onload event again and everything works fine. the problem seems to be that polling doesn't seem to working when i call
$.connection.hub.start();
instead its doing a get to the current url and returning the page again in the get request.
The problem had nothing to do with the question I asked.
I thought it might have to do with the onload function, but it did not.
The problem was because my page had a reference to the Jquery.Validate plugin.
The version I was using was 1.7, I updated to 1.9 of the plugin and it worked fine.

Resources