Google Calendar Attendees widget for Dashing
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #EEC647;
$value-color: #fff;
$title-color: rgba(255, 255, 255, 0.7);
$label-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.7);
// ----------------------------------------------------------------------------
// Widget-list styles
// ----------------------------------------------------------------------------
.widget-attendees {
background-color: $background-color;
vertical-align: top;
padding: 15px 12px 40px 12px !important;
.title {
color: $title-color;
display: inline-block;
.counter{
display: inline-block;
width: 40px;
height: 40px;
line-height: 40px;
background: #F14D00;
border-radius: 20px;
font-size: 30px;
font-weight: bold;
}
}
.value {
font-weight: 600;
color: $value-color;
}
ol {
list-style-position: inside;
}
.list-nostyle {
list-style: none;
}
.label {
color: $label-color;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
}
.more-info {
color: $moreinfo-color;
}
.attendee {
float: left;
margin: 4px;
position: relative;
.counter{
position: absolute;
width: 22px;
height: 22px;
z-index: 10;
top: -4px;
right: -4px;
line-height: 22px;
background: #F14D00;
border-radius: 11px;
font-size: 12px;
font-weight: bold;
}
}
}
# encoding: UTF-8
require 'google/api_client'
require 'date'
require 'time'
require 'digest/md5'
require 'active_support'
require 'active_support/all'
# Update these to match your own apps credentials
service_account_email = ENV['GOOGLE_SERVICE_ACCOUNT_EMAIL'] # Email of service account
key_file = ENV['GOOGLE_SERVICE_PK_FILE'] # File containing your private key
key_secret = ENV['GOOGLE_SERVICE_KEY_SECRET'] # Password to unlock private key
calendarID = ENV['ATTENDEE_CALENDAR_ID'] # Calendar ID.
eventId = ENV['ATTENDEE_EVENT_ID'] # Event ID
defaultImg = ENV['DEFAULT_GRAVATAR'] # Url to image to show as default when no gravatar
next_event_time = ENV['NEXT_EVENT_TIME'] || '14:00' # Time to start showing the next event
next_event_timezone = ENV['NEXT_EVENT_TIMEZONE'] # Time zone to parse the next event time in
# Get the Google API client
client = Google::APIClient.new(:application_name => 'Google Calendar Attendee Widget',
:application_version => '0.0.1')
# Load your credentials for the service account
if not key_file.nil? and File.exists? key_file
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
else
key = OpenSSL::PKey::RSA.new ENV['GOOGLE_SERVICE_PK'], key_secret
end
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/calendar.readonly',
:issuer => service_account_email,
:signing_key => key)
# Start the scheduler
SCHEDULER.every '60s', :first_in => 4 do |job|
# Request a token for our service account
client.authorization.fetch_access_token!
# Get the calendar API
calendar = client.discovered_api('calendar','v3')
# Start and end dates
Time.zone = next_event_timezone
today = Date.today.in_time_zone
tomorrow = Date.today.next_day.in_time_zone
after_tomorrow = Date.today.next_day(2).in_time_zone
# Check if the current time has passed the defined threshold
show_tomorrow_event = Time.zone.now >= Time.zone.parse(next_event_time)
# Search event dates
startDate = !show_tomorrow_event ? today.to_datetime.rfc3339 : tomorrow.to_datetime.rfc3339
endDate = !show_tomorrow_event ? tomorrow.to_datetime.rfc3339 : after_tomorrow.to_datetime.rfc3339
# Get the events
events = client.execute(:api_method => calendar.events.instances,
:parameters => {
:calendarId => calendarID,
:eventId => eventId,
:maxResults => 1,
:timeMin => startDate,
:timeMax => endDate
}
)
# Set the event if there is one found
if events.data.items.count > 0
# Get the first matching event
calendar_event = events.data.items.first
# Get only the attedees that had accepted
accepted_attendees = calendar_event.attendees.select {|attendee| attendee.responseStatus == 'accepted'}
# Prepare the attendees object
accepted_attendees = accepted_attendees.map do |attendee|
email = attendee.email.downcase
# Force additional guests property
attendee['additionalGuests'] = attendee['additionalGuests'] || 0
# Set the gravatar url
hash = Digest::MD5.hexdigest(email)
attendee[:gravatar] = "http://www.gravatar.com/avatar/#{hash}"
attendee[:gravatar] += "?default=#{defaultImg}" if defaultImg
attendee
end
# Event hash to pass to dashing
event = {
title: calendar_event.summary,
attendees: accepted_attendees,
total_attendees: accepted_attendees.reduce(accepted_attendees.length){|r, v| r + v['additionalGuests']},
}
end
# Update the dashboard
send_event('attendees', {
calendar_event: event,
tomorrow_event: show_tomorrow_event
})
end
<div data-renderif="calendar_event">
<h1 class="title">
<span data-bind="calendar_event.title"></span>
<span class="counter" data-bind="calendar_event.total_attendees"></span>
</h1>
<ul class="clearfix">
<li class="attendee" data-foreach-item="calendar_event.attendees">
<img class="gravatar" data-bind-src="item.gravatar" width="62px" height="62px"/>
<div class="counter" data-bind="'+%{extras}' | interpolate {'extras': 'item.additionalGuests'}" data-insertif="item.additionalGuests"></div>
</li>
</ul>
<p class="more-info">
<span data-bind="detailMessage"></span>
</p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
</div>
<div data-hideif="event">
<h1 class="title" data-bind="noEventMessage"></h1>
</div>
class Dashing.Attendees extends Dashing.Widget
ready: ->
# This is fired when the widget is done being rendered
onData: (data) ->
@set('detailMessage', if data.tomorrow_event then @get('tomorrowMessage') else @get('todayMessage') )
A Dashing widget for displaying the number of attendees for a specific calendar event on Google Calendar
It's specially designed to be used against a recursive event. For example, we use it at platanus to show how many people and who is going to have lunch in the office.
Made by platanus in Chile
google-api-ruby-client rails/activesupport
Add it to dashing's gemfile:
gem 'google-api-client'
gem 'activesupport'
and run bundle install
.
To use this widget, you'll first need to set up a Google API project.
210987654321-3rmagherd99kitt3h5@developer.gserviceaccount.com
- you'll need it in environmental variables laterYou can install the widget with dashing install 2f0b6010d6ffab479d61
, or manually add each file in the corresponding location
Setup your environmental variables
GOOGLE_SERVICE_ACCOUNT_EMAIL # Email of service account
GOOGLE_SERVICE_PK_FILE # File containing your private key
GOOGLE_SERVICE_KEY_SECRET # Password to unlock private key 'notasecret'
ATTENDEE_CALENDAR_ID # Calendar ID.
ATTENDEE_EVENT_ID # Event ID
DEFAULT_GRAVATAR # Url to image to show as default when no gravatar
NEXT_EVENT_TIME # Time to start showing the next event 'America/Los Angeles'
1. Add the widget HTML to your dashboard
```html
<li data-row="1" data-col="4" data-sizex="1" data-sizey="1">
<div data-id="attendees"
data-view="Attendees"
data-today-message="Today lunch"
data-tomorrow-message="Tomorrow lunch"
data-no-event-message="No lunch"
data-updatedAtMessage="Updated"></div>
<i class="fa fa-cutlery icon-background"></i>
</li>
```
To set your PK12 certificate in heroku you can follow this guide http://ar.zu.my/how-to-store-private-key-files-in-heroku/