acts_as_dashboard 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.3.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{acts_as_dashboard}
8
- s.version = "0.3.2"
8
+ s.version = "0.3.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nick Hoffman"]
12
- s.date = %q{2010-08-04}
12
+ s.date = %q{2010-08-05}
13
13
  s.description = %q{acts_as_dashboard makes it easy to create dashboards in Rails apps. Very little configuration is required. Read the docs to get started.}
14
14
  s.email = %q{nick@deadorange.com}
15
15
  s.extra_rdoc_files = [
@@ -1,305 +1,307 @@
1
- // function includeJavaScriptFile(path) {{{
2
- //
3
- // Creates a JavaScript <script> element and appends it
4
- // to the <head>.
5
- //
6
- function includeJavaScriptFile(path) {
7
- // Ensure that we have a non-empty string.'
8
- if ((typeof(path) != 'string') || (!path))
9
- {return;}
10
-
11
- // Ensure that we can find the <head>.
12
- var head = jQuery('head');
13
- if (!head)
14
- {return;}
15
-
16
- var element = document.createElement('script');
17
- element.type = 'text/javascript';
18
- element.src = path;
19
-
20
- head.append(element);
21
-
22
- return true;
23
- } // }}}
24
-
25
- // function buildTheDashboard() {{{
26
- //
27
- // Determines which dashboard widgets to build,
28
- // builds them, and adds them to the DOM.
29
- //
30
- function buildTheDashboard() {
31
- var parsed_widgets = jQuery.parseJSON(json_widgets);
32
-
33
- jQuery.each(parsed_widgets, function(index, widget) {
34
- if (widget.type == 'number')
35
- {dashboard.addNumberWidget(widget);}
36
- else if (widget.type == 'short_messages')
37
- {dashboard.addShortMessagesWidget(widget);}
38
- else if (widget.type == 'line_graph')
39
- {dashboard.addLineGraphWidget(widget);}
40
- });
41
- } // }}}
42
-
43
- function createUpdateTimerFor(widget) { // {{{
44
- $(this).everyTime(widget.update_interval, widget.name, function() {
45
- widget.updateData();
46
- });
47
- } // }}}
48
-
49
- // Begin Dashboard class. {{{
50
- var Dashboard = new JS.Class({
51
- initialize: function(options) { // {{{
52
- this.basePath = options.basePath;
53
-
54
- this.numberWidgets = new Array();
55
- this.shortMessagesWidgets = new Array();
56
- this.lineGraphWidgets = new Array();
57
-
58
- this.div = jQuery('#dashboard');
59
- this.numberWidgetsDiv = this.div.find('.dashboard-numbers');
60
- this.shortMessagesWidgetsDiv = this.div.find('.dashboard-short-messages');
61
- this.lineGraphWidgetsDiv = this.div.find('.dashboard-line-graphs');
62
- }, // }}}
63
-
64
- addNumberWidget: function(options) { // {{{
65
- var widget = new NumberWidget(options);
66
- var templateDiv = this.numberWidgetsDiv.find('.widget-template');
67
-
68
- var widgetDiv = templateDiv.clone(false)
69
- .removeClass('widget-template')
70
- .addClass('number-widget')
71
- .attr('id', widget.divID())
72
- .appendTo(this.numberWidgetsDiv);
73
-
74
- // Set the new div's title.
75
- widgetDiv.find('.widget-title').html(widget.title);
76
-
77
- widget.setDataDivTo(widgetDiv.find('.widget-data'));
78
- widget.updateData();
79
-
80
- createUpdateTimerFor(widget);
81
-
82
- this.numberWidgets.push(widget);
83
-
84
- widgetDiv.show();
85
- }, // }}}
86
-
87
- addShortMessagesWidget: function(options) { // {{{
88
- var widget = new ShortMessagesWidget(options);
89
- var templateDiv = this.shortMessagesWidgetsDiv.find('.widget-template');
90
-
91
- var widgetDiv = templateDiv.clone(false)
92
- .removeClass('widget-template')
93
- .addClass('short-messages-widget')
94
- .attr('id', widget.divID())
95
- .appendTo(this.shortMessagesWidgetsDiv);
96
-
97
- // Set the new div's title.
98
- widgetDiv.find('.widget-title').html(widget.title);
99
-
100
- widget.setDataDivTo(widgetDiv.find('.widget-data'));
101
- widget.updateData();
102
-
103
- createUpdateTimerFor(widget);
104
-
105
- this.shortMessagesWidgets.push(widget);
106
-
107
- widgetDiv.show();
108
- }, // }}}
109
-
110
- addLineGraphWidget: function(options) { // {{{
111
- var widget = new LineGraphWidget(options);
112
- var templateDiv = this.lineGraphWidgetsDiv.find('.widget-template');
113
-
114
- var widgetDiv = templateDiv.clone(false)
115
- .removeClass('widget-template')
116
- .addClass('line-graph-widget')
117
- .attr('id', widget.divID())
118
- .appendTo(this.lineGraphWidgetsDiv);
119
-
120
- // Set the new div's title.
121
- widgetDiv.find('.widget-title').html(widget.title);
122
-
123
- var dataDiv = widgetDiv.find('.widget-data')
124
- .attr('id', widget.divID() + '-data');
125
-
126
- widget.setDataDivTo(dataDiv);
127
-
128
- widget.updateData();
129
-
130
- // I don't know why, but setting these properties when dataDiv
131
- // is initialized fails to work. They work here, though...
132
- dataDiv.css('height', widget.height)
133
- dataDiv.css('width', widget.width)
134
-
135
- createUpdateTimerFor(widget);
136
-
137
- this.lineGraphWidgets.push(widget);
138
-
139
- widgetDiv.show();
140
- } // }}}
141
- });
142
- // End Dashboard class. }}}
143
-
144
- // Begin DashboardWidget class. {{{
145
- var DashboardWidget = new JS.Class({
146
- initialize: function(options) {
147
- this.type = options.type;
148
- this.name = options.name;
149
- this.title = options.title;
150
- this.update_interval = options.update_interval;
151
- },
152
-
153
- dataURL: function() {
154
- return dashboard.basePath + this.name;
155
- },
156
-
157
- divID: function() {
158
- return this.name + '-' + this.type + '-widget';
159
- },
160
-
161
- setDataDivTo: function(element) {
162
- this.dataDiv = element;
163
- }
164
- });
165
- // End DashboardWidget class. }}}
166
-
167
- // Begin NumberWidget class. {{{
168
- var NumberWidget = new JS.Class(DashboardWidget, {
169
- initialize: function(options) {
170
- options['type'] = 'number';
171
- this.callSuper(options);
172
- },
173
-
174
- updateData: function() {
175
- if (!this.dataDiv)
176
- {return false;}
177
-
178
- // This is needed so that the dataDiv property is accessible with jQuery.get() .
179
- var element = this.dataDiv;
180
-
181
- jQuery.get(this.dataURL(), function(data) {
182
- element.fadeOut(400, function() {
183
- element.html(data);
184
- element.fadeIn();
185
- });
186
- }, 'text');
187
- }
188
- });
189
- // End NumberWidget class. }}}
190
-
191
- // Begin ShortMessagesWidget class. {{{
192
- var ShortMessagesWidget = new JS.Class(DashboardWidget, {
193
- initialize: function(options) {
194
- options['type'] = 'short_messages';
195
- this.callSuper(options);
196
- this.maxDataItems = 5;
197
- },
198
-
199
- firstDataItem: function() {
200
- return this.dataDiv.find('li.widget-data-item:first');
201
- },
202
-
203
- dataItemsCount: function() {
204
- return this.dataDiv.find('li.widget-data-item').length;
205
- },
206
-
207
- createDataItem: function() {
208
- return this.dataDiv.find('li.widget-data-template')
209
- .clone(false)
210
- .removeClass('widget-data-template')
211
- .addClass('widget-data-item');
212
- },
213
-
214
- updateData: function() {
215
- if (!this.dataDiv)
216
- {return false;}
217
-
218
- var new_data = '';
219
- var new_li = this.createDataItem();
220
-
221
- // We use ajax() instead of get() because the "async" option must
222
- // be false. If it isn't, we're unable to determine if data was
223
- // obtained.
224
- var get_result = jQuery.ajax({
225
- url: this.dataURL(),
226
- type: 'GET',
227
- async: false,
228
- cache: false,
229
- dataType: 'text',
230
- timeout: this.updateInterval,
231
- success: function(data) {
232
- new_li.html(data);
233
- new_data = data;
234
- }
235
- });
236
-
237
- // If no data was obtained, return. Otherwise, an empty list item
238
- // will be shown.
239
- if (new_data == '')
240
- {return false;}
241
-
242
- new_li.appendTo(this.dataDiv.find('ul'));
243
-
244
- // Hide the first list item if we've reached the maximum number of
245
- // list items to show in this widget.
246
- if (this.dataItemsCount() > this.maxDataItems) {
247
- var firstDataItem = this.firstDataItem();
248
-
249
- firstDataItem.slideUp(400, function() {
250
- firstDataItem.remove();
251
- });
252
- }
253
-
254
- new_li.slideDown();
255
- }
256
- });
257
- // End ShortMessagesWidget class. }}}
258
-
259
- // Begin LineGraphWidget class. {{{
260
- var LineGraphWidget = new JS.Class(DashboardWidget, {
261
- initialize: function(options) {
262
- this.height = options.height;
263
- this.width = options.width;
264
- this.seriesColours = options.line_colours;
265
- this.x_axis = options.x_axis;
266
-
267
- options.type = 'line_graph';
268
- this.callSuper(options);
269
- },
270
-
271
- updateData: function() {
272
- if (!this.graph)
273
- {this.createGraph();}
274
-
275
- // This is needed so that the dataDiv property is accessible with jQuery.get() .
276
- var graph = this.graph;
277
-
278
- jQuery.get(this.dataURL(), function(data) {
279
- graph.series[0].data = data;
280
- graph.replot({resetAxes: true});
281
- }, 'json');
282
- },
283
-
284
- createGraph: function() {
285
- includeJavaScriptFile('/javascripts/jqplot-0.9.7/plugins/jqplot.dateAxisRenderer.min.js');
286
-
287
- var x_axis_format = {};
288
- if (this.x_axis === 'dates') {
289
- var x_axis_format = {
290
- renderer: jQuery.jqplot.DateAxisRenderer,
291
- tickOptions: {formatString: '%Y-%m-%d'}
292
- }
293
- }
294
-
295
- this.graph = jQuery.jqplot(this.dataDiv.attr('id'), [ [] ], {
296
- title: this.title,
297
- seriesColors: this.seriesColours,
298
- axes: {
299
- xaxis: x_axis_format
300
- }
301
- });
302
- }
303
- });
304
- // End LineGraphWidget class. }}}
305
-
1
+ // function includeJavaScriptFile(path) {{{
2
+ //
3
+ // Creates a JavaScript <script> element and appends it
4
+ // to the <head>.
5
+ //
6
+ function includeJavaScriptFile(path) {
7
+ // Ensure that we have a non-empty string.'
8
+ if ((typeof(path) != 'string') || (!path))
9
+ {return;}
10
+
11
+ // Ensure that we can find the <head>.
12
+ var head = jQuery('head');
13
+ if (!head)
14
+ {return;}
15
+
16
+ var element = document.createElement('script');
17
+ element.type = 'text/javascript';
18
+ element.src = path;
19
+
20
+ head.append(element);
21
+
22
+ return true;
23
+ } // }}}
24
+
25
+ // function buildTheDashboard() {{{
26
+ //
27
+ // Determines which dashboard widgets to build,
28
+ // builds them, and adds them to the DOM.
29
+ //
30
+ function buildTheDashboard() {
31
+ var parsed_widgets = jQuery.parseJSON(json_widgets);
32
+
33
+ jQuery.each(parsed_widgets, function(index, widget) {
34
+ if (widget.type == 'number')
35
+ {dashboard.addNumberWidget(widget);}
36
+ else if (widget.type == 'short_messages')
37
+ {dashboard.addShortMessagesWidget(widget);}
38
+ else if (widget.type == 'line_graph')
39
+ {dashboard.addLineGraphWidget(widget);}
40
+ });
41
+ } // }}}
42
+
43
+ function createUpdateTimerFor(widget) { // {{{
44
+ $(this).everyTime(widget.update_interval, widget.name, function() {
45
+ widget.updateData();
46
+ });
47
+ } // }}}
48
+
49
+ // Begin Dashboard class. {{{
50
+ var Dashboard = new JS.Class({
51
+ initialize: function(options) { // {{{
52
+ this.basePath = options.basePath;
53
+
54
+ this.numberWidgets = new Array();
55
+ this.shortMessagesWidgets = new Array();
56
+ this.lineGraphWidgets = new Array();
57
+
58
+ this.div = jQuery('#dashboard');
59
+ this.numberWidgetsDiv = this.div.find('.dashboard-numbers');
60
+ this.shortMessagesWidgetsDiv = this.div.find('.dashboard-short-messages');
61
+ this.lineGraphWidgetsDiv = this.div.find('.dashboard-line-graphs');
62
+ }, // }}}
63
+
64
+ addNumberWidget: function(options) { // {{{
65
+ var widget = new NumberWidget(options);
66
+ var templateDiv = this.numberWidgetsDiv.find('.widget-template');
67
+
68
+ var widgetDiv = templateDiv.clone(false)
69
+ .removeClass('widget-template')
70
+ .addClass('number-widget')
71
+ .attr('id', widget.divID())
72
+ .appendTo(this.numberWidgetsDiv);
73
+
74
+ // Set the new div's title.
75
+ widgetDiv.find('.widget-title').html(widget.title);
76
+
77
+ widget.setDataDivTo(widgetDiv.find('.widget-data'));
78
+ widget.updateData();
79
+
80
+ createUpdateTimerFor(widget);
81
+
82
+ this.numberWidgets.push(widget);
83
+
84
+ widgetDiv.show();
85
+ }, // }}}
86
+
87
+ addShortMessagesWidget: function(options) { // {{{
88
+ var widget = new ShortMessagesWidget(options);
89
+ var templateDiv = this.shortMessagesWidgetsDiv.find('.widget-template');
90
+
91
+ var widgetDiv = templateDiv.clone(false)
92
+ .removeClass('widget-template')
93
+ .addClass('short-messages-widget')
94
+ .attr('id', widget.divID())
95
+ .appendTo(this.shortMessagesWidgetsDiv);
96
+
97
+ // Set the new div's title.
98
+ widgetDiv.find('.widget-title').html(widget.title);
99
+
100
+ widget.setDataDivTo(widgetDiv.find('.widget-data'));
101
+ widget.updateData();
102
+
103
+ createUpdateTimerFor(widget);
104
+
105
+ this.shortMessagesWidgets.push(widget);
106
+
107
+ widgetDiv.show();
108
+ }, // }}}
109
+
110
+ addLineGraphWidget: function(options) { // {{{
111
+ var widget = new LineGraphWidget(options);
112
+ var templateDiv = this.lineGraphWidgetsDiv.find('.widget-template');
113
+
114
+ var widgetDiv = templateDiv.clone(false)
115
+ .removeClass('widget-template')
116
+ .addClass('line-graph-widget')
117
+ .attr('id', widget.divID())
118
+ .appendTo(this.lineGraphWidgetsDiv);
119
+
120
+ // Set the new div's title.
121
+ widgetDiv.find('.widget-title').html(widget.title);
122
+
123
+ var dataDiv = widgetDiv.find('.widget-data')
124
+ .attr('id', widget.divID() + '-data');
125
+
126
+ widget.setDataDivTo(dataDiv);
127
+
128
+ widget.updateData();
129
+
130
+ // I don't know why, but setting these properties when dataDiv
131
+ // is initialized fails to work. They work here, though...
132
+ dataDiv.css('height', widget.height)
133
+ dataDiv.css('width', widget.width)
134
+
135
+ createUpdateTimerFor(widget);
136
+
137
+ this.lineGraphWidgets.push(widget);
138
+
139
+ widgetDiv.show();
140
+ } // }}}
141
+ });
142
+ // End Dashboard class. }}}
143
+
144
+ // Begin DashboardWidget class. {{{
145
+ var DashboardWidget = new JS.Class({
146
+ initialize: function(options) {
147
+ this.type = options.type;
148
+ this.name = options.name;
149
+ this.title = options.title;
150
+ this.update_interval = options.update_interval;
151
+ },
152
+
153
+ dataURL: function() {
154
+ return dashboard.basePath + this.name;
155
+ },
156
+
157
+ divID: function() {
158
+ return this.name + '-' + this.type + '-widget';
159
+ },
160
+
161
+ setDataDivTo: function(element) {
162
+ this.dataDiv = element;
163
+ }
164
+ });
165
+ // End DashboardWidget class. }}}
166
+
167
+ // Begin NumberWidget class. {{{
168
+ var NumberWidget = new JS.Class(DashboardWidget, {
169
+ initialize: function(options) {
170
+ options['type'] = 'number';
171
+ this.callSuper(options);
172
+ },
173
+
174
+ updateData: function() {
175
+ if (!this.dataDiv)
176
+ {return false;}
177
+
178
+ // This is needed so that the dataDiv property is accessible with jQuery.get() .
179
+ var element = this.dataDiv;
180
+
181
+ jQuery.get(this.dataURL(), function(data) {
182
+ element.fadeOut(400, function() {
183
+ element.html(data);
184
+ element.fadeIn();
185
+ });
186
+ }, 'text');
187
+ }
188
+ });
189
+ // End NumberWidget class. }}}
190
+
191
+ // Begin ShortMessagesWidget class. {{{
192
+ var ShortMessagesWidget = new JS.Class(DashboardWidget, {
193
+ initialize: function(options) {
194
+ options['type'] = 'short_messages';
195
+ this.callSuper(options);
196
+ this.maxDataItems = 5;
197
+ },
198
+
199
+ firstDataItem: function() {
200
+ return this.dataDiv.find('li.widget-data-item:first');
201
+ },
202
+
203
+ dataItemsCount: function() {
204
+ return this.dataDiv.find('li.widget-data-item').length;
205
+ },
206
+
207
+ createDataItem: function() {
208
+ return this.dataDiv.find('li.widget-data-template')
209
+ .clone(false)
210
+ .removeClass('widget-data-template')
211
+ .addClass('widget-data-item');
212
+ },
213
+
214
+ updateData: function() {
215
+ if (!this.dataDiv)
216
+ {return false;}
217
+
218
+ var new_data = '';
219
+ var new_li = this.createDataItem();
220
+
221
+ // We use ajax() instead of get() because the "async" option must
222
+ // be false. If it isn't, we're unable to determine if data was
223
+ // obtained.
224
+ var get_result = jQuery.ajax({
225
+ url: this.dataURL(),
226
+ type: 'GET',
227
+ async: false,
228
+ cache: false,
229
+ dataType: 'text',
230
+ timeout: this.updateInterval,
231
+ success: function(data) {
232
+ new_li.html(data);
233
+ new_data = data;
234
+ }
235
+ });
236
+
237
+ // If no data was obtained, return. Otherwise, an empty list item
238
+ // will be shown.
239
+ if (new_data == '')
240
+ {return false;}
241
+
242
+ // Ensure that we don't show the same data twice in a row.
243
+ if (this.dataDiv.find('li:last-child').html() != new_li.html()) {
244
+ new_li.appendTo(this.dataDiv.find('ul'));
245
+
246
+ // Hide the first list item if we've reached the maximum number of
247
+ // list items to show in this widget.
248
+ if (this.dataItemsCount() > this.maxDataItems) {
249
+ var firstDataItem = this.firstDataItem();
250
+
251
+ firstDataItem.slideUp(400, function() {
252
+ firstDataItem.remove();
253
+ });
254
+ }
255
+
256
+ new_li.slideDown();
257
+ }
258
+ }
259
+ });
260
+ // End ShortMessagesWidget class. }}}
261
+
262
+ // Begin LineGraphWidget class. {{{
263
+ var LineGraphWidget = new JS.Class(DashboardWidget, {
264
+ initialize: function(options) {
265
+ this.height = options.height;
266
+ this.width = options.width;
267
+ this.seriesColours = options.line_colours;
268
+ this.x_axis = options.x_axis;
269
+
270
+ options.type = 'line_graph';
271
+ this.callSuper(options);
272
+ },
273
+
274
+ updateData: function() {
275
+ if (!this.graph)
276
+ {this.createGraph();}
277
+
278
+ // This is needed so that the dataDiv property is accessible with jQuery.get() .
279
+ var graph = this.graph;
280
+
281
+ jQuery.get(this.dataURL(), function(data) {
282
+ graph.series[0].data = data;
283
+ graph.replot({resetAxes: true});
284
+ }, 'json');
285
+ },
286
+
287
+ createGraph: function() {
288
+ includeJavaScriptFile('/javascripts/jqplot-0.9.7/plugins/jqplot.dateAxisRenderer.min.js');
289
+
290
+ var x_axis_format = {};
291
+ if (this.x_axis === 'dates') {
292
+ var x_axis_format = {
293
+ renderer: jQuery.jqplot.DateAxisRenderer,
294
+ tickOptions: {formatString: '%Y-%m-%d'}
295
+ }
296
+ }
297
+
298
+ this.graph = jQuery.jqplot(this.dataDiv.attr('id'), [ [] ], {
299
+ seriesColors: this.seriesColours,
300
+ axes: {
301
+ xaxis: x_axis_format
302
+ }
303
+ });
304
+ }
305
+ });
306
+ // End LineGraphWidget class. }}}
307
+
@@ -2,7 +2,7 @@ module ActsAsDashboard
2
2
  module InstanceMethods
3
3
  def show
4
4
  @json_widgets = dashboard_config.widgets.map {|w| w.attributes}.to_json
5
- @dashboard_path = '/' + self.class.to_s.underscore.sub('_controller', '').singularize + '/widgets/'
5
+ @dashboard_path = "#{ApplicationController.relative_url_root}/" + self.class.to_s.underscore.sub('_controller', '').singularize + '/widgets/'
6
6
 
7
7
  # @dashboard_css_path = File.join(File.dirname(__FILE__), 'public', 'stylesheets', 'dashboard.css')
8
8
  # @dashboard_css = File.open(@dashboard_css_path).read
@@ -239,19 +239,22 @@ var ShortMessagesWidget = new JS.Class(DashboardWidget, {
239
239
  if (new_data == '')
240
240
  {return false;}
241
241
 
242
- new_li.appendTo(this.dataDiv.find('ul'));
243
-
244
- // Hide the first list item if we've reached the maximum number of
245
- // list items to show in this widget.
246
- if (this.dataItemsCount() > this.maxDataItems) {
247
- var firstDataItem = this.firstDataItem();
242
+ // Ensure that we don't show the same data twice in a row.
243
+ if (this.dataDiv.find('li:last-child').html() != new_li.html()) {
244
+ new_li.appendTo(this.dataDiv.find('ul'));
245
+
246
+ // Hide the first list item if we've reached the maximum number of
247
+ // list items to show in this widget.
248
+ if (this.dataItemsCount() > this.maxDataItems) {
249
+ var firstDataItem = this.firstDataItem();
250
+
251
+ firstDataItem.slideUp(400, function() {
252
+ firstDataItem.remove();
253
+ });
254
+ }
248
255
 
249
- firstDataItem.slideUp(400, function() {
250
- firstDataItem.remove();
251
- });
256
+ new_li.slideDown();
252
257
  }
253
-
254
- new_li.slideDown();
255
258
  }
256
259
  });
257
260
  // End ShortMessagesWidget class. }}}
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_dashboard
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 2
10
- version: 0.3.2
9
+ - 3
10
+ version: 0.3.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Nick Hoffman
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-04 00:00:00 -04:00
18
+ date: 2010-08-05 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency