summaryrefslogtreecommitdiff
path: root/javascripts/dashing.coffee
blob: 58218aecf867b2fcc06b7eba119de8d16fadff60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#= require jquery
#= require es5-shim
#= require batman
#= require batman.jquery


Batman.Filters.prettyNumber = (num) ->
  num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") unless isNaN(num)

Batman.Filters.dashize = (str) ->
  dashes_rx1 = /([A-Z]+)([A-Z][a-z])/g;
  dashes_rx2 = /([a-z\d])([A-Z])/g;

  return str.replace(dashes_rx1, '$1_$2').replace(dashes_rx2, '$1_$2').replace(/_/g, '-').toLowerCase()

Batman.Filters.shortenedNumber = (num) ->
  return num if isNaN(num)
  if num >= 1000000000
    (num / 1000000000).toFixed(1) + 'B'
  else if num >= 1000000
    (num / 1000000).toFixed(1) + 'M'
  else if num >= 1000
    (num / 1000).toFixed(1) + 'K'
  else
    num

class window.Dashing extends Batman.App
  @on 'reload', (data) ->
    window.location.reload(true)

  @root ->
Dashing.params = Batman.URI.paramsFromQuery(window.location.search.slice(1));

class Dashing.Widget extends Batman.View
  constructor:  ->
    # Set the view path
    @constructor::source = Batman.Filters.underscore(@constructor.name)
    super

    @mixin($(@node).data())
    Dashing.widgets[@id] ||= []
    Dashing.widgets[@id].push(@)

    type = Batman.Filters.dashize(@view)
    $(@node).addClass("widget widget-#{type} #{@id}")

  @accessor 'updatedAtMessage', ->
    if updatedAt = @get('updatedAt')
      timestamp = new Date(updatedAt)
      hours = timestamp.getHours()
      minutes = ("0" + timestamp.getMinutes()).slice(-2)
      "Last updated at #{hours}:#{minutes}"

  @::on 'ready', ->
    Dashing.Widget.fire 'ready'

    # In case the events from the server came before the widget was rendered
    lastData = Dashing.lastEvents[@id]
    if lastData
      lastData = @select(lastData)
      @mixin(lastData)
      @onData(lastData)

  receiveData: (data) =>
    data = @select(data)
    @mixin(data)
    @onData(data)

  onData: (data) =>
    # Widgets override this to handle incoming data

  select: (data) =>
    # Widgets override this to transform data before it is applied to the model
    return data

Dashing.AnimatedValue =
  get: Batman.Property.defaultAccessor.get
  set: (k, to) ->
    if !to? || isNaN(to)
      @[k] = to
    else
      timer = "interval_#{k}"
      num = if (!isNaN(@[k]) && @[k]?) then @[k] else 0
      unless @[timer] || num == to
        to = parseFloat(to)
        num = parseFloat(num)
        up = to > num
        num_interval = Math.abs(num - to) / 90
        @[timer] =
          setInterval =>
            num = if up then Math.ceil(num+num_interval) else Math.floor(num-num_interval)
            if (up && num > to) || (!up && num < to)
              num = to
              clearInterval(@[timer])
              @[timer] = null
              delete @[timer]
            @[k] = num
            @set k, to
          , 10
      @[k] = num

Dashing.widgets = widgets = {}
Dashing.lastEvents = lastEvents = {}
Dashing.debugMode = false

source = new EventSource('events')
source.addEventListener 'open', (e) ->
  console.log("Connection opened", e)

source.addEventListener 'error', (e)->
  console.log("Connection error", e)
  if (e.currentTarget.readyState == EventSource.CLOSED)
    console.log("Connection closed")
    setTimeout (->
      window.location.reload()
    ), 5*60*1000

source.addEventListener 'message', (e) ->
  data = JSON.parse(e.data)
  if lastEvents[data.id]?.updatedAt != data.updatedAt
    if Dashing.debugMode
      console.log("Received data for #{data.id}", data)
    lastEvents[data.id] = data
    if widgets[data.id]?.length > 0
      for widget in widgets[data.id]
        widget.receiveData(data)

source.addEventListener 'dashboards', (e) ->
  data = JSON.parse(e.data)
  if Dashing.debugMode
    console.log("Received data for dashboards", data)
  if data.dashboard is '*' or window.location.pathname is "/#{data.dashboard}"
    Dashing.fire data.event, data

$(document).ready ->
  Dashing.run()