|
/* |
|
|
|
|
|
Main.gs |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// We use a library here called "Moment" |
|
// It's a dependency, so the below won't work until you have done this: |
|
// Go to Resources -> Libraries and enter this product key: MHMchiX6c1bwSqGM1PZiW_PxhMjh3Sh48 |
|
var moment = Moment.load(); |
|
|
|
// Define the paragraph styles that will be used |
|
// You access them via Google Apps Scripts through class objects such as these |
|
// And then pass it to functions like Paragarph.setHeading |
|
|
|
var HEADER1 = DocumentApp.ParagraphHeading.HEADING1; |
|
var HEADER2 = DocumentApp.ParagraphHeading.HEADING2; |
|
var NORMAL = DocumentApp.ParagraphHeading.NORMAL; |
|
var TIMEKEY = 'timeStart'; |
|
|
|
// This include function is used in the Nofication.html file |
|
// This allows me to include files easily, like importing |
|
|
|
function include(filename) { |
|
return HtmlService.createHtmlOutputFromFile(filename) |
|
.setSandboxMode(HtmlService.SandboxMode.IFRAME) |
|
.getContent(); |
|
} |
|
|
|
// showAlert is used sparingly in the main code and is useful for debugging |
|
|
|
function showAlert(title, prompt, buttons) { |
|
var ui = DocumentApp.getUi(); |
|
|
|
var result = ui.alert( |
|
title, |
|
prompt, |
|
buttons); |
|
|
|
// Process the user's response. |
|
if (result == ui.Button.YES) { |
|
// User clicked "Yes". |
|
return true; |
|
} else { |
|
// User clicked "No" or X in the title bar. |
|
return false; |
|
} |
|
} |
|
|
|
// showPrompt displays the prompt and processes the user's response |
|
|
|
function showPrompt(title, prompt, buttons) { |
|
var ui = DocumentApp.getUi(); // Same variations. |
|
|
|
var result = ui.prompt(title, prompt, buttons); |
|
|
|
// Process the user's response. |
|
var button = result.getSelectedButton(); |
|
var text = result.getResponseText(); |
|
if (button == ui.Button.OK) { |
|
return text; |
|
} else if (button == ui.Button.CANCEL) { |
|
return null |
|
} |
|
return "" |
|
} |
|
|
|
// This function runs automatically when the file is opened |
|
|
|
function onOpen() { |
|
var ui = DocumentApp.getUi(); |
|
|
|
// TODO: Figure out how to get the owner (probably using File service) |
|
ui.createMenu('Learning Journal') |
|
.addItem('Start…', 'start') |
|
.addItem('Finished!', 'finish') |
|
.addSeparator() |
|
.addItem('Notifications', 'notify') |
|
.addToUi(); |
|
|
|
if (showAlert( |
|
"Are you ready to start the timer?", |
|
'After clicking "Yes", begin writing. When you are done writing, you can click on "Learning Journal" and "Finished" to get a report of how long you wrote, and how many words you have written.', |
|
DocumentApp.getUi().ButtonSet.YES_NO) |
|
) { |
|
start() |
|
} |
|
} |
|
|
|
function test_notify() { |
|
notify('hello', 'hi'); |
|
} |
|
|
|
function notify() { |
|
|
|
var agent = PropertiesService.getScriptProperties().getProperty('notify_email'); |
|
if (!agent) { |
|
var prompt = "No one is currently notified. Add an email below."; |
|
} else { |
|
var prompt = "Right now " + agent + " receives an email. To change, type below"; |
|
} |
|
|
|
var result = showPrompt( |
|
"Who to notify after clicking 'Finished'?", |
|
prompt, |
|
DocumentApp.getUi().ButtonSet.OK_CANCEL) |
|
if (result) { |
|
//TODO: Validate |
|
var scriptProperties = PropertiesService.getScriptProperties(); |
|
scriptProperties.setProperty('notify_email', result) |
|
} |
|
} |
|
|
|
// Not used: |
|
|
|
function tryThis() { |
|
var file = DriveApp.getFileById(DocumentApp.getActiveDocument().getId()); |
|
Logger.log(file); |
|
Logger.log(file.getOwner().getEmail()); |
|
} |
|
|
|
// |
|
// These functions are convenience functions that will allow us to |
|
// to add text, very useful |
|
// |
|
|
|
function insertHROnTop() { |
|
var doc = DocumentApp.getActiveDocument(); |
|
var body = doc.getBody(); |
|
body.insertParagraph(0, '\n'); |
|
body.insertHorizontalRule(0); |
|
body.insertParagraph(0, '\n'); |
|
} |
|
|
|
function insertTextOnTop(textToInsert, heading, select) { |
|
var doc = DocumentApp.getActiveDocument(); |
|
var text = doc.getBody(); |
|
var par = text.insertParagraph(0, textToInsert); |
|
par.setHeading(heading); |
|
|
|
if (select) { |
|
var rangeBuilder = doc.newRange(); |
|
rangeBuilder.addElement(par); |
|
doc.setSelection(rangeBuilder.build()); |
|
} |
|
} |
|
|
|
// Calculates how much time has passed, using the moment library |
|
|
|
function testCalcTimeElasped() { |
|
var userProperties = PropertiesService.getUserProperties(); |
|
var then = moment(userProperties.getProperty('timeStart')); |
|
var now = moment(moment().format()); |
|
var result = calcTimeElapsed(then, now); |
|
Logger.log(result); |
|
} |
|
|
|
function calcTimeElapsed(now, then) { |
|
Logger.log(then.format("HH:mm:ss")); |
|
|
|
var duration = moment.duration(then.diff(now)); |
|
return Math.round(duration.asMinutes()); |
|
} |
|
|
|
// Count how many words are in s |
|
// Kinda rudementary |
|
|
|
function countWords(s){ |
|
s = s.replace(/(^\s*)|(\s*$)/gi,"");//exclude start and end white-space |
|
s = s.replace(/[ ]{2,}/gi," ");//2 or more space to 1 |
|
s = s.replace(/\n /,"\n"); // exclude newline with a start spacing |
|
return s.split(' ').length; |
|
} |
|
|
|
// Function that collects every typed word starting at the beginning of the document |
|
// and loops until it reaches a horizontal rule |
|
// Returns the count and the words themselves |
|
|
|
function words() { |
|
var doc = DocumentApp.getActiveDocument(); |
|
var body = doc.getBody(); |
|
|
|
var finished = false; |
|
var userEntered = ""; |
|
|
|
for (var i = 0; i < body.getNumChildren(); i++) { |
|
var child = body.getChild(i); |
|
|
|
if (!finished) { |
|
userEntered += " " + child.getText(); |
|
} |
|
|
|
if (child.getNumChildren() > 0) { |
|
for (var c = 0; c < child.getNumChildren(); c++) { |
|
var embeddedChild = child.getChild(c); |
|
if (embeddedChild.getType() == DocumentApp.ElementType.HORIZONTAL_RULE) { |
|
finished = true; |
|
} |
|
} |
|
} |
|
} |
|
|
|
return {count: countWords(userEntered), text: userEntered}; |
|
|
|
} |
|
|
|
function test() { |
|
start(); |
|
finish(); |
|
} |
|
|
|
// Starts the timer and presents sample text |
|
|
|
function start() { |
|
var userProperties = PropertiesService.getUserProperties(); |
|
userProperties.setProperties({'timeStart': moment().format() }); |
|
insertHROnTop(); |
|
insertTextOnTop("Start writing!", NORMAL, true); |
|
} |
|
|
|
// Looks at the script property "notify_email" |
|
// And sends email |
|
|
|
function emailAgents(body) { |
|
var user = Session.getActiveUser(); |
|
var doc = DocumentApp.getActiveDocument(); |
|
var body = doc.getUrl() + '\n\n' + body; |
|
var subject = '[' + doc.getName() + '] New Entry by ' + user.getEmail() |
|
|
|
var agent = PropertiesService.getScriptProperties().getProperty('notify_email'); |
|
if (agent) { |
|
MailApp.sendEmail(agent, subject, body); |
|
} |
|
Logger.log(agent); |
|
} |
|
|
|
// This function gets called when user clicks finished |
|
// It collects the script property timeStart and calls the other functions appropriately |
|
|
|
function finish() { |
|
var userProperties = PropertiesService.getUserProperties(); |
|
var timeStart = userProperties.getProperty('timeStart'); |
|
if (timeStart != "") { |
|
var now = moment(moment().format()); |
|
var then = moment(timeStart); |
|
var result = calcTimeElapsed(then, now); |
|
|
|
var wds = words(); |
|
|
|
var title = "(You spent " + result + " minutes to write " + wds.count + " words!)"; |
|
|
|
insertTextOnTop(title, HEADER2, false); |
|
insertTextOnTop(moment().format('MMMM Do YYYY'), HEADER1, false); |
|
|
|
// clear it to indicate usage |
|
userProperties.setProperties({'timeStart': ""}); |
|
|
|
emailAgents(wds.text); |
|
|
|
} else { |
|
showAlert("Oops!", "You have to click on 'Start' in the 'Learning Journal' menu first!", DocumentApp.getUi().ButtonSet.OK); |
|
} |
|
} |