One of my initiatives with the PCCE was to build a curriculum development environment (www.tftshare.ca) for our teachers that utilized the highly collaborative Google Apps for Education platform. It is a place where teachers can create units, lesson plans and resources using the Google Apps and Google Docs suite of tools and share them with one another. When the unit is finished, the user can post the unit for others in the domain to view. Naturally, the fantastic flexibility of Google Apps script was used as the glue that holds it all together. We now are extremely pleased to have over 2000 educational units currently under development by our instructors! Even with this wonderful success story, we saw a few issues and some definite areas for improvement.
Ultimately, we wanted to increase collaboration and facilitate the sharing of information between staff. However, many people did not check the email address associated with their tftshare.ca account; and who could blame them? Most of us have a plethora of accounts that seems to be growing from year to year. Having one more account to check just seems like one more thing. What to do? Well, I decided that the environment needed an email notification system that would inform people when important emails were sent out to them. Emails that would:
- notify the user when a request was made to share a unit
- let the user know when one of their units was posted
- inform the user when they received a Google + notification from a colleague
- share important information from TfT Share administrators (updates, new features, etc.)
Building the email notification system was surprisingly easy with the Gmail Service provided through Google Apps Script. For example, when users share a unit or a TfT Coordinator posts a unit, the user will be informed via email using a script sent via an app on the tftshare.ca website.
First, the Gmail account is scanned to see if a [TfT Share] label has been created. This is the label that will be used to archive the email notification when the link is clicked to view its contents or the user clicks the close button:
// Check the user’s labels to see if a “[TfT Share]” label exists. If not, create one
var labels = GmailApp.getUserLabels();
var x = labels.length;
var found = false;
while (x--) {
var label = labels[x].getName();
if (label == "[TfT Share]") {
found = true;
}
}
if (found == false) {
GmailApp.createLabel('[TfT Share]');
}
The user's messages are then scanned via the GmailApp.getInboxThreads() function:
// scan the first 50 threads of a user’s inbox and store the results in an array
// next, scan the messages first subject text of a thread via the .getFistMessageSubject() function
var threads = GmailApp.getInboxThreads(0, 50);
var x = threads.length;
var message = threads[x].getFirstMessageSubject();
Once I have the subject text of the first message in a thread, I scan the subject text for key words and perform functions depending on specific keyword matches:
// find a match in the subject text and create a notification box based on the text - this particular notification is for a unit shared with editing privileges
if (message.search(/\[TfT Share\]/) !== -1 && message.search('EDITING Permission') !== -1) {
// found a match so do create the notification
var threadId = threads[x].getId();
var date = threads[x].getLastMessageDate();
// image for the notification icon
var nImg = app.createImage('https://sites.google.com/a/tftshare.ca/g-g/3-0/n-edit.png');
// URL to identify the email if clicked
var mailUrl = "https://mail.google.com/mail/u/0/#all/" + threadId;
// set the id of this element via .setId(‘panel’+threadId) to retrieve when element is is clicked
var msgPanel = app.createVerticalPanel().setId('panel'+threadId)
.setStyleAttribute('borderRadius','10px')
.setStyleAttribute('margin','7px')
.setStyleAttribute('background','rgb(220,235,190)')
.setStyleAttribute('padding','10px');
// top message for the notification
var topMsg = app.createLabel('A TfT Unit Was Shared With You With EDITING Permission:').setStyleAttribute('minWidth','375px')
.setStyleAttribute('fontSize','14px')
.setStyleAttribute('fontWeight','bold')
.setStyleAttribute('color','rgb(0,57,101)');
// Link to open the notification email
// set the id of this element via .setId(threadId) to retrieve when element is is clicked
var botLink = app.createAnchor(message, mailUrl).setId(threadId).setStyleAttribute('minWidth','435px')
.setStyleAttribute('fontWeight','bold')
.setStyleAttribute('fontFamily','arial')
.setStyleAttribute('color','rgb(37,132,201)')
.setStyleAttribute('textDecoration','none');
// add the date to the notification
var dateMsg = app.createLabel(date)
.setStyleAttribute('fontSize','10px')
.setStyleAttribute('fontStyle','italic')
.setStyleAttribute('color','green');
// click handler archives the email to [TfT Share] label - created automatically by script on open
var linkCkH = app.createServerClickHandler('archive');
botLink.addClickHandler(linkCkH).addClickHandler(ClH);
// close button - archives the link and removes it from notification system if it isn’t read
// set the id of this element via .setId(‘close’+threadId) to retrieve when element is is clicked
var close = app.createImage('https://sites.google.com/a/tftshare.ca/g-g/3-0/button-close-n.png').setId('close'+threadId);
var closeCkH = app.createServerClickHandler('archiveClose');
close.addClickHandler(closeCkH).addClickHandler(ClH);
var msgGrid = app.createFlexTable();
msgGrid.setWidget(0,0,nImg).setWidget(0,1,topMsg).setWidget(0,2,close);
msgPanel.add(msgGrid).add(botLink).add(dateMsg);
vPanel.add(msgPanel);
// add one more to the total number of email notifications for the red notification indicator total
total++;
}
The archive functions archive the selected email notification under the [TfT Share] label that is created at the beginning of the script:
// EMAIL URL ANCHOR LINK CLICKED: this function captures the threadId via “e.parameter.source” and .getId() function to archive the email and close the panel. The function also decreases the total counter and sets the text to show the change in the total
function archive(e) {
var app = UiApp.getActiveApplication();
// read the threadID set up via .setId() from the source of the clicked element
var threadId = e.parameter.source;
// close the panel containing the clicked element
app.getElementById('panel'+threadId).setVisible(false);
// archive the email that has the threadId
var thread = GmailApp.getThreadById(threadId);
var label = GmailApp.getUserLabelByName('[TfT Share]');
thread.addLabel(label).moveToArchive();
// decrease the total count in the visible counter
var tempTotal = parseInt(UserProperties.getProperty('nTotal'));
var nTotal = tempTotal -1;
UserProperties.setProperty('nTotal',nTotal);
app.getElementById('nTotal').setText(nTotal);
app.getElementById('screenerPanel').setVisible(false);
if (nTotal == 0) app.getElementById('noNotesPanel').setVisible(true);
return app;
}
// CLOSE BUTTON CLICKED: this function captures the threadId via “e.parameter.source” and .getId() function to archive the email and close the panel. The function also decreases the total counter and sets the text to show the change in the total
function archiveClose(e) {
var app = UiApp.getActiveApplication();
// read the threadID set up via .setId() from the source of the clicked element
var tempId = e.parameter.source;
// remove the word ‘close’ from the Id to extract the threadId variable
var threadId = tempId.substr(5);
// close the panel containing the clicked element
app.getElementById('panel'+threadId).setVisible(false);
// archive the email that has the threadId
var thread = GmailApp.getThreadById(threadId);
var label = GmailApp.getUserLabelByName('[TfT Share]');
thread.addLabel(label).moveToArchive();
// decrease the total count in the visible counter
var tempTotal = parseInt(UserProperties.getProperty('nTotal'));
var nTotal = tempTotal -1;
UserProperties.setProperty('nTotal',nTotal);
app.getElementById('nTotal').setText(nTotal);
app.getElementById('screenerPanel').setVisible(false);
if (nTotal == 0) app.getElementById('noNotesPanel').setVisible(true);
return app;
}
And there you have it! Essentially, the notification system has three major functions:
- SCAN user emails for keywords to trigger notifications
- CREATE notifications and add them to the total
- ADD clickHandlers to handle close events and anchor click events to close the panel, archive the email and decrease the total count
Although designed for an educational setting, this notification system design could be adapted to any number of use cases, from a classroom student notification system to a organizational notification system for businesses and non-profits. Quick and easy to modify, the notifications can also be customized by colour and icon to suit any need.
Sample Notification from the System |
Sample Notification from the System |
Email Notification |
Notification System with the Curriculum Creation/sharing Environment [written entirely in Google Apps Script] |
No comments:
Post a Comment