graffable 0.0.2 → 0.0.3

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
  SHA1:
3
- metadata.gz: 46adff9ed7f91eaf984f65e4dea871ce51de43df
4
- data.tar.gz: 18c69537813f8d22bcceec67793f6377b1937f1f
3
+ metadata.gz: e2223326e8c8ba239381e37e462493512fc7b5f9
4
+ data.tar.gz: 3e469d9a364e2e146204ad14cc2edefec26f61c7
5
5
  SHA512:
6
- metadata.gz: 29fd8acb103da34e6674e26d2c0e6f43087de388d46a5dd7d5dac7c99e0eb574ceee77f7bdc6996d1a781b62dcff8be2ba22170a3af1d14018c0e75cde9f2eae
7
- data.tar.gz: c690f97cb951290a6380a8a1ae30613617891172c9f6fee5b2828df41bd8658d1f704c183c883a1eedc372bd7e916ba1c7e721b842e0b5e7a41d9dd410689bcc
6
+ metadata.gz: 607a1e4529864ba28870a84ec4c4e8f984544829a57aa336c53c2593e3316ef4def2eac44d2331e89599522ece482ad7f50eaf92d16c2909e68748c97c8ad6db
7
+ data.tar.gz: 32cca37a38e3c92137b2fed6e49aa4160a2f99c245ee828e961b0268909b46b6deb24a1a67511507481d9db66b07e129e4421a286ac8a670ba1c60e12bc95674
data/.gitignore CHANGED
@@ -1,5 +1,8 @@
1
1
  .*.swp
2
+ .DS_Store
3
+
2
4
  /.env
5
+ /db/*.sql
3
6
  /db/*.sqlite3
4
7
  /db/seed.rb
5
8
  /Gemfile.lock
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']`)
@@ -0,0 +1,2 @@
1
+ web: bundle exec rackup config.ru
2
+
data/Rakefile CHANGED
@@ -1,5 +1,9 @@
1
1
  require 'bundler/gem_tasks'
2
2
 
3
+ require 'dotenv'
4
+ Dotenv.load
5
+ require 'dotenv/tasks'
6
+
3
7
  require './lib/graffable.rb'
4
8
  ENV['GRAFFABLE_DATABASE_URL'] ||= 'sqlite://db/development.sqlite3'
5
9
 
@@ -0,0 +1,12 @@
1
+
2
+ Sequel.migration do
3
+ transaction
4
+
5
+ change do
6
+ alter_table(:reports) do
7
+ add_column :txt, String, size: 255
8
+ end
9
+ end
10
+
11
+ end
12
+
@@ -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
@@ -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 = date_mapping[ tuple.first ]
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);
@@ -1,4 +1,4 @@
1
1
  module Graffable
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
4
4
 
@@ -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.0.3/css/bootstrap.min.css' }
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.3/jquery.min.js' }
9
- %script{ type: 'text/javascript', src: '//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js' }
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.5.js') }
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
- #legend{ style: 'padding-bottom: 1em;' }
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
- // TODO options['yaxis'] = { max: series['max'], min: series['min'], tickDecimals: 0 }
55
- $.plot( "#placeholder", series.data, options );
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.2
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-02-06 00:00:00.000000000 Z
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.5.js
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,9 +0,0 @@
1
- Graffable To Do
2
- ===============
3
- # `GET /groups.json`
4
- # `GET /groups`
5
- # `GET /:group.json`
6
- # `GET /:group`
7
- # `GET /:group/:report.json`
8
- # `GET /:group/:report`
9
-
@@ -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);