Fix Notification Email Content - google-app-maker

So I have a Status Dropdown on a fragment page (used to edit database entries) that I want to send an email notification when the entry changes from "Pending" to "Ready to Build".
I am using the following code:
var widgets = widget.parent.descendants;
var to = 'notifications#xxx.com';
var subject = 'New System Order: ' + widgets.ProjectName.value;
var msg = "A new order for [ " + widgets.ProjectName.value + " ] has been created for [ " + widgets.UsersPosition.value + " ]";
sendMessage(to, subject, msg);
You can see that I also have it pulling the Project Name/User Position in the subject/body of the email. These are Text Boxes on that Fragment page displaying the information from the entry.
All of these works great and exactly as desired when the Dropdown and the Text Boxes are all in the same panel. However, when I separate them into separate panels (for aesthetics) the system cannot find widgets.ProjectName.value or widgets.UsersPosition.value.
I'm assuming I just need to adjust the var widgets = widget.parent.descendants; line, but I don't know to what.
Any help would be greatly appreciated. Thank you.

So it looks like I just need to change widget.parent.descendants; to widget.root.descendants;

I would recommend you to use Model events instead.
App Maker will fire the 'onSave' event every time a record is modified.
Go to the 'Events' tab in the model editor, and add something like:
if (oldRecord.State == "Pending" && record.State == 'Ready to Build') {
sendEmail_();
}
You can learn more about model events here.
Regards,
Julian.-

Related

Set email body content in google appmaker

I want to send an email with a content related to my data such as in following piece of code I found on Datasource script of Google AppMaker Project Tracker template. But I don't understand how it works. How that data.modifiedBy reflect to the record in my datasource?
Any help from the floors? Thanks ..
Look at the Notifications server side script in the template.
It has method notifyAboutItemChanges_ which is passing the data to this record.
function notifyAboutItemChanges_(changes) {
var settings = getAppSettingsRecord_()[0];
if (!settings.EnableEmailNotifications) {
return;
}
var data = {
appUrl: settings.AppUrl,
itemType: changes[0].Type,
itemKey: changes[0]._key,
itemName: changes[0].Name,
modifiedBy: changes[0].ModifiedBy,
changes: changes
};
// Email subject.
var subjectTemplate =
HtmlService.createTemplate(settings.NotificationEmailSubject);
}
This function is passing this data to your settings record.
So no magic here :) You need to pass the data to your record which will be replaced at run time with the values.
For more details on Email refer this sample app.

onCreate send email to self in AppMaker?

Still learning about app maker and found this presentation at Google I/O '17 "Build Powerful Custom Apps Fast with App Maker on G Suite"
At timestamp 15.24 sec some code is shown on the screen showing how to send an email to yourself once someone creates a new item can.
https://youtu.be/Q84HQgI3Dd8?t=15m27s
Question
Can anyone advise where and how this code can be implemented its pretty cool and would be a great feature to add when a record is created
Thanks in advance and no worries if you cant help
You are looking for model events:
https://developers.google.com/appmaker/models/events
In App Maker models typically have onCreate, onSave, onLoad, onDelete events. It is the best place to handle email notifications. Here is a link to App Script email API:
https://developers.google.com/apps-script/reference/mail/mail-app
I strongly recommend you to go to the Codelab for App Maker. The section Building a form to send an email describes the whole process.
The steps to highlight are:
Step 11 - Set the onClick property of the button as a custom action with the code:
var widgets = widget.parent.descendants;
var to = widgets.To.value;
var subject = widgets.Subject.value;
var msg = widgets.Msg.value;
widgets.EmailStatus.text = 'Sending email...';
SendEmail(to, subject, msg)
Step 13 - Add the following ClientScript code:
function clearEmailForm(){
var formWidgets = app.pages.Basic.descendants;
formWidgets.EmailStatus.text = "";
formWidgets.Msg.value = "";
formWidgets.To.value = "";
formWidgets.Subject.value = "";
}
function SendEmail(To, Subject, Msg){
var status = app.pages.Basic.descendants.EmailStatus;
google.script.run.withSuccessHandler(function(result) {
status.text = 'Email sent...';
clearEmailForm();
})
.SendEmail(To, Subject, Msg);
}
Step 14 - Now add the corresponding code to the ServerScript.
function SendEmail(to, subject, msg){
MailApp.sendEmail(to, subject , msg);
}

Google Tag Manager get user ID and time onClick

I have button with ID on the website.
At the moment we track button click with Tag Manager and Analytics.
But I would like to know, is there a way to save information about user ID and time when button was clicked?
Looking forward for any information.
Thank you!
I guess user ID, what you mentioned is internal ID in your website. First of all, you need to find a way how to receive user ID in your system. It can be many ways.
For example, let's say that your website has hidden input with user ID which has id="user-id" and you want to track button "Track this button". Basic html code if your page is:
<input type="hidden" id="user-id" value="unqieuserid123"/>
<button id="button-id">Track this button</button>
You need to create user defined variable (Variables->User-Defined Variables->New). Choose "Javascript" and enter name "UserId" and this code:
function () {
return document.getElementById("user-id") != null ?
document.getElementById("user-id").value : ""
}
At the end it should be like that:
Create variable for receiving user time (it will write user local time) with name "UserTime" and javascript code:
function() {
// Get local time as ISO string with offset at the end
var now = new Date();
var tzo = -now.getTimezoneOffset();
var dif = tzo >= 0 ? '+' : '-';
var pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return now.getFullYear()
+ '-' + pad(now.getMonth()+1)
+ '-' + pad(now.getDate())
+ 'T' + pad(now.getHours())
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ '.' + pad(now.getMilliseconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
At the end it should be like that:
Enable built-in variable Click Element if it is not enabled yet.
Create new trigger, for your button. In my case it is like that:
Create new tag for tracking and sending data to GA. Here you can use your variables created on step #1 and #2. Like {{UserId}} and {{UserTime}}. In my example it is like that:
At the end in Google Analytics you will receive event with this label:
'user id: unqieuserid123; user time: 2017-05-31T12:20:19.06+04:00'
I solved this problem in the following way:
- Created variables in Google Tag Manager (GTM) which track the user ID and the date & time.
I already had tags which tracked button clicks on the website, so I added these variables in the categories of Tags ("Label" and "Value")
Click event
Every time user click on the button, these variables track information about ID and date&time.

Full calendar Scheduler - get ResourceId on selecting the slotduration for adding events

In Scheduler Calendar, Iam getting the resources from resources.json on the first column.
Iam trying to add the events for each resources.
When I click the slotduration straight to each resources, I should get the resourceId. So, I would know to which resources, Iam adding the events.
In select function, Iam able to get only the start and end time, but NOT the resourceId.
Any help will be highly appreciated.
There is fourth argument in the select callback, Using that you would be able to get resource. see the example below.
$('#calendar').fullCalendar({
select: function (start, end, calendar,res)
{
//to get resource
console.log(res);
}
});
It will give you json object.
To get resource id on click of resource header do the following changes in scheduler.js,
modify below method.add id and class to the resource header.
ResourceRow.prototype.renderSpreadsheetContent = function(tr) {
.......
.......
td = $('<td id="'+resource.id+'" class="' + this.view.widgetContentClass + ' resourceHeader"/>').append(contentEl); // add id and class to the resource header.
.......
.......
}
After changing the code just bind an event in your js file as below
$(".resourceHeader").click(function(){
var resourceId=$(this).attr("id");
//write a code to get all the events of selected resource
//and render it on calendar
});
You are good to go now.
Thanks

How to retrieve only new data?

I'm trying to create simple notification system for my site admin, and I need to send only real-time messages to every admin user. But when I use firebase it loads old data on every page, and user see all messages from database. If I set limit(1) user will see last notification on every page reloading:
var eventsList = new Firebase('https://*****-messages.firebaseio.com/');
eventsList.on('child_added', function(message) {
var message = message.val();
$.notification(message.message);
});
How I can load only new messages, without old notification history?
This is by design, in a real-time system there is no concept of the "latest" data because it's always changing. However, if you want to only display items added to the list after the page has loaded, you can do the following:
var newItems = false;
var eventsList = new Firebase('https://*****-messages.firebaseio.com/');
eventsList.on('child_added', function(message) {
if (!newItems) return;
var message = message.val();
$.notification(message.message);
});
eventsList.once('value', function(messages) {
newItems = true;
});
I would comment on the above, but due to reputation I cannot, so hoping this is adequate and this is to address the last comment by Gruff McGruff.
Once fires after because you want to break out of the loop of grabbing all child items. Once that loops is broken, you'll set the newItems variable to true, and then it will be able to get all new children after that.
If you fired it before, it would defeat the purpose and grab all child items regardless because you'll set the newItems variable immediately.
Also, I've used this approach and it works well.

Resources