smashing 1.3.0 → 1.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f8f8fb6bb541b6c3423dbd9a07a5adf9d68c74b1e40631d8adfd9f483bafc71
4
- data.tar.gz: 39043eca7120a94098d95d3e90555d81d2bd80189cc172dce62dad8f3c082b4b
3
+ metadata.gz: '058b11a398a65314e3f1be01b288a294b5ea529135bd249f05a73664cf1670c8'
4
+ data.tar.gz: 36752e8f83da914912df2a9ac83c27b9f82a6f3c2d19fabe1647916d2ff5bfff
5
5
  SHA512:
6
- metadata.gz: 8056ec91983755e1d60b80acb8098acc2e4c0cd5bdd568e31bf0d154b44a6c77afaba06dc2e0d447ae2dd84e7f3c2d01aaf254f368b1207fb8d0c91e52b3077c
7
- data.tar.gz: 03e3c4e500e57409d98a7cc316fb3f40d829e271f687d7d4076404c4e0e1dd8706c969b2f1cc5b3dc2ed260110df74b045bb4285a7d909046d04b8ce0cdcbb6d
6
+ metadata.gz: 00a26dbd1912da56c8cf19e9a2a0898ec3d2c50d8b0891a582ec0f89b3d864db153b6828311b6ec62466f3cee919a71ee4f7682a9eb4069c6b065067aa9880b5
7
+ data.tar.gz: '090f77812bb062f28130fa5e0fdd073c37f5eabb8f123f4eeb609d2c9a6dc90b014379957061d6974c3e08faba27656e40e7da2be0050bad1e4a511b90a5394c'
data/README.md CHANGED
@@ -1,9 +1,12 @@
1
+ [![Build](https://github.com/Smashing/smashing/actions/workflows/main.yml/badge.svg)](https://github.com/Smashing/smashing/actions/workflows/main.yml)
1
2
  [![Gitter chat](https://badges.gitter.im/smashing.svg)](https://gitter.im/Smashing)
2
3
 
3
4
  # [Smashing](https://github.com/Smashing/smashing/wiki)
4
5
 
5
6
  Smashing, the spiritual successor to [Dashing](https://github.com/Shopify/dashing), is a Sinatra based framework that lets you build excellent dashboards. It looks especially great on TVs.
6
7
 
8
+ ![Smashing logo](./.github/docs/assets/screenshot.png)
9
+
7
10
  ## Community
8
11
 
9
12
  Feel free to submit issues for bugs, new features, and enhancements in [GitHub](https://github.com/Smashing/smashing/issues). For more general questions, or help with widgets, please use the [gitter chatroom](https://gitter.im/Smashing).
@@ -53,8 +53,9 @@ class Dashing.Widget extends Batman.View
53
53
  super
54
54
 
55
55
  @mixin($(@node).data())
56
- Dashing.widgets[@id] ||= []
57
- Dashing.widgets[@id].push(@)
56
+ if @id # skip widgets without id
57
+ Dashing.widgets[@id] ||= []
58
+ Dashing.widgets[@id].push(@)
58
59
 
59
60
  type = Batman.Filters.dashize(@view)
60
61
  $(@node).addClass("widget widget-#{type} #{@id}")
@@ -120,35 +121,43 @@ Dashing.AnimatedValue =
120
121
  Dashing.widgets = widgets = {}
121
122
  Dashing.lastEvents = lastEvents = {}
122
123
  Dashing.debugMode = false
124
+ Dashing.filterEvents = true
123
125
 
124
- source = new EventSource('events')
125
- source.addEventListener 'open', (e) ->
126
- console.log("Connection opened", e)
127
-
128
- source.addEventListener 'error', (e)->
129
- console.log("Connection error", e)
130
- if (e.currentTarget.readyState == EventSource.CLOSED)
131
- console.log("Connection closed")
132
- setTimeout (->
133
- window.location.reload()
134
- ), 5*60*1000
135
-
136
- source.addEventListener 'message', (e) ->
137
- data = JSON.parse(e.data)
138
- if lastEvents[data.id]?.updatedAt != data.updatedAt
139
- if Dashing.debugMode
140
- console.log("Received data for #{data.id}", data)
141
- lastEvents[data.id] = data
142
- if widgets[data.id]?.length > 0
143
- for widget in widgets[data.id]
144
- widget.receiveData(data)
145
-
146
- source.addEventListener 'dashboards', (e) ->
147
- data = JSON.parse(e.data)
148
- if Dashing.debugMode
149
- console.log("Received data for dashboards", data)
150
- if data.dashboard is '*' or window.location.pathname is "/#{data.dashboard}"
151
- Dashing.fire data.event, data
126
+ Dashing.on 'run', ->
127
+ @layout.on 'ready', -> # run only when all widgets are created
128
+ ids = Object.keys(Dashing.widgets)
129
+ url = if Dashing.filterEvents
130
+ 'events?ids=' + encodeURIComponent(ids.join(','))
131
+ else
132
+ 'events'
133
+ source = new EventSource(url)
134
+ source.addEventListener 'open', (e) ->
135
+ console.log("Connection opened", e)
136
+
137
+ source.addEventListener 'error', (e)->
138
+ console.log("Connection error", e)
139
+ if (e.currentTarget.readyState == EventSource.CLOSED)
140
+ console.log("Connection closed")
141
+ setTimeout (->
142
+ window.location.reload()
143
+ ), 5*60*1000
144
+
145
+ source.addEventListener 'message', (e) ->
146
+ data = JSON.parse(e.data)
147
+ if lastEvents[data.id]?.updatedAt != data.updatedAt
148
+ if Dashing.debugMode
149
+ console.log("Received data for #{data.id}", data)
150
+ lastEvents[data.id] = data
151
+ if widgets[data.id]?.length > 0
152
+ for widget in widgets[data.id]
153
+ widget.receiveData(data)
154
+
155
+ source.addEventListener 'dashboards', (e) ->
156
+ data = JSON.parse(e.data)
157
+ if Dashing.debugMode
158
+ console.log("Received data for dashboards", data)
159
+ if data.dashboard is '*' or window.location.pathname is "/#{data.dashboard}"
160
+ Dashing.fire data.event, data
152
161
 
153
162
  $(document).ready ->
154
163
  Dashing.run()
data/lib/dashing/app.rb CHANGED
@@ -25,6 +25,10 @@ helpers do
25
25
  # override with auth logic
26
26
  end
27
27
 
28
+ def h(text)
29
+ Rack::Utils.escape_html(text)
30
+ end
31
+
28
32
  def authenticated?(token)
29
33
  return true unless settings.auth_token
30
34
  token && Rack::Utils.secure_compare(settings.auth_token, token)
@@ -36,7 +40,7 @@ set :sprockets, Sprockets::Environment.new(settings.root)
36
40
  set :assets_prefix, '/assets'
37
41
  set :digest_assets, false
38
42
  set :server, 'thin'
39
- set :connections, []
43
+ set :connections, {}
40
44
  set :history_file, 'history.yml'
41
45
  set :public_folder, File.join(settings.root, 'public')
42
46
  set :views, File.join(settings.root, 'dashboards')
@@ -54,7 +58,7 @@ end
54
58
  settings.sprockets.append_path("assets/#{path}")
55
59
  end
56
60
 
57
- ['widgets', File.expand_path('../../../javascripts', __FILE__)]. each do |path|
61
+ ['widgets', File.expand_path('../../../javascripts', __FILE__)].each do |path|
58
62
  settings.sprockets.append_path(path)
59
63
  end
60
64
 
@@ -77,9 +81,12 @@ end
77
81
  get '/events', :provides => 'text/event-stream' do
78
82
  protected!
79
83
  response.headers['X-Accel-Buffering'] = 'no' # Disable buffering for nginx
84
+ ids = params[:ids] ? params[:ids].split(',').to_set : nil
80
85
  stream :keep_open do |out|
81
- settings.connections << out
82
- out << latest_events
86
+ settings.connections[out] = ids
87
+ settings.history.each do |id, event|
88
+ out << event if ids.nil? || ids.include?(id)
89
+ end
83
90
  out.callback { settings.connections.delete(out) }
84
91
  end
85
92
  end
@@ -126,12 +133,12 @@ get '/views/:widget?.html' do
126
133
  return Tilt[language].new(file).render if File.exist?(file)
127
134
  end
128
135
 
129
- "Drats! Unable to find a widget file named: #{params[:widget]} to render."
136
+ "Drats! Unable to find a widget file named: #{h(params[:widget])} to render."
130
137
  end
131
138
 
132
139
  Thin::Server.class_eval do
133
140
  def stop_with_connection_closing
134
- Sinatra::Application.settings.connections.dup.each(&:close)
141
+ Sinatra::Application.settings.connections.dup.each_key(&:close)
135
142
  stop_without_connection_closing
136
143
  end
137
144
 
@@ -141,10 +148,16 @@ end
141
148
 
142
149
  def send_event(id, body, target=nil)
143
150
  body[:id] = id
144
- body[:updatedAt] ||= (Time.now.to_f * 1000.0).to_i
151
+ body[:updatedAt] ||= (Time.now.to_f * 1000.0).to_i
145
152
  event = format_event(body.to_json, target)
146
153
  Sinatra::Application.settings.history[id] = event unless target == 'dashboards'
147
- Sinatra::Application.settings.connections.each { |out| out << event }
154
+ Sinatra::Application.settings.connections.each { |out, ids|
155
+ begin
156
+ out << event if target == 'dashboards' || ids.nil? || ids.include?(id)
157
+ rescue IOError => e # if the socket is closed an IOError is thrown
158
+ Sinatra::Application.settings.connections.delete(out)
159
+ end
160
+ }
148
161
  end
149
162
 
150
163
  def format_event(body, name=nil)
@@ -153,12 +166,6 @@ def format_event(body, name=nil)
153
166
  str << "data: #{body}\n\n"
154
167
  end
155
168
 
156
- def latest_events
157
- settings.history.inject("") do |str, (_id, body)|
158
- str << body
159
- end
160
- end
161
-
162
169
  def first_dashboard
163
170
  files = Dir[File.join(settings.views, '*')].collect { |f| File.basename(f, '.*') }
164
171
  files -= ['layout']
@@ -1,3 +1,3 @@
1
1
  module Dashing
2
- VERSION = "1.3.0".freeze
2
+ VERSION = "1.3.5".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smashing
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Beauchamp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-04 00:00:00.000000000 Z
11
+ date: 2021-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coffee-script
@@ -16,98 +16,98 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.4.1
19
+ version: '2.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.4.1
26
+ version: '2.4'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: execjs
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.7.0
33
+ version: '2.7'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.7.0
40
+ version: '2.7'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sinatra
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 2.0.0
47
+ version: '2.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 2.0.0
54
+ version: '2.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: sinatra-contrib
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.0.0
61
+ version: '2.0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.0.0
68
+ version: '2.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thin
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.7.2
75
+ version: '1.7'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 1.7.2
82
+ version: '1.7'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rufus-scheduler
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 3.6.0
89
+ version: '3.6'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 3.6.0
96
+ version: '3.6'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: thor
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 1.0.1
103
+ version: '1.0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 1.0.1
110
+ version: '1.0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: sprockets
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 2.2.2
145
+ version: '2.2'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 2.2.2
152
+ version: '2.2'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: rake
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -371,7 +371,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
371
371
  - !ruby/object:Gem::Version
372
372
  version: '0'
373
373
  requirements: []
374
- rubygems_version: 3.1.2
374
+ rubygems_version: 3.2.3
375
375
  signing_key:
376
376
  specification_version: 4
377
377
  summary: The wonderfully excellent dashboard framework.