Skip to content

Instantly share code, notes, and snippets.

@netconstructor
Forked from tfohlmeister/README.md
Created June 21, 2013 11:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save netconstructor/5830644 to your computer and use it in GitHub Desktop.
Save netconstructor/5830644 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 humand-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 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. For each calendar you'll have to define a name, so that you might assign custom background colors for events of each calendar.

While the main job is called in larger intervalls, 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.

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 in the /jobs directory.

Put the following in your dashingboard.erb file to the current/next event as well as the one afterwards:

<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 an appropriate name. 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}"
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_time : "No time",
when_end: when_node ? DateTime.iso8601(when_node.attribute('endTime').text).to_time : "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