Alert when code is running background in google sheet - google-sheets

Working with Google App script and Javascript, I managed to retrieve xls Gmail attachments, convert it to google sheets, send an warning email to some recipients, insert an event with the Google Drive folder link when a new attachment is added to it, and at the end I managed with a standalone script to import some of the data coming from such xls file converted to a main Google Sheet where one operator is working h24 ( updating some data to be forwarded later on and during the service itself).
The standalone script run every 30 minutes to check incoming mail ( the schedule for the next day or days), and when it find it, it execute the code.
The lock service is not available on standalone scripts up to now, so I cannot lock the document, so I wish to display a message to the user that the script is about to run and not edit anything, since other scripts bounded to the Spreadsheet are using the Lock service, and so the result could be quite disappointing. I searched info regarding this "alert", but I cannot find a clue about it.
Could you address me somewhere?
I could add a menu function instead of a standalone script, and the operator could select "Import data" and that's it, but I wish to automate the operation in background.

You could use the HTML Service. I don't know much about it myself but I think the following may do what you need:
At the top of you .gs file:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var htmlApp = HtmlService.createTemplateFromFile("html");
var status = "Loading....."
htmlApp.data = status;
ss.show(htmlApp.evaluate()
.setWidth(300)
.setHeight(200));
At the end (just before the last brace):
var status = "Finished!"
htmlApp.data = status;
ss.show(htmlApp.evaluate()
.setWidth(300)
.setHeight(200));
In a new HTML script file named 'html':
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h2>Updating..</h2>
<p id="status">(innerHTML).</p>
<div id="imageico"></div>
<script>
var imageContainer = document.getElementById("imageico");
if (<?= data ?> != "Finished!"){
document.getElementById("status").innerHTML = "Running script, please wait..";
} else {
document.getElementById("status").innerHTML = "Finished! You can now close the window.";
closeBtn();
}
function closeBtn(){
var button = document.createElement("INPUT");
button.setAttribute("type", "button");
button.setAttribute("value", "Close");
button.setAttribute("onclick", "closeWindow();");
imageContainer.appendChild(button);
}
function closeWindow(){
google.script.host.close();
}
</script>
</body>
</html>
EDITED Based on comments
In your .gs file:
function test() {
htmlApp("","");
/*
*
* Put your code in here....
*
*/
Utilities.sleep(3000); // change this value to show the "Running script, please wait.." HTML window for longer time.
htmlApp("Finished!","");
Utilities.sleep(3000); // change this value to show the "Finished! This window will close automatically. HTML window for longer time.
htmlApp("","close"); // Automatically closes the HTML window.
}
function htmlApp (status,close) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var htmlApp = HtmlService.createTemplateFromFile("html");
htmlApp.data = status;
htmlApp.close = close;
ss.show(htmlApp.evaluate()
.setWidth(300)
.setHeight(200));
}
In the HTML script file named 'html':
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h2>Updating..</h2>
<p id="status">(innerHTML).</p>
<div id="imageico"></div>
<script>
var imageContainer = document.getElementById("imageico");
if (<?= data ?> != "Finished!"){
document.getElementById("status").innerHTML = "Running script, please wait..";
} else {
document.getElementById("status").innerHTML = "Finished! This window will close automatically.";
}
if (<?= close ?> == "close"){
google.script.host.close();
}
</script>
</body>
</html>
Have a look at this Sample Spreadsheet.

I don't see any methods or sample scripts regarding your concern. But this documentation about alert might help. It will open a dialog box in the user's editor with the given message and an "OK" button. However, this method suspends the server-side script while the dialog is open and the script will resume after the user dismisses the dialog.
You may also execute alert dialogs before running your script.
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show alert', 'showAlert')
.addToUi();
}
function showAlert() {
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert(
'Please confirm',
'Are you sure you want to continue?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
ui.alert('Confirmation received.');
} else {
// User clicked "No" or X in the title bar.
ui.alert('Permission denied.');
}
}

Related

How to automatically change agent status on Amazon Connect?

I need step by step directions on how to load the CCP into a webpage and use the streams API. I would need the javascript to turn the agent from "missed" to "available" after 25 seconds.
Currently we have to manually update staus which doesn't make sense for our use case.
I saw on the Amazon Connect forum someone made mention of a way to automatically change the status of from Missed to Available.
If you're embedding the CCP and using the Streams API, you can check
the agent status on refresh, and if it's in Missed Call, set it to
Available. I have this set to happen after 10 seconds.
For an embedded CCP you can do this using Stream API. You can subscribe to the agent refresh status, and do it there.
connect.agent(function (agent) {
logInfoMsg("Subscribing to events for agent " + agent.getName());
logInfoMsg("Agent is currently in status of " + agent.getStatus().name);
agent.onRefresh(handleAgentRefresh);
}
function handleAgentRefresh(agent) {
var status = agent.getStatus().name;
logInfoEvent("[agent.onRefresh] Agent data refreshed. Agent status is " + status);
//if status == Missed Call,
// set it to Available after 25 seconds."
//For example -but maybe this is not the best approach
if (status == "Missed") { //PLEASE review if "Missed" and "Availble" are proper codes
setTimeout(function () {
agent.setState("Available", {
success: function () {
logInfoEvent(" Agent is now Available");
},
failure: function (err) {
logInfoEvent("Couldn't change Agent status to Available. Maybe already in another call?");
}
});
;
}, 25000);
}
}
If you also need to know how to embed the CCP in a website, you can just do something like this
<!DOCTYPE html>
<meta charset="UTF-8">
<html>
<head>
<script type="text/javascript" src="amazon-connect-1.4.js"></script>
</head>
<!-- Add the call to init() as an onload so it will only run once the page is loaded -->
<body onload="init()">
<div id=containerDiv style="width: 400px;height: 800px;"></div>
<script type="text/javascript">
var instanceURL = "https://my-instance-domain.awsapps.com/connect/ccp-v2/";
// initialise the streams api
function init() {
// initialize the ccp
connect.core.initCCP(containerDiv, {
ccpUrl: instanceURL, // REQUIRED
loginPopup: true, // optional, defaults to `true`
region: "eu-central-1", // REQUIRED for `CHAT`, optional otherwise
softphone: { // optional
allowFramedSoftphone: true, // optional
disableRingtone: false, // optional
ringtoneUrl: "./ringtone.mp3" // optional
}
});
}
</script>
</body>
</html>
You can see the documentation for StreamsAPI here https://github.com/amazon-connect/amazon-connect-streams/blob/master/Documentation.md

get content of webview in nativescript

Is there a way I can read the content of webview after the page is loaded ?
The reason is redirect (like window.location.replace or window.location.href ) is not working in IOS in my case, works fine in Android.
https://docs.nativescript.org/cookbook/ui/web-view
I can access url, error. but how to access content ?
Narayan
I was only looking for IOS. I found the answer and sharing it here. For Android I would like to point some leads.
if (webView.ios) {
var webHeader = webView.ios.stringByEvaluatingJavaScriptFromString("document.head.innerHTML").trim();
console.log(webHeader);
var webBody = webView.ios.stringByEvaluatingJavaScriptFromString("document.body.innerHTML").trim();
console.log(webBody);
} else if (webView.android) {
webTitle = webView.android.getTitle(); //getting the title title
console.log(webTitle)
}
Some stack overflow lead for Android
You could look at this post. installs a library that allows communication with the webview through observables. Right now I'm using it myself and it's great for both iOS and Android
1- install:
tns plugin add nativescript-webview-interface
2- in web project copy plugin file
cp node_modules/nativescript-webview-interface/www/nativescript-webview-interface.js app/www/lib/
3- code:
xml:
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
loaded="pageLoaded">
<web-view id="webView"></web-view>
</Page>
var webViewInterfaceModule = require('nativescript-webview-
interface');
var oWebViewInterface;
function pageLoaded(args){
page = args.object;
setupWebViewInterface(page)
}
function setupWebViewInterface(page){
var webView = page.getViewById('webView');
oWebViewInterface = new
webViewInterfaceModule.WebViewInterface(webView, '~/www/index.html');
}
function handleEventFromWebView(){
oWebViewInterface.on('anyEvent', function(eventData){
// perform action on event
});
}
function emitEventToWebView(){
oWebViewInterface.emit('anyEvent', eventData);
}
function callJSFunction(){
oWebViewInterface.callJSFunction('functionName', args, function(result){
});
}
web-view:
<html>
<head></head>
<body>
<script src="path/to/nativescript-webview-interface.js"></script>
<script src="path/to/your-custom-script.js"></script>
</body>
web-view js:
var oWebViewInterface = window.nsWebViewInterface;
// register listener for any event from native app
oWebViewInterface.on('anyEvent', function(eventData){
});
// emit event to native app
oWebViewInterface.emit('anyEvent', eventData);
// function which can be called by native app
window.functionCalledByNative = function(arg1, arg2){
// do any processing
return dataOrPromise;
}
More Info:
https://www.npmjs.com/package/nativescript-webview-interface
http://shripalsoni.com/blog/nativescript-webview-native-bi-directional-communication/
This will work for IOS
if (webview.ios){
url = args.url;
}

How to read/intercept JavaScript on the page before it is executed?

I would like to intercept location.reload(); via a Firefox API or by reading the JS on the page (remote & embedded) before it is loaded/executed or by any other means possible.
Example:
<head>
<script>
window.setTimeout(function() { location.reload(); }, 10000);
</script>
</head>
I have tried beforescriptexecute event listener (via GreaseMonkey & // #run-at document-start) but it is fired AFTER above is executed.
Update:
beforescriptexecute works nicely on REMOTE scripts since the event beforescriptexecute is fired before making the request (but then on the script src and not script content). It is different if the script is within normal script tag (and not remote), as per the example given. The beforescriptexecute fires and the script content can be rewritten but by then the window.setTimeout() has already fired and it is executing.
The beforescriptexecute should work. Its a non-greasemonkey event:
https://developer.mozilla.org/en-US/docs/Web/Events/beforescriptexecute
You can do stuff like this:
document.addEventListener("beforescriptexecute", function(e) {
src = e.target.src;
content = e.target.text;
if (src.search("i18n.js") > -1) {
// Stop original script
e.preventDefault();
e.stopPropagation();
window.jQuery(e.target).remove();
var script = document.createElement('script');
script.textContent = 'script you want';
(document.head || document.documentElement).appendChild(script);
script.onload = function() {
this.parentNode.removeChild(this);
}
}

What would unhook my View and Controller from each other in Chrome and IE but not in Firefox?

I have previously successfully tested this MVC functionality in my app in Chrome but have recenlty also tested in IE (10) and Firefox.
When I mash the submit button on a page which sends model values to its controller for running a query and generating a report, it now works only in Firefox (each of the three browser indeed have their own peculiar characteristics -- where they shine or "dull" in relation to their cohorts (gleaming in purple and gold) -- but Chrome and Firefox seem to have lost the connection between the submit button's click handler and the corresponding Controller's method.
The app seems to simply hang after mashing the submit button in Chrome and IE; the breakpoints I have -- the first of which is at the very beginning of the corresponding [HttpPost] ActionResult in the Controller class -- are not reached. In fact, the app seems to freeze after mashing the button -- right-clicking the submit button after that does not give me an "inspect that element" in the context menu.
[HttpPost]
public ActionResult ReceiptCriteria(SalesReceiptCriteriaModel model)
{
if (ModelState.IsValid) // <-- there is a breakpoint here; only Firefox reaches it
{
. . .
In Firefox, it runs, and the breakpoints are hit.
What could possibly cause Chrome and IE to fail in this way, wheras Firefox soldiers on?
UPDATE
In response to Moby's request, here is the jQuery for the View in question:
The HTML in the View is pretty generic; the jQuery is:
$("#submit_button").click(function() {
// http://stackoverflow.com/questions/18192288/how-can-i-compare-date-time-values-using-the-jqueryui-datepicker-and-html5-time
var begD = $.datepicker.parseDate('mm/dd/yy', $('#BeginDate').val());
var endD = $.datepicker.parseDate('mm/dd/yy', $('#EndDate').val());
if (begD > endD) {
alert('Begin date must be before End date');
$('#BeginDate').focus();
return false;
}
else if (begD.toString() == endD.toString()) {
var dteString = begD.getFullYear() + "/" + (begD.getMonth() + 1) + "/" + begD.getDate();
var begT = new Date(dteString + " " + $('#BeginTime').val());
var endT = new Date(dteString + " " + $('#EndTime').val());
if (begT > endT) {
alert('Begin date must be before End date');
$('#BeginTime').focus();
return false;
}
}
$("#NumberOfResults").css("visibility", "visible");
$("#NumberOfResults").html("Please wait...");
EnableButton("submit_button", false);
// If all are selected, don't enumerate them; just set it at "All" (change of case, from 'all' to 'All', shows that the logic did execute)
var deptsList = $('#depts').checkedBoxes();
if (deptsList.length < deptsArray.length) {
$('#deptHeader span').html(deptsList.join(", "));
}
else if (deptsList.length == deptsArray.length) {
$('#deptHeader span').html("All");
}
// " "
var sitesList = $('#sites').checkedBoxes();
$('#sitesHeader span').html(sitesList.join(", "));
if (sitesList.length < sitesArray.length) {
$('#sitesHeader span').html(sitesList.join(", "));
}
else if (sitesList.length == sitesArray.length) {
$('#sitesHeader span').html("All");
}
$('#hiddenDepts').val(deptsList);
$('#hiddenSites').val(sitesList);
var UPCs = $('#UPC').val();
if (UPCs == "All") {
$('#UPC').val("1"); // take everything (1 and greater)
}
var resultsText = jQuery.trim($("#spanNumberOfResults").text());
if (resultsText != "") {
$("#NumberOfResults").css("visibility", "visible");
if (resultsText == "0") {
$("#NumberOfResults").css("color", "red");
} else {
var href = '/#ConfigurationManager.AppSettings["ThisApp"]/TLDCriteria/LoadReport';
var report_parms = {
GUID: "#Model.GUID",
SerialNumber: "#Model.SerialNumber",
ReportName: "#Model.ReportName"
};
window.open(href, "report_window", "resizable=1, width=850, left=" + (screen.width / 2 - 425));
}
}
}); // end of submit button click
function EnableButton(id, enable) {
if (enable) {
$("#" + id).removeAttr("disabled")
.removeClass("bottomButtonDisabled")
.removeClass("bottomButtonEnabled")
.addClass("bottomButtonEnabled");
} else {
$("#" + id).attr("disabled", "true")
.removeClass("bottomButtonDisabled")
.removeClass("bottomButtonEnabled")
.addClass("bottomButtonDisabled");
}
}
UPDATE 2
Something else which may or may not shed some light on this problem is my .js and .css references:
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js" type="text/javascript" defer > </script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript" defer> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript" defer> </script>
<script src="#Url.Content("~/Scripts/jquery-migrate-1.2.0.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/anytime.compressed.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/dynamicCheckboxes.js")" type="text/javascript" > </script>
. . .
<link href="http://code.jquery.com/ui/1.9.2/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/dynamicCheckboxes.css")" rel="stylesheet" type="text/css" />
<link href="#Url.Content("~/Content/anytime.compressed.css")" rel="stylesheet" type="text/css" />
<!--[if lt IE 9]>
<script src="/Scripts/html5shiv.js"> </script>
<![endif]-->
UPDATE 3
The Network tab in the Chrome Developer Tools looks like the middle of Wyoming (a whole lot of nothing), with a msg about the bottom informing me "No requests captured. Reload the page to see detailed information on the network activity."
When I dutifully mashed F5, it showed all the .js and .css files accessed, and finally (at the top), the page I'm gawking at. Mashing the "View Report" causes no more activity in the tab, though. I do see the console.log() msg I placed at the end of the submit button click handler, though, to wit: "made it to the end of submit button click"
There is one err msg in the console, too, but this:
Failed to load resource: the server responded with a status of 400 (Bad Request) http://localhost/%3C%=%20System.Configuration.ConfigurationManager.AppSettings[%22ThisApp%22]%20%%3E/Content/Images/SSCSsprite.png
Would simply fail to load the resource, not wreak other mayhem, right?
UPDATE 4
Based on Simon Halsey's hint, I found that, on stepping though the jQuery in Chrome, it fails this test:
if (resultsText != "") {
...obviously it's not in Firefox, and I assume that it also fails in IE (I'll czech to be sure in both cases, and update this).
Later: It's "" in Firefox, too...and the first time through, it also failed-wouldn't continue on. Second time through, it got through, though...???
There is two options:
There is no request due to javascript error
Your request signature doesnt math controller method
A.
Browsers have different behaivior with some javascript functions. Thats one of the reasons why jQuery is so popular.
The most efficient way to find it is to debug javascript line by line in each browser.
Likely it is the reason.
B.
Also your javascript is quite exotic for me. I guess you are catching sumbit button click and modifying inputs values on a fly.
I would recommend to use $.post or $.ajax and preventDefault instead.
It would make your javascript more clear and simple.
C.
To analyze what requests are sent from your browser I would recommend to use fiddler.
http://fiddler2.com/

Trouble using Titanium's webview to fire an API event

I'm trying to fire an event from an external HTML page opened inside of Titanium's webview.
app.js file...
var group, now, tab, view, window;
now = new Date();
view = Titanium.UI.createWebView({url: 'http://MYWEBSITE.com/index.htm?time=' + now.getTime()});
window = Titanium.UI.createWindow({tabBarHidden: true, navBarHidden: true});
window.add(view);
Titanium.App.addEventListener('browse', function(e) {
Ti.API.info("I received " + e.something + " from the webview.");
});
group = Titanium.UI.createTabGroup();
tab = Titanium.UI.createTab({title: 'window', window: window});
group.addTab(tab);
group.open(tab);
js excerpt from web page...
$("#testButton").mousedown(function() {
alert ("I got clicked.");
Ti.App.fireEvent('browse', {something:'stuff'});
});
(I include the time in the URL to ensure the page is always fresh.)
Adding the event listener as shown above, or using view.addEventListener, compiles but ultimately doesn't work.
Using Titanium.UI.WebView.addEventListener produces an error message that the object doesn't exist.
Do I need to open the URL/webview in a different manner?
Also, since Titanium.App.fireEvent is not a recognized function, except to Titanium, how does one prevent a JavaScript error?
Thanks.
// from web page
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id='testButton'>TEST BUTTON</div>
</body>
<script>
var _button = document.getElementById ("testButton");
_button.onmousedown = function () {
alert (this.id);
Ti.App.fireEvent('fromwebview', {name:this.id});
return false;
};
</script>
</html>
from apps.js
Ti.App.addEventListener('fromwebview', function(data)
{
Titanium.API.info("--> " + data.name);
});
Just to warn you all - I don't think this works with remote pages anymore for security reasons. Spent ages trying fruitlessly!
You can make this work on your remote html page by including the Titanium Injection code. For sdk 1.8.3 it's the following. Now your remote html page can talk to the device.
var Ti = {_event_listeners:[],createEventListener:function(listener ){ var newListener={ listener:listener ,systemId:-1 ,index:this._event_listeners.length };this._event_listeners.push(newListener);return newListener;},getEventListenerByKey:function(key,arg){for(var i=0;i<this._event_listeners.length;i++){if(this._event_listeners[i][key]==arg){return this._event_listeners[i];}} return null;},API:TiAPI,App:{addEventListener:function(eventName,listener) {var newListener=Ti.createEventListener(listener);newListener.systemId=TiApp.addEventListener(eventName,newListener.index);return newListener.systemId;},removeEventListener:function(eventName,listener) {if(typeof listener=='number'){TiApp.removeEventListener(eventName,listener);var l=Ti.getEventListenerByKey('systemId',listener);if(l!==null){Ti._event_listeners.splice(l.index,1);}}else{l=Ti.getEventListenerByKey('listener',listener);if(l!==null){TiApp.removeEventListener(eventName,l.systemId);Ti._event_listeners.splice(l.index,1);}}},fireEvent:function(eventName,data) {TiApp.fireEvent(eventName,JSON.stringify(data));}},executeListener:function(id,data) {var listener=this.getEventListenerByKey('index',id);if(listener!==null){listener.listener.call(listener.listener,data);}}};var Titanium=Ti;

Resources