Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
leoherzog committed Sep 26, 2016
0 parents commit 6e89475
Show file tree
Hide file tree
Showing 7 changed files with 569 additions and 0 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
![In/Out Board 2](http://i.imgur.com/8FcMfsp.jpg)

# In/Out 2

### Basics

This project is a rewrite of [my old web-based office in/out board](https://github.com/xd1936/inout), written in [Google Apps Script](https://developers.google.com/apps-script/) and powered by Google Calendar. It's a simple HTML table generator that formats and displays a hard-coded list of user's current statuses on Google Calendar.

For each user, you get their **name** (with optional **phone extension**), **free/busy status**, **location**, and **duration of the event**. If the person has shared their calendar with you, you will see if they are free or busy, and if busy, event information available to you. When that user creates a new event in Google Calendar, "Available" vs. "Busy" events determine their status on the board, and "Public" vs. "Private" events determine if the details of the event are visible on the board. If you have more than one event going on at the same time, the board looks at the event that is ending latest.

Because this code is hosted and authenticated server-side on Google Apps Script, there are no dependencies or servers required. It simply generates a web page.

### Setup

1. Create a [new Google Apps Script project](https://www.google.com/script/start/) in Google Drive.
2. Copy and paste the code from the `src` folder into six files in the Apps Script project
3. Go into **Resources****Advanced Google services...**, and turn on the **Calendar API v3**. Also follow the *Developer Console* link on this same screen and enable access to the **Google Calendar API** for this project ([more information](https://developers.google.com/apps-script/guides/services/advanced)).
4. Go into **Publish****Deploy as web app...**. Choose the level of access that you want to have on the in/out web page, and click **Deploy**.

You're done! Share the link to your new In/Out board (the *Current web app URL*), or point a TV to look at that page.

### Updating

To update, simply copy and paste all files from the `src` folder (except your config file) to your project, and go to **Publish****Deploy as web app...**. Increment the version number (Pick "New" under the **Project Version** dropdown) and click **Deploy**. You should be good to go!

- - -

Feel free to take a look at the source and adapt as you please. I would love to see some pull requests for improvements to the Javascript.

This source is licensed as follows:

[![Creative Commons License](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/)

<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Javascript In/Out 2</span> is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).

- - -

If you want to say thanks, [buy me a coffee via PayPal](https://www.paypal.me/leoherzog)
146 changes: 146 additions & 0 deletions src/Code.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
function doGet(request) {
return HtmlService.createTemplateFromFile('index.html')
.evaluate()
.setTitle("In/Out Board")
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}

function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}

/**
* Checks if a Google Calendar ID has any busy events happening right now, or coming up in the next 5 minutes
*
* @param {string} the id of the google calendar
* @return {object} the status of the calendar right now (free, busy, or not found), the calendar's name, and the details of the event if busy
*/
function checkIfBusy(id) {

if (!id) {
return {id: id, busy: "Please call this method with a valid Google Calendar ID"};
}

// get the array of events from that user's calendar
var now = new Date();
var fiveMinutesFromNow = new Date(now.getTime() + (5 * 60 * 1000));
now = now.toISOString();
fiveMinutesFromNow = fiveMinutesFromNow.toISOString();

try {

var events = Calendar.Events.list(id, {timeMin: now, timeMax: fiveMinutesFromNow, singleEvents: true, orderBy: "updated"}).items;

}
catch(err) {

return {id: id, busy: "Error: " + err};

}

// check if there are any other problems with that array of events
if (!events) {
return {id: id, busy: "Calendar not found or not shared"};
}

if (events.length == 0) { // there is nothing going on at all right now

return {id: id, busy: false};

} else { // go through the logic of determining which event (if any) should be returned

// build an array of event objects that are set to 'busy' status
var busyEvents = [];

for (var i = 0; i < events.length; i++) {

var eventId = events[i].id;

var verboseEvent = Calendar.Events.get(id, eventId); // use the advanced calendar service to grab all the event's deets

if (!verboseEvent.transparency) { // if the event is 'busy', not 'available'
busyEvents.push(verboseEvent);
}

}

if (busyEvents.length == 0) { // if there WERE one or more events, but none were set to 'busy'

return {id: id, busy: false};

} else if (busyEvents.length == 1) { // we've got one busy event going on right now

var eventName = busyEvents[0].summary;
var eventLocation = busyEvents[0].location;
if (busyEvents[0].start.dateTime) {
var allDay = false;
var start = busyEvents[0].start.dateTime;
} else {
var allDay = true;
var start = busyEvents[0].start.date;
}
if (busyEvents[0].end.dateTime) {
var end = busyEvents[0].end.dateTime;
} else {
var end = busyEvents[0].end.date;
}

return {id: id, busy: true, eventDetails: {name: eventName, location: eventLocation, startTime: start, endTime: end, allDay: allDay}};

} else { // we've got two more more busy events going on right now

var selectedEvent = busyEvents[0]; // select the first busy event in the array

for (var i = 0; i < busyEvents.length; i++) { // go through each busy event

if (busyEvents[i].end.dateTime == null) { // (if there's an all-day/multi-day event, it may not have a dateTime... just a date)
busyEvents[i].end.dateTime = busyEvents[i].end.date + "T00:00:00-05:00"; // (this converts that date to a dateTime for the comparison below)
}

if (busyEvents[i].end.dateTime > selectedEvent.end.dateTime) { // if this event ends later than the selected event...
selectedEvent = busyEvents[i]; // ...make this event the new selected event
}

}

if (selectedEvent.end.date) { // now that we've done our comparisons with time, we might have an all-day event with both an end.date and end.dateTime...
delete selectedEvent.end.dateTime; // remove the dateTime so that it only has a date again
}

var eventName = selectedEvent.summary;
var eventLocation = selectedEvent.location;
if (selectedEvent.start.dateTime) {
var allDay = false;
var start = selectedEvent.start.dateTime;
} else {
var allDay = true;
var start = selectedEvent.start.date;
}
if (selectedEvent.end.dateTime) {
var end = selectedEvent.end.dateTime;
} else {
var end = selectedEvent.end.date;
}

return {id: id, busy: true, eventDetails: {name: eventName, location: eventLocation, startTime: start, endTime: end, allDay: allDay}};

}

}

}

function testShit_() {
var freeOrBusy = checkIfBusy("[email protected]");

Logger.log(freeOrBusy.busy); // boolean

if (freeOrBusy.eventDetails) {
Logger.log(freeOrBusy.eventDetails.name); // string
Logger.log(freeOrBusy.eventDetails.location); // string
Logger.log(freeOrBusy.eventDetails.startTime); // 'date' or 'dateTime' string
Logger.log(freeOrBusy.eventDetails.endTime); // 'date' or 'dateTime' string
Logger.log(freeOrBusy.eventDetails.allDay); // boolean
}
}
5 changes: 5 additions & 0 deletions src/clock.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
function setClock() {
document.getElementById('date').innerHTML = moment().format("dddd, MMMM Do, YYYY | h:mm a");
}
</script>
17 changes: 17 additions & 0 deletions src/config.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script>
config = {
'cityName': 'Greendale',
'weatherLat': 39.8586998,
'weatherLon': -104.673865,
'showExt': true,
'people': [
{name:'Jeff Winger', ext:'7654', id:'[email protected]'},
{name:'Abed Nadir', ext:'1357', id:'[email protected]'},
{name:'Annie Edison', ext:'8552', id:'[email protected]'},
{name:'Troy Barnes', ext:'0086', id:'[email protected]'},
{name:'Britta Perry', ext:'0000', id:'[email protected]'},
{name:'Shirley Bennett', ext:'5322', id:'[email protected]'},
{name:'Pierce Hawthorne', ext:'7775', id:'[email protected]'}
]
};
</script>
7 changes: 7 additions & 0 deletions src/forecast.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
function refreshForecast() {
document.getElementById("forecast").innerHTML = '';
console.log("Refreshing forecast...");
document.getElementById("forecast").innerHTML = '<iframe id="forecast-embed" type="text/html" frameborder="0" height="240px" width="100%" src="https://forecast.io/embed/#lat=' + config.weatherLat + '&lon=' + config.weatherLon + '&name=' + config.cityName + '&font=Georgia&refresh=' + new Date().getTime() + '" seamless></iframe>';
}
</script>
Loading

0 comments on commit 6e89475

Please sign in to comment.