smashing 1.3.0 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.