Skip to content

Instantly share code, notes, and snippets.

@Brunas
Last active September 15, 2020 22:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Brunas/3f4a08fe875f9bcb883f to your computer and use it in GitHub Desktop.
Save Brunas/3f4a08fe875f9bcb883f to your computer and use it in GitHub Desktop.
Freeday Countdown widget

Description

This is Dashing widget to display countdown to next free day like weekend or bank holiday. It works similarly to Clock with time refreshed every 0.5 seconds.

##Usage

The widget uses Holidays gem and JQuery JPlayer for sound notifications. Put it to /assets/javascripts/jplayer directory.

Put the freeday_countdown.rb file in your /jobs folder, freeday_countdown_settings.json to /assets/config. Put freeday_countdown.coffee, freeday_countdown.html and freeday_countdown.scss to /widgets/freeday_countdown.

Make sure directory /assets/config and /assets/sounds is accessible by Dashing user.

To include the widget in a dashboard, add the following snippet to the dashboard layout file:

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="freeday_countdown_lt" data-view="FreedayCountdown" data-sound="/assets/sounds/Rudimental-Home.mp3"></div>
  <i class="icon-time icon-background"></i>
</li>
<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="freeday_countdown_gb" data-view="FreedayCountdown" data-sound="nosound" data-time-offset="2"></div>
  <i class="icon-time icon-background"></i>
</li>

Widget ID should start with freeday_countdown_. Region ID from settings file is appended.

##Settings

Amend /assets/config/freeday_countdown_settings.json to set workday start and end, lunch duration accordingly to your region.

Put sound file you like to /assets/sounds and use it in widget data-sound attribute value or amend @handleSound CoffeeScript function to use it. I'm using /assets/sounds/Rudimental-Home.mp3 in my example. If you do not wish to hear any sound, specify nosound. I did not try that, but specifying any other URL, e.g. Youtube, should work as well.

If different time zone region widgets are used, specify data-time-offset, to make base point of time calculations the same.

There is no need to restart service if job is already running and settings file is amended.

class Dashing.FreedayCountdown extends Dashing.Widget
ready: ->
setInterval(@countDown, 500)
countDown: =>
today = new Date()
# Today is freeday!
if @parseDate(@get('countdown').date) < today
@set('name', "Today is "+@get('countdown').name)
@set('time', '')
return
# Calculate time
@set('name', "till "+@get('countdown').name)
secs = Math.floor((@parseDate(@get('countdown').date) - today)/1000)
# add time offset hours if specified
secs += $(@node).data('time-offset')*3600 if $(@node).data('time-offset')
@handleSound(secs)
days = Math.floor(secs/86400)
secs -= days*86400
hours = Math.floor(secs/3600)
secs -= hours*3600
mins = Math.floor(secs/60)
secs -= mins*60
timeString = ''
timeString = String(days) + " day" if days > 0
timeString += "s" if days > 1
timeString += " " if days > 0
timeString += @formatTime(hours) + ":" + @formatTime(mins) + ":" + @formatTime(secs)
@set('time', timeString)
formatTime: (i) ->
if i < 10 then "0" + i else i
handleSound: (secs) ->
sound = "/assets/sounds/Rudimental-Home.mp3"
sound = $(@node).data('sound') if $(@node).data('sound')
return if not sound or sound is 'nosound'
region = @get('region')
jp = $(@node).find('#jquery_jplayer_'+region)
if jp.length <= 0 && secs >= 0 && secs <= 200
$(@node).append('<script type="text/javascript" src="/assets/jplayer/jquery.jplayer.js"></script>')
$(@node).append('<div id="jquery_jplayer_'+region+'"/>')
jp = $(@node).find('#jquery_jplayer_'+region)
jp.jPlayer({ solution: "html", supplied: "mp3" }).jPlayer("setMedia", { mp3: sound }).jPlayer("play")
jp.remove() if jp.length >0 && secs > 200 || secs < 0
parseDate: (dStr)->
new Date(dStr.substr(0,4),Number(dStr.substr(5,2))-1,dStr.substr(8,2), dStr.substr(11,2), dStr.substr(14,2), dStr.substr(17,2))
<h2 data-bind="time"></h2>
<h1 data-bind="name"></h1>
require "json"
require "time"
require "holidays"
class FreedayCountdown
DEBUG = 0
CONFIG_FILE = 'assets/config/freeday_countdown_settings.json'
def debug
DEBUG
end
def configFile
CONFIG_FILE
end
# function to validate json
def valid_json? (json)
JSON.parse(json)
return true
rescue JSON::ParserError
return false
end
def get_start_date
Date.today
end
def get_end_date
Date.today.next_month(2)
end
def get_saturdays
days = []
(get_start_date .. get_end_date).select { |d| d.wday.eql? 6 }.each do |d|
days.push({ :date => d, :name => "Week's #{d.cweek.to_s} End" })
end
days
end
def get_holidays(region)
Holidays.between(get_start_date, get_end_date, region)
end
def get_freedays(region)
hols = get_holidays(region)
return get_saturdays if !hols or hols.empty?
# sort by date and name, make it unique
# remove sundays - no one's in office.
# remove free mondays - they go together with weekend
wdays_to_reject = [0, 1]
hols = (hols + get_saturdays).sort_by { |o| [o[:date], o[:name]] }.uniq { |o| o[:date] }.reject { |d| wdays_to_reject.include? d[:date].wday }
# also, remove free days in the middle of free period, e.g. long Christmas weekend on 2014
hols.select.with_index { |d, i| i == 0 || (i > 0 && hols[i - 1][:date] != d[:date]-1)}
end
def get_next_freeday_with_time(region, settings)
frees = get_freedays(region.to_sym)
free = frees.first
time = settings["workdayEndHour"]
time = settings["workdayEndHourBeforeHoliday"] if !free[:name].start_with?("Week's ")
result = { "date" => Time.parse((free[:date]-1).to_s + " " + time), "name" => free[:name] }
puts result if DEBUG > 1
result
end
end
@FC = FreedayCountdown.new()
SCHEDULER.every '1h', :first_in => 0 do |job|
str = IO.read(@FC.configFile)
if str and @FC.valid_json?(str)
JSON.parse(str).each do |region, settings|
puts DateTime.now.to_s+" Countdown is working with #{region}" if @FC.debug > 0
puts [countdown: @FC.get_next_freeday_with_time(region, settings), region: region, settings: settings] if @FC.debug > 1
send_event("freeday_countdown_#{region}", {countdown: @FC.get_next_freeday_with_time(region, settings), region: region, settings: settings})
end
end
end
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #3f4274;
// ----------------------------------------------------------------------------
// Widget-freeday-countdown styles
// ----------------------------------------------------------------------------
.widget-freeday-countdown {
background-color: $background-color;
h1 {
font-size:+3em;
}
h2 {
font-size:+4em;
text-transform: none;
}
}
{"gb":{"workdayEndHour":"17:00","workdayEndHourBeforeHoliday":"17:00","workdayStartHour":"08:30","lunchDuration":"01:00"},"lt":{"workdayEndHour":"18:00","workdayEndHourBeforeHoliday":"17:00","workdayStartHour":"09:00","lunchDuration":"01:00"}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment