Skip to content

Instantly share code, notes, and snippets.

@tresni
Forked from tfohlmeister/README.md
Last active January 1, 2016 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tresni/8175108 to your computer and use it in GitHub Desktop.
Save tresni/8175108 to your computer and use it in GitHub Desktop.

Description

Dashing widget to display a bunch of current and coming-up Google Calendar events.

The widget shows only one event and is based on the text-widget which is default in the Dashing installation. The time is displayed as human-readable time string with the help of MomentJS.

A Dashing job fetches the events of a given public or private calendar url, orders events to match starting time and sends the data to the dashboard. A certain event offset can be set for each calendar widget so that it will show the first (data-pre="0"), the second (data-pre="1") or any other following event based on the offset. For each calendar you'll have to define a name which enables you to assign custom background colors for events of each calendar.

While the main job is called in larger intervals, there is a second job to be run every minute or so, which kicks out already finished events. In that way processing load on the client (dashboard) side is minimized as only little data is transfered.

Google calendar widget

##Usage You'll need nokogiri for processing XML so add gem 'nokogiri' to your Gemfile and run bundle install from terminal.

Download MomentJS and put moment.min.js in your /assets/javascripts directory. It gets included automatically.

The files calendar.coffee, calendar.html and calendar.scss go in the /widget/calendar directory.

The calendar.rb goes into the /jobs directory.

Put the following in your dashingboard.erb file to make the current and following event show up in your dashboard:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="calendar_events" data-pre="0" data-view="Calendar"></div>
</li>

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="calendar_events" data-pre="1"  data-view="Calendar"></div>
</li>

##Settings (calendar.rb) Set your calendar urls in the calendars variable and give each one an appropriate name. You can obtain your personal calendar urls from the settings page for a certain Google Calendar you have access to. You might also change how often both jobs are called to suit your needs. To change calendar colors simply add a class .calendar-name-YOURCALENDARNAME with appropriate background-color to calendar.scss.

class Dashing.Calendar extends Dashing.Widget
ready: =>
if !@pre? then @set('pre',0)
setInterval(@updateTime, 5000+(1000*@pre))
onData: (data) =>
@events = data.events
@updateEvent()
updateEvent: =>
event = @events[@pre]
@updateContent(event)
@updateTime()
updateContent: (event) =>
@setBackgroundClassBy event.calendar
@set('event',event)
updateTime: =>
if @event?
event = @event
diff = moment(event.when_start).diff(moment())
if diff<0
event.time = "Ends "+moment(event.when_end).fromNow()
else
event.time = moment(event.when_start).calendar()
@unset('event')
@set('event',event)
setBackgroundClassBy: (name) =>
@removeBackgroundClass()
$(@node).addClass "calendar-name-#{name.toLowerCase()}"
removeBackgroundClass: =>
classNames = $(@node).attr("class").split " "
for className in classNames
match = /calendar-name-(.*)/.exec className
$(@node).removeClass match[0] if match
<h1 class="subtitle" data-bind="event.time"></h1>
<h2 class="title" data-bind="event.title"></h2>
<h3 data-bind="event.body | raw"></h3>
<p class="more-info" data-bind="moreinfo | raw"></p>
<p class="updated-at" data-bind="updatedAtMessage | prepend ' | ' | prepend event.calendar"></p>
#!/usr/bin/env ruby
require 'open-uri'
require 'nokogiri'
require 'date'
require 'cgi'
# Config
# make sure your URLs end with /full, not /simple (which is default)!
# ------
calendars = [{name: 'Private', url: 'PUT ANY PRIVATE XML-URL HERE'},
{name: 'Business', url: 'PUT ANY PRIVATE XML-URL HERE'}]
events = Array.new
SCHEDULER.every '10m', :first_in => 0 do |job|
events = Array.new
min = CGI.escape(DateTime.now().to_s)
max = CGI.escape((DateTime.now()+7).to_s)
calendars.each do |calendar|
url = calendar[:url]+"?singleevents=true&orderby=starttime&start-min=#{min}&start-max=#{max}&fields=entry(gd:when,title,content)"
reader = Nokogiri::XML(open(url))
reader.remove_namespaces!
reader.xpath("//feed/entry").each do |e|
title = e.at_xpath("./title").text
content = e.at_xpath("./content").text
when_node = e.at_xpath("./when")
events.push({title: title,
body: content ? content : "",
calendar: calendar[:name],
when_start_raw: when_node ? DateTime.iso8601(when_node.attribute('startTime').text).to_time.to_i : 0,
when_end_raw: when_node ? DateTime.iso8601(when_node.attribute('endTime').text).to_time.to_i : 0,
when_start: when_node ? DateTime.iso8601(when_node.attribute('startTime').text).to_s : "No time",
when_end: when_node ? DateTime.iso8601(when_node.attribute('endTime').text).to_s : "No time"
})
end
end
events.sort! { |a,b| a[:when_start_raw] <=> b[:when_start_raw] }
events = events.slice!(0,15) # 15 elements is probably enough...
send_event('calendar_events', { events: events })
end
SCHEDULER.every '1m', :first_in => 0 do |job|
events_tmp = Array.new(events)
events_tmp.delete_if{|event| DateTime.now().to_time.to_i>=event[:when_end_raw]}
if events_tmp.count != events.count
events = events_tmp
send_event('calendar_events', { events: events })
end
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #ec663c;
$title-color: rgba(255, 255, 255, 1);
$subtitle-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.7);
$private-color: rgb(123, 209, 72);
$business-color: rgb(255, 173, 70);
// ----------------------------------------------------------------------------
// Widget-calendar styles
// ----------------------------------------------------------------------------
.widget-calendar {
transition: background-color 2s linear;
-moz-transition: background-color 2s linear;
-o-transition: background-color 2s linear;
-webkit-transition: background-color 2s linear;
background-color: $background-color;
.subtitle {
color: $subtitle-color;
font-size: 20px;
margin: 15px 0;
}
.title {
color: $title-color;
font-size: 30px;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(255, 255, 255, 0.7);
}
&.large h3 {
font-size: 65px;
}
}
.calendar-name-private {
background-color: $private-color;
}
.calendar-name-business {
background-color: $business-color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment