graffable 0.0.2 → 0.0.3
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 +4 -4
- data/.gitignore +3 -0
- data/CHANGES.md +14 -0
- data/Procfile +2 -0
- data/Rakefile +4 -0
- data/db/migrations/004_add_reports_txt.rb +12 -0
- data/graffable.gemspec +2 -0
- data/lib/graffable/app.rb +67 -12
- data/lib/graffable/public/javascript/jquery.flot.tooltip.min-0.6.6.js +12 -0
- data/lib/graffable/version.rb +1 -1
- data/lib/graffable/views/layout.haml +8 -5
- data/lib/graffable/views/report.haml +13 -4
- metadata +33 -4
- data/TODO.md +0 -9
- data/lib/graffable/public/javascript/jquery.flot.tooltip.min-0.6.5.js +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2223326e8c8ba239381e37e462493512fc7b5f9
|
4
|
+
data.tar.gz: 3e469d9a364e2e146204ad14cc2edefec26f61c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 607a1e4529864ba28870a84ec4c4e8f984544829a57aa336c53c2593e3316ef4def2eac44d2331e89599522ece482ad7f50eaf92d16c2909e68748c97c8ad6db
|
7
|
+
data.tar.gz: 32cca37a38e3c92137b2fed6e49aa4160a2f99c245ee828e961b0268909b46b6deb24a1a67511507481d9db66b07e129e4421a286ac8a670ba1c60e12bc95674
|
data/.gitignore
CHANGED
data/CHANGES.md
CHANGED
@@ -2,6 +2,20 @@
|
|
2
2
|
Graffable Changes
|
3
3
|
=================
|
4
4
|
|
5
|
+
2014-03-12 Graffable v0.0.3
|
6
|
+
---------------------------
|
7
|
+
* Added hourly reports
|
8
|
+
* Reports now include label totals
|
9
|
+
* Reports now sort labels by total
|
10
|
+
* Reports have more descriptive `<title>` and `<h1>` tags
|
11
|
+
* Reports now ordered by description
|
12
|
+
* Reports no longer attempt to plot data when there is no data to plot
|
13
|
+
* Reports now have an optional `txt` column
|
14
|
+
* Update JQuery to v2.1.0
|
15
|
+
* Update jquery.flot.tooltip to v0.6.6
|
16
|
+
* Update Twitter Bootstrap to v3.1.1
|
17
|
+
|
18
|
+
|
5
19
|
2014-02-06 Graffable v0.0.2
|
6
20
|
---------------------------
|
7
21
|
* `Graffable::Database.connect()` now connects to `ENV['DATABASE_URL']` (was `ENV['GRAFFABLE_DATABASE_URL']`)
|
data/Procfile
ADDED
data/Rakefile
CHANGED
data/graffable.gemspec
CHANGED
@@ -25,6 +25,8 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency 'sinatra-flash'
|
26
26
|
|
27
27
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
28
|
+
spec.add_development_dependency 'dotenv'
|
29
|
+
spec.add_development_dependency 'foreman'
|
28
30
|
spec.add_development_dependency 'rake'
|
29
31
|
spec.add_development_dependency 'sqlite3'
|
30
32
|
end
|
data/lib/graffable/app.rb
CHANGED
@@ -26,12 +26,36 @@ module Graffable
|
|
26
26
|
end
|
27
27
|
|
28
28
|
|
29
|
+
# /:group/:report/:year/:month/:day.json
|
30
|
+
get %r{/(.+)/(.+)/(\d{4})/(\d{2})/(\d{2}).(csv|json)} do |group_name, report_name, year, month, day, extension|
|
31
|
+
group = assert_group group_name
|
32
|
+
report = assert_report group, report_name
|
33
|
+
|
34
|
+
# TODO DRY!
|
35
|
+
query = "SELECT year,month,day,hour,label,#{ report[:aggregate].to_s.upcase }(value) AS value " +
|
36
|
+
"FROM numbers " +
|
37
|
+
"WHERE report_id=:report_id " +
|
38
|
+
"AND year=:year " +
|
39
|
+
"AND month=:month " +
|
40
|
+
"AND day=:day " +
|
41
|
+
"GROUP BY year,month,day,hour,label " +
|
42
|
+
"ORDER BY year,month,day,hour,label"
|
43
|
+
dataset = @db.fetch( query, day: day, month: month, report_id: report[:id], year: year )
|
44
|
+
|
45
|
+
case extension
|
46
|
+
when 'csv'
|
47
|
+
return_csv dataset
|
48
|
+
when 'json'
|
49
|
+
return_json dataset, date_formatter: lambda { |y,m,d,h| h }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
29
53
|
# /:group/:report/:year/:month.json
|
30
54
|
get %r{/(.+)/(.+)/(\d{4})/(\d{2}).(csv|json)} do |group_name, report_name, year, month, extension|
|
31
55
|
group = assert_group group_name
|
32
56
|
report = assert_report group, report_name
|
33
57
|
|
34
|
-
# TODO DRY
|
58
|
+
# TODO DRY!
|
35
59
|
query = "SELECT year,month,day,label,#{ report[:aggregate].to_s.upcase }(value) AS value " +
|
36
60
|
"FROM numbers " +
|
37
61
|
"WHERE report_id=:report_id " +
|
@@ -54,7 +78,7 @@ module Graffable
|
|
54
78
|
group = assert_group group_name
|
55
79
|
report = assert_report group, report_name
|
56
80
|
|
57
|
-
# TODO DRY
|
81
|
+
# TODO DRY!
|
58
82
|
query = "SELECT year,month,label,#{ report[:aggregate].to_s.upcase }(value) AS value " +
|
59
83
|
"FROM numbers " +
|
60
84
|
"WHERE report_id=:report_id " +
|
@@ -76,7 +100,7 @@ module Graffable
|
|
76
100
|
group = assert_group group_name
|
77
101
|
report = assert_report group, report_name
|
78
102
|
|
79
|
-
# TODO DRY
|
103
|
+
# TODO DRY!
|
80
104
|
query = "SELECT year,month,day,label,#{ report[:aggregate].to_s.upcase }(value) AS value " +
|
81
105
|
"FROM numbers " +
|
82
106
|
"WHERE report_id=:report_id " +
|
@@ -93,12 +117,35 @@ module Graffable
|
|
93
117
|
end
|
94
118
|
end
|
95
119
|
|
96
|
-
# TODO DRY
|
120
|
+
# TODO DRY!
|
121
|
+
get %r{/(.+)/(.+)/(\d{4})/(\d{2})/(\d{2})} do |group_name, report_name, year, month, day|
|
122
|
+
@group = @groups.detect { |g| group_name == g[:name] }
|
123
|
+
redirect_with_warning( '/', "Report group not found: #{group_name}" ) unless @group
|
124
|
+
|
125
|
+
@reports = @db[:reports].where( group_id: @group[:id] ).order(:description).all
|
126
|
+
@report = @reports.detect { |r| report_name == r[:name] }
|
127
|
+
redirect_with_warning( "/#{group_name}", "Report not found: #{report_name}" ) unless @report
|
128
|
+
|
129
|
+
@data_url = "/#{group_name}/#{report_name}/#{year}/#{month}/#{day}.json"
|
130
|
+
@interval = "#{year}-#{month}-#{day}"
|
131
|
+
|
132
|
+
date = Date.parse( "#{year}-#{month}-#{day}" )
|
133
|
+
prev_day = date - 1
|
134
|
+
next_day = date + 1
|
135
|
+
@previous = "/#{group_name}/#{report_name}/#{ prev_day.year }/#{ prev_day.strftime('%m') }/#{ prev_day.strftime('%d') }"
|
136
|
+
@next = "/#{group_name}/#{report_name}/#{ next_day.year }/#{ next_day.strftime('%m') }/#{ next_day.strftime('%d') }"
|
137
|
+
|
138
|
+
@title = "#{ @report[:description] } - #{ @interval }"
|
139
|
+
|
140
|
+
haml :report
|
141
|
+
end
|
142
|
+
|
143
|
+
# TODO DRY!
|
97
144
|
get %r{/(.+)/(.+)/(\d{4})/(\d{2})} do |group_name, report_name, year, month|
|
98
145
|
@group = @groups.detect { |g| group_name == g[:name] }
|
99
146
|
redirect_with_warning( '/', "Report group not found: #{group_name}" ) unless @group
|
100
147
|
|
101
|
-
@reports = @db[:reports].where( group_id: @group[:id] ).all
|
148
|
+
@reports = @db[:reports].where( group_id: @group[:id] ).order(:description).all
|
102
149
|
@report = @reports.detect { |r| report_name == r[:name] }
|
103
150
|
redirect_with_warning( "/#{group_name}", "Report not found: #{report_name}" ) unless @report
|
104
151
|
|
@@ -109,15 +156,17 @@ module Graffable
|
|
109
156
|
@previous = "/#{group_name}/#{report_name}/#{ date.prev_month.year }/#{ date.prev_month.strftime('%m') }"
|
110
157
|
@next = "/#{group_name}/#{report_name}/#{ date.next_month.year }/#{ date.next_month.strftime('%m') }"
|
111
158
|
|
159
|
+
@title = "#{ @report[:description] } - #{ @interval }"
|
160
|
+
|
112
161
|
haml :report
|
113
162
|
end
|
114
163
|
|
115
|
-
# TODO DRY
|
164
|
+
# TODO DRY!
|
116
165
|
get %r{/(.+)/(.+)/(\d{4})} do |group_name, report_name, year|
|
117
166
|
@group = @groups.detect { |g| group_name == g[:name] }
|
118
167
|
redirect_with_warning( '/', "Report group not found: #{group_name}" ) unless @group
|
119
168
|
|
120
|
-
@reports = @db[:reports].where( group_id: @group[:id] ).all
|
169
|
+
@reports = @db[:reports].where( group_id: @group[:id] ).order(:description).all
|
121
170
|
@report = @reports.detect { |r| report_name == r[:name] }
|
122
171
|
redirect_with_warning( "/#{group_name}", "Report not found: #{report_name}" ) unless @report
|
123
172
|
|
@@ -128,21 +177,25 @@ module Graffable
|
|
128
177
|
@previous = "/#{group_name}/#{report_name}/#{ date.prev_year.year }"
|
129
178
|
@next = "/#{group_name}/#{report_name}/#{ date.next_year.year }"
|
130
179
|
|
180
|
+
@title = "#{ @report[:description] } - #{ @interval }"
|
181
|
+
|
131
182
|
haml :report
|
132
183
|
end
|
133
184
|
|
134
|
-
# TODO DRY
|
185
|
+
# TODO DRY!
|
135
186
|
get '/:group/:report' do
|
136
187
|
@group = @groups.detect { |g| params[:group] == g[:name] }
|
137
188
|
redirect_with_warning( '/', "Report group not found: #{ params[:group] }" ) unless @group
|
138
189
|
|
139
|
-
@reports = @db[:reports].where( group_id: @group[:id] ).all
|
190
|
+
@reports = @db[:reports].where( group_id: @group[:id] ).order(:description).all
|
140
191
|
@report = @reports.detect { |r| params[:report] == r[:name] }
|
141
192
|
redirect_with_warning( "/#{ params[:group] }", "Report not found: #{ params[:report] }" ) unless @report
|
142
193
|
|
143
194
|
@data_url = "/#{ params[:group] }/#{ params[:report] }.json"
|
144
195
|
@interval = 'Recent'
|
145
196
|
|
197
|
+
@title = "#{ @report[:description] } - #{ @interval }"
|
198
|
+
|
146
199
|
haml :report
|
147
200
|
end
|
148
201
|
|
@@ -150,7 +203,7 @@ module Graffable
|
|
150
203
|
@group = @groups.detect{ |g| params[:group] == g[:name] }
|
151
204
|
redirect_with_warning( '/', "Report group not found: #{ params[:group] }" ) unless @group
|
152
205
|
|
153
|
-
@reports = @db[:reports].where( group_id: @group[:id] ).all
|
206
|
+
@reports = @db[:reports].where( group_id: @group[:id] ).order(:description).all
|
154
207
|
haml :group
|
155
208
|
end
|
156
209
|
|
@@ -227,14 +280,16 @@ module Graffable
|
|
227
280
|
|
228
281
|
values = values.sort.reverse.slice( 0 .. opts[:max] - 1 ).reverse if opts[:max] > - 1
|
229
282
|
values.each do |tuple|
|
230
|
-
date
|
283
|
+
date = date_mapping[ tuple.first ]
|
231
284
|
pairs = tuple.last
|
232
285
|
pairs.each_pair do |label, value|
|
233
286
|
unless data.key?(label)
|
234
|
-
data[label] = { data: [] }
|
287
|
+
data[label] = { data: [], total: 0 }
|
235
288
|
data[label][:label] = label unless label.empty?
|
236
289
|
end
|
237
290
|
data[label][:data].push [ date, value ]
|
291
|
+
data[label][:total] = data[label][:total] + value
|
292
|
+
data[label][:label] = "#{label} (#{ data[label][:total] })" unless label.empty?
|
238
293
|
end
|
239
294
|
end
|
240
295
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/*
|
2
|
+
* jquery.flot.tooltip
|
3
|
+
*
|
4
|
+
* description: easy-to-use tooltips for Flot charts
|
5
|
+
* version: 0.6.6
|
6
|
+
* author: Krzysztof Urbas @krzysu [myviews.pl]
|
7
|
+
* website: https://github.com/krzysu/flot.tooltip
|
8
|
+
*
|
9
|
+
* build on 2014-02-10
|
10
|
+
* released under MIT License, 2012
|
11
|
+
*/
|
12
|
+
!function(a){var b={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,monthNames:null,dayNames:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},c=function(a){this.tipPosition={x:0,y:0},this.init(a)};c.prototype.init=function(b){function c(a){var b={};b.x=a.pageX,b.y=a.pageY,e.updateTooltipPosition(b)}function d(a,b,c){var d=e.getDomElement();if(c){var f;f=e.stringFormat(e.tooltipOptions.content,c),d.html(f),e.updateTooltipPosition({x:b.pageX,y:b.pageY}),d.css({left:e.tipPosition.x+e.tooltipOptions.shifts.x,top:e.tipPosition.y+e.tooltipOptions.shifts.y}).show(),"function"==typeof e.tooltipOptions.onHover&&e.tooltipOptions.onHover(c,d)}else d.hide().html("")}var e=this;b.hooks.bindEvents.push(function(b,f){if(e.plotOptions=b.getOptions(),e.plotOptions.tooltip!==!1&&"undefined"!=typeof e.plotOptions.tooltip){e.tooltipOptions=e.plotOptions.tooltipOpts;{e.getDomElement()}a(b.getPlaceholder()).bind("plothover",d),a(f).bind("mousemove",c)}}),b.hooks.shutdown.push(function(b,e){a(b.getPlaceholder()).unbind("plothover",d),a(e).unbind("mousemove",c)})},c.prototype.getDomElement=function(){var b;return a("#flotTip").length>0?b=a("#flotTip"):(b=a("<div />").attr("id","flotTip"),b.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&b.css({background:"#fff","z-index":"1040",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),b},c.prototype.updateTooltipPosition=function(b){var c=a("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,d=a("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;b.x-a(window).scrollLeft()>a(window).innerWidth()-c&&(b.x-=c),b.y-a(window).scrollTop()>a(window).innerHeight()-d&&(b.y-=d),this.tipPosition.x=b.x,this.tipPosition.y=b.y},c.prototype.stringFormat=function(a,b){var c,d,e=/%p\.{0,1}(\d{0,})/,f=/%s/,g=/%x\.{0,1}(\d{0,})/,h=/%y\.{0,1}(\d{0,})/,i="%x",j="%y";if("undefined"!=typeof b.series.threshold?(c=b.datapoint[0],d=b.datapoint[1]):(c=b.series.data[b.dataIndex][0],d=b.series.data[b.dataIndex][1]),null===b.series.label&&b.series.originSeries&&(b.series.label=b.series.originSeries.label),"function"==typeof a&&(a=a(b.series.label,c,d,b)),"undefined"!=typeof b.series.percent&&(a=this.adjustValPrecision(e,a,b.series.percent)),a="undefined"!=typeof b.series.label?a.replace(f,b.series.label):a.replace(f,""),this.isTimeMode("xaxis",b)&&this.isXDateFormat(b)&&(a=a.replace(g,this.timestampToDate(c,this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",b)&&this.isYDateFormat(b)&&(a=a.replace(h,this.timestampToDate(d,this.tooltipOptions.yDateFormat))),"number"==typeof c&&(a=this.adjustValPrecision(g,a,c)),"number"==typeof d&&(a=this.adjustValPrecision(h,a,d)),"undefined"!=typeof b.series.xaxis.ticks&&b.series.xaxis.ticks.length>b.dataIndex&&!this.isTimeMode("xaxis",b)&&(a=a.replace(g,b.series.xaxis.ticks[b.dataIndex].label)),"undefined"!=typeof b.series.yaxis.ticks)for(var k in b.series.yaxis.ticks)if(b.series.yaxis.ticks.hasOwnProperty(k)){var l=this.isCategoriesMode("yaxis",b)?b.series.yaxis.ticks[k].label:b.series.yaxis.ticks[k].v;l===d&&(a=a.replace(h,b.series.yaxis.ticks[k].label))}return"undefined"!=typeof b.series.xaxis.tickFormatter&&(a=a.replace(i,b.series.xaxis.tickFormatter(c,b.series.xaxis).replace(/\$/g,"$$"))),"undefined"!=typeof b.series.yaxis.tickFormatter&&(a=a.replace(j,b.series.yaxis.tickFormatter(d,b.series.yaxis).replace(/\$/g,"$$"))),a},c.prototype.isTimeMode=function(a,b){return"undefined"!=typeof b.series[a].options.mode&&"time"===b.series[a].options.mode},c.prototype.isXDateFormat=function(){return"undefined"!=typeof this.tooltipOptions.xDateFormat&&null!==this.tooltipOptions.xDateFormat},c.prototype.isYDateFormat=function(){return"undefined"!=typeof this.tooltipOptions.yDateFormat&&null!==this.tooltipOptions.yDateFormat},c.prototype.isCategoriesMode=function(a,b){return"undefined"!=typeof b.series[a].options.mode&&"categories"===b.series[a].options.mode},c.prototype.timestampToDate=function(b,c){var d=new Date(1*b);return a.plot.formatDate(d,c,this.tooltipOptions.monthNames,this.tooltipOptions.dayNames)},c.prototype.adjustValPrecision=function(a,b,c){var d,e=b.match(a);return null!==e&&""!==RegExp.$1&&(d=RegExp.$1,c=c.toFixed(d),b=b.replace(a,c)),b};var d=function(a){new c(a)};a.plot.plugins.push({init:d,options:b,name:"tooltip",version:"0.6.6"})}(jQuery);
|
data/lib/graffable/version.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
%html
|
2
2
|
%head
|
3
3
|
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1.0' }
|
4
|
-
%link{ rel: 'stylesheet', type: 'text/css', href: '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.
|
4
|
+
%link{ rel: 'stylesheet', type: 'text/css', href: '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.min.css' }
|
5
5
|
%link{ rel: 'stylesheet', type: 'text/css', href: url('/stylesheets/graffable.css') }
|
6
|
-
%title= 'Metrics'
|
6
|
+
%title= @title ? "Metrics - #{ @title }" : 'Metrics'
|
7
7
|
%body
|
8
|
-
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/jquery/2.0
|
9
|
-
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.
|
8
|
+
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js' }
|
9
|
+
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/js/bootstrap.min.js' }
|
10
10
|
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.min.js' }
|
11
11
|
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.categories.min.js' }
|
12
12
|
%script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.stack.min.js' }
|
13
|
-
%script{ type: 'text/javascript', src: url('/javascript/jquery.flot.tooltip.min-0.6.
|
13
|
+
%script{ type: 'text/javascript', src: url('/javascript/jquery.flot.tooltip.min-0.6.6.js') }
|
14
14
|
|
15
15
|
%nav.navbar.navbar-default{ role: 'navigation' }
|
16
16
|
.navbar-header
|
@@ -50,12 +50,15 @@
|
|
50
50
|
- url = "/#{ @group[:name] }/#{ @report[:name] }"
|
51
51
|
- year = Time.now.year
|
52
52
|
- month = Time.now.strftime("%m")
|
53
|
+
- day = DateTime.now.strftime("%d")
|
53
54
|
%li
|
54
55
|
%a{ href: url(url) } Recent
|
55
56
|
%li
|
56
57
|
%a{ href: url("#{url}/#{year}") }= year
|
57
58
|
%li
|
58
59
|
%a{ href: url("#{url}/#{year}/#{month}") }= "#{year}-#{month}"
|
60
|
+
%li
|
61
|
+
%a{ href: url("#{url}/#{year}/#{month}/#{day}") }= "#{year}-#{month}-#{day}"
|
59
62
|
|
60
63
|
.container
|
61
64
|
.flash
|
@@ -3,14 +3,18 @@
|
|
3
3
|
- if @previous
|
4
4
|
%a{ href: url(@previous) }
|
5
5
|
%span.glyphicon.glyphicon-chevron-left
|
6
|
-
%h1{ style: 'display: inline; padding: 0em 1em;' }= @report[:description]
|
6
|
+
%h1{ style: 'display: inline; padding: 0em 1em;' }= @title || @report[:description]
|
7
7
|
- if @next
|
8
8
|
%a{ href: url(@next) }
|
9
9
|
%span.glyphicon.glyphicon-chevron-right
|
10
10
|
|
11
11
|
#content{ style: 'align: center; margin: auto; padding: 1em; width: 95%;' }
|
12
12
|
#placeholder{ style: 'align: center; height: 75%; margin: auto; padding: 1em; width: 95%;' }
|
13
|
-
#
|
13
|
+
#footer
|
14
|
+
%span#legend{ style: 'float: left; padding-bottom: 1em;' }
|
15
|
+
- if @report[:txt]
|
16
|
+
%span#accordion{ style: 'float: right; padding-bottom: 5em;' }
|
17
|
+
%span= @report[:txt]
|
14
18
|
|
15
19
|
:javascript
|
16
20
|
data_url = "#{ url(@data_url) }";
|
@@ -51,8 +55,13 @@
|
|
51
55
|
var data = [];
|
52
56
|
|
53
57
|
function onDataReceived(series) {
|
54
|
-
|
55
|
-
|
58
|
+
if ( 'undefined' == typeof series.data || ( series.data instanceof Array && 0 == series.data.length ) ) {
|
59
|
+
$('#placeholder').html("<p style='color: red' alignment='center'>No data available for this time period</p>");
|
60
|
+
}
|
61
|
+
else {
|
62
|
+
$.plot( "#placeholder", series.data.sort( function(a,b) { return b.total - a.total } ), options );
|
63
|
+
$( "#accordion" ).accordion( { active: false, collapsible: true } ); // XXX
|
64
|
+
}
|
56
65
|
}
|
57
66
|
|
58
67
|
$.ajax({
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graffable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- blair christensen.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: haml
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: dotenv
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: foreman
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: rake
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,13 +161,14 @@ files:
|
|
133
161
|
- CHANGES.md
|
134
162
|
- Gemfile
|
135
163
|
- LICENSE.txt
|
164
|
+
- Procfile
|
136
165
|
- README.md
|
137
166
|
- Rakefile
|
138
|
-
- TODO.md
|
139
167
|
- config.ru
|
140
168
|
- db/migrations/001_create_groups.rb
|
141
169
|
- db/migrations/002_create_reports.rb
|
142
170
|
- db/migrations/003_create_numbers.rb
|
171
|
+
- db/migrations/004_add_reports_txt.rb
|
143
172
|
- graffable.gemspec
|
144
173
|
- lib/graffable.rb
|
145
174
|
- lib/graffable/app.rb
|
@@ -147,7 +176,7 @@ files:
|
|
147
176
|
- lib/graffable/importer.rb
|
148
177
|
- lib/graffable/migration_task.rb
|
149
178
|
- lib/graffable/public/favicon.ico
|
150
|
-
- lib/graffable/public/javascript/jquery.flot.tooltip.min-0.6.
|
179
|
+
- lib/graffable/public/javascript/jquery.flot.tooltip.min-0.6.6.js
|
151
180
|
- lib/graffable/public/stylesheets/graffable.css
|
152
181
|
- lib/graffable/seed_task.rb
|
153
182
|
- lib/graffable/version.rb
|
data/TODO.md
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* jquery.flot.tooltip
|
3
|
-
*
|
4
|
-
* description: easy-to-use tooltips for Flot charts
|
5
|
-
* version: 0.6.5
|
6
|
-
* author: Krzysztof Urbas @krzysu [myviews.pl]
|
7
|
-
* website: https://github.com/krzysu/flot.tooltip
|
8
|
-
*
|
9
|
-
* build on 2014-01-23
|
10
|
-
* released under MIT License, 2012
|
11
|
-
*/
|
12
|
-
(function(t){var i={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,monthNames:null,dayNames:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},o=function(t){this.tipPosition={x:0,y:0},this.init(t)};o.prototype.init=function(i){function o(t){var i={};i.x=t.pageX,i.y=t.pageY,s.updateTooltipPosition(i)}function e(t,i,o){var e=s.getDomElement();if(o){var n;n=s.stringFormat(s.tooltipOptions.content,o),e.html(n),s.updateTooltipPosition({x:i.pageX,y:i.pageY}),e.css({left:s.tipPosition.x+s.tooltipOptions.shifts.x,top:s.tipPosition.y+s.tooltipOptions.shifts.y}).show(),"function"==typeof s.tooltipOptions.onHover&&s.tooltipOptions.onHover(o,e)}else e.hide().html("")}var s=this;i.hooks.bindEvents.push(function(i,n){s.plotOptions=i.getOptions(),s.plotOptions.tooltip!==!1&&void 0!==s.plotOptions.tooltip&&(s.tooltipOptions=s.plotOptions.tooltipOpts,s.getDomElement(),t(i.getPlaceholder()).bind("plothover",e),t(n).bind("mousemove",o))}),i.hooks.shutdown.push(function(i,s){t(i.getPlaceholder()).unbind("plothover",e),t(s).unbind("mousemove",o)})},o.prototype.getDomElement=function(){var i;return t("#flotTip").length>0?i=t("#flotTip"):(i=t("<div />").attr("id","flotTip"),i.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&i.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),i},o.prototype.updateTooltipPosition=function(i){var o=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;i.x-t(window).scrollLeft()>t(window).innerWidth()-o&&(i.x-=o),i.y-t(window).scrollTop()>t(window).innerHeight()-e&&(i.y-=e),this.tipPosition.x=i.x,this.tipPosition.y=i.y},o.prototype.stringFormat=function(t,i){var o,e,s=/%p\.{0,1}(\d{0,})/,n=/%s/,p=/%x\.{0,1}(\d{0,})/,a=/%y\.{0,1}(\d{0,})/,r="%x",l="%y";return i.series.threshold!==void 0?(o=i.datapoint[0],e=i.datapoint[1]):(o=i.series.data[i.dataIndex][0],e=i.series.data[i.dataIndex][1]),null===i.series.label&&i.series.originSeries&&(i.series.label=i.series.originSeries.label),"function"==typeof t&&(t=t(i.series.label,o,e,i)),i.series.percent!==void 0&&(t=this.adjustValPrecision(s,t,i.series.percent)),t=i.series.label!==void 0?t.replace(n,i.series.label):t.replace(n,""),this.isTimeMode("xaxis",i)&&this.isXDateFormat(i)&&(t=t.replace(p,this.timestampToDate(o,this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",i)&&this.isYDateFormat(i)&&(t=t.replace(a,this.timestampToDate(e,this.tooltipOptions.yDateFormat))),"number"==typeof o&&(t=this.adjustValPrecision(p,t,o)),"number"==typeof e&&(t=this.adjustValPrecision(a,t,e)),i.series.xaxis.ticks!==void 0&&i.series.xaxis.ticks.length>i.dataIndex&&!this.isTimeMode("xaxis",i)&&(t=t.replace(p,i.series.xaxis.ticks[i.dataIndex].label)),i.series.xaxis.tickFormatter!==void 0&&(t=t.replace(r,i.series.xaxis.tickFormatter(o,i.series.xaxis).replace(/\$/g,"$$"))),i.series.yaxis.tickFormatter!==void 0&&(t=t.replace(l,i.series.yaxis.tickFormatter(e,i.series.yaxis).replace(/\$/g,"$$"))),t},o.prototype.isTimeMode=function(t,i){return i.series[t].options.mode!==void 0&&"time"===i.series[t].options.mode},o.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},o.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},o.prototype.timestampToDate=function(i,o){var e=new Date(1*i);return t.plot.formatDate(e,o,this.tooltipOptions.monthNames,this.tooltipOptions.dayNames)},o.prototype.adjustValPrecision=function(t,i,o){var e,s=i.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,o=o.toFixed(e),i=i.replace(t,o)),i};var e=function(t){new o(t)};t.plot.plugins.push({init:e,options:i,name:"tooltip",version:"0.6.1"})})(jQuery);
|