gricer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +84 -0
  3. data/Rakefile +49 -0
  4. data/app/assets/images/gricer/fluid/breadcrumb.png +0 -0
  5. data/app/assets/javascripts/gricer.js.coffee +85 -0
  6. data/app/assets/javascripts/gricer_backend_jquery.js.coffee +352 -0
  7. data/app/assets/javascripts/jquery.flot.js +2599 -0
  8. data/app/assets/javascripts/jquery.flot.pie.js +750 -0
  9. data/app/assets/javascripts/jquery.flot.resize.js +60 -0
  10. data/app/assets/javascripts/jquery.flot.symbol.js +70 -0
  11. data/app/assets/javascripts/worldmap.js +146 -0
  12. data/app/assets/stylesheets/gricer/fluid-jquery-ui.css.scss +1298 -0
  13. data/app/assets/stylesheets/gricer/fluid.css.scss +240 -0
  14. data/app/assets/stylesheets/gricer/helpers/css3.css.scss +21 -0
  15. data/app/controllers/gricer/base_controller.rb +141 -0
  16. data/app/controllers/gricer/capture_controller.rb +42 -0
  17. data/app/controllers/gricer/dashboard_controller.rb +18 -0
  18. data/app/controllers/gricer/requests_controller.rb +42 -0
  19. data/app/controllers/gricer/sessions_controller.rb +24 -0
  20. data/app/helpers/gricer/base_helper.rb +22 -0
  21. data/app/models/gricer/agent.rb +789 -0
  22. data/app/models/gricer/request.rb +239 -0
  23. data/app/models/gricer/session.rb +433 -0
  24. data/app/views/gricer/capture/index.html.erb +1 -0
  25. data/app/views/gricer/dashboard/_menu.html.erb +10 -0
  26. data/app/views/gricer/dashboard/_overview.html.erb +33 -0
  27. data/app/views/gricer/dashboard/index.html.erb +19 -0
  28. data/config/routes.rb +51 -0
  29. data/lib/gricer.rb +36 -0
  30. data/lib/gricer/action_controller/base.rb +28 -0
  31. data/lib/gricer/action_controller/track.rb +132 -0
  32. data/lib/gricer/active_model/statistics.rb +167 -0
  33. data/lib/gricer/config.rb +125 -0
  34. data/lib/gricer/engine.rb +9 -0
  35. data/lib/gricer/localization.rb +3 -0
  36. data/lib/tasks/gricer_tasks.rake +92 -0
  37. data/spec/controllers/gricer/base_controller_spec.rb +207 -0
  38. data/spec/controllers/gricer/capture_controller_spec.rb +44 -0
  39. data/spec/controllers/gricer/dashboard_controller_spec.rb +44 -0
  40. data/spec/controllers/gricer/requests_controller_spec.rb +36 -0
  41. data/spec/controllers/gricer/sessions_controller_spec.rb +37 -0
  42. data/spec/dummy/Rakefile +7 -0
  43. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  44. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  45. data/spec/dummy/app/assets/stylesheets/dashboard.css +4 -0
  46. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  47. data/spec/dummy/app/assets/stylesheets/sessions.css +4 -0
  48. data/spec/dummy/app/controllers/application_controller.rb +23 -0
  49. data/spec/dummy/app/controllers/dashboard_controller.rb +19 -0
  50. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  51. data/spec/dummy/app/helpers/dashboard_helper.rb +2 -0
  52. data/spec/dummy/app/views/dashboard/index.html.erb +236 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +48 -0
  56. data/spec/dummy/config/boot.rb +10 -0
  57. data/spec/dummy/config/cucumber.yml +9 -0
  58. data/spec/dummy/config/database.yml +25 -0
  59. data/spec/dummy/config/environment.rb +5 -0
  60. data/spec/dummy/config/environments/development.rb +27 -0
  61. data/spec/dummy/config/environments/production.rb +51 -0
  62. data/spec/dummy/config/environments/test.rb +39 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/inflections.rb +10 -0
  65. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  66. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  67. data/spec/dummy/config/initializers/session_store.rb +8 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  69. data/spec/dummy/config/locales/en.yml +5 -0
  70. data/spec/dummy/config/routes.rb +11 -0
  71. data/spec/dummy/db/schema.rb +241 -0
  72. data/spec/dummy/log/development.log +0 -0
  73. data/spec/dummy/public/404.html +26 -0
  74. data/spec/dummy/public/422.html +26 -0
  75. data/spec/dummy/public/500.html +26 -0
  76. data/spec/dummy/public/favicon.ico +0 -0
  77. data/spec/dummy/script/rails +6 -0
  78. data/spec/helpers/gricer/base_helper_spec.rb +28 -0
  79. data/spec/lib/gricer/action_controller/track_spec.rb +63 -0
  80. data/spec/models/gricer/agent_spec.rb +829 -0
  81. data/spec/models/gricer/request_spec.rb +145 -0
  82. data/spec/models/gricer/session_spec.rb +209 -0
  83. data/spec/routing/capture_routes_spec.rb +6 -0
  84. data/spec/routing/dashboard_routes_spec.rb +9 -0
  85. data/spec/routing/requests_routes_spec.rb +90 -0
  86. data/spec/routing/sessions_routes_spec.rb +115 -0
  87. data/spec/spec_helper.rb +23 -0
  88. metadata +185 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Sven G. Brönstrup
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,84 @@
1
+ = Gricer
2
+
3
+ Web Analytics Tool for Rails 3.1
4
+
5
+ == Installation
6
+
7
+ * Add Gricer to your Rails application's Gemfile:
8
+
9
+ gem 'rails', '>=3.1rc5'
10
+ gem 'gricer', git: 'https://github.com/gmah/gricer.git'
11
+
12
+ * Include the Gricer's CSS theme to your Rails 3 asset chain (e.g. your application.css[.scss]):
13
+
14
+ /*
15
+ ...
16
+ *= require gricer/fluid
17
+ ...
18
+ */
19
+
20
+ If you are using jquery you may add the default theme unless you use your own jquery-ui theme:
21
+
22
+ *= require gricer/fluid-jquery-ui
23
+
24
+ At the moment there is only the fluid theme. More will come with the time.
25
+
26
+ * Include the Gricer's JS files to your Rails 3 asset chain (e.g. your application.js):
27
+
28
+ //= require gricer
29
+
30
+ For the backend you need to include jquery JS files (the jquery-ui is optional):
31
+
32
+ //= require jquery
33
+ //= require jquery-ui
34
+ //= require jquery_ujs
35
+
36
+ * Add the Gricer's hook to your controllers (or your ApplicationController if you want to track all controllers):
37
+
38
+ class ApplicationController < ActionController::Base
39
+ ...
40
+ gricer_track_requests
41
+ ...
42
+ end
43
+
44
+ * To track values captured by javascript (Flash, Silverlight, screen resolution, ...) add to the end of your layout file:
45
+
46
+ <%= gricer_track_tag %>
47
+
48
+ * Migrate your DB:
49
+
50
+ bundle exec rake db:migrate
51
+
52
+ == Geocoding your visitors
53
+
54
+ * If you want to geocode your visitors add geoip-c to your Gemfile:
55
+
56
+ gem 'geoip-c'
57
+
58
+ * Configure Gricer to use GeoIP (e.g. in an initializer)
59
+
60
+ require 'geoip'
61
+
62
+ Gricer.configure do |config|
63
+ config.geoip_db = GeoIP::City.new("#{PATH_TO_YOUR_GEOIP_DB}/GeoLiteCity.dat", :index, false)
64
+ end
65
+
66
+ == API Documentation
67
+
68
+ * API Documentation can be created by running
69
+ rake doc:yard
70
+ from the Gricer project directory.
71
+ * There is an auto-generated, up-to-the-hour online_documentation[http://gricer.org/api] of the API Documentation.
72
+
73
+
74
+ == Note on Patches/Pull Requests
75
+
76
+ * Fork the project.
77
+ * Make your feature addition or bug fix.
78
+ * Add tests for it. No discussion. No tests, no game. We use rspec and cucumber with associated addons.
79
+ * Commit, do not mess with rakefile, version, or history. If you want to have your own version, thats fine. But bump your version in a seperate commit that can be ignored when pulling.
80
+ * Send me a pull request. Bonus points for topic branches.
81
+
82
+ == Copyright
83
+
84
+ Copyright (c) 2011 Sven G. Brönstrup. See MIT-LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new(:spec)
17
+
18
+ require 'cucumber/rake/task'
19
+ Cucumber::Rake::Task.new(:cucumber)
20
+
21
+ namespace :doc do
22
+ RDoc::Task.new(:rdoc) do |rdoc|
23
+ rdoc.rdoc_dir = 'rdoc'
24
+ rdoc.title = 'Gricer'
25
+ rdoc.options << '--line-numbers' << '--inline-source'
26
+ rdoc.rdoc_files.include('README.rdoc')
27
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
+ end
29
+
30
+ begin
31
+ require 'yard'
32
+
33
+ YARD::Rake::YardocTask.new(:yard) do |t|
34
+ t.files = ['lib/**/*.rb', 'app/**/*.rb', '-', 'README.rdoc', 'MIT-LICENSE']
35
+ t.options = ['--title', 'API - Gricer - Web Analytics Tool for Rails 3.1', '--private', '--protected']
36
+ end
37
+ rescue
38
+ end
39
+ end
40
+
41
+
42
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
43
+ load 'rails/tasks/engine.rake'
44
+
45
+
46
+
47
+ desc "Run RSpec and Cucumber tests"
48
+ task :test => [:spec, :cucumber]
49
+ task :default => :test
@@ -0,0 +1,85 @@
1
+ window.Gricer =
2
+ getFlashVersion: ->
3
+ if navigator?.plugins?.length > 0
4
+ for r in navigator.plugins
5
+ if r.name.indexOf("Shockwave Flash") > -1
6
+ return r.description.split("Shockwave Flash ")[1]
7
+ else
8
+ if window.ActiveXObject
9
+ for q in [12..2]
10
+ try
11
+ g = new ActiveXObject "ShockwaveFlash.ShockwaveFlash." + q
12
+ if g
13
+ return q + ".0"
14
+ catch p
15
+ # nop
16
+ return false
17
+
18
+ hasJava: ->
19
+ if !self.screen && self.java
20
+ return java.awt.Toolkit.getDefaultToolkit() ? 1 : 0
21
+ else
22
+ if navigator?.javaEnabled()
23
+ return navigator.javaEnabled() ? 1 : 0
24
+ return undefined
25
+
26
+ getSilverlightVersion: ->
27
+ version = false;
28
+ if plugin = navigator?.plugins?["Silverlight Plug-In"]
29
+ version = plugin.description
30
+ if version == "1.0.30226.2"
31
+ version = "2.0.30226.2";
32
+ else
33
+ if window.ActiveXObject
34
+ try
35
+ control = new ActiveXObject('AgControl.AgControl')
36
+ q = 1;
37
+ while control.IsVersionSupported(q + '.0')
38
+ q++;
39
+
40
+ version = q-1
41
+ q = 0;
42
+
43
+ while control.IsVersionSupported(version +'.' + q)
44
+ q++
45
+
46
+ version += '.' + (q-1) + '.'
47
+
48
+ i = 10000
49
+ while i >= 1
50
+ q=1;
51
+ while control.IsVersionSupported(version + (q*i))
52
+ q++
53
+ version += (q-1)
54
+
55
+ i = i / 10
56
+ control = null
57
+ catch p
58
+ version = false
59
+
60
+ return version
61
+
62
+ getWindowSize: ->
63
+ if typeof( window.innerWidth ) == 'number'
64
+ # Non-IE
65
+ return {width: window.innerWidth, height: window.innerHeight}
66
+ else if _ref = document.documentElement?.clientWidth
67
+ # IE 6+ in 'standards compliant mode'
68
+ return {width: document.documentElement.clientWidth, height: document.documentElement.clientHeight}
69
+ else if _ref = document.body?.clientWidth
70
+ # IE 4 compatible
71
+ return {width: document.body.clientWidth, height: document.body.clientHeight}
72
+
73
+ prepareValues: ->
74
+ windowsize = Gricer.getWindowSize()
75
+
76
+ {
77
+ f: Gricer.getFlashVersion(),
78
+ j: Gricer.hasJava(),
79
+ sl: Gricer.getSilverlightVersion(),
80
+ sx: screen.width,
81
+ sy: screen.height,
82
+ sd: screen.colorDepth,
83
+ wx: windowsize.width,
84
+ wy: windowsize.height
85
+ }
@@ -0,0 +1,352 @@
1
+ #=require jquery.flot
2
+ #=require jquery.flot.resize
3
+ #=require jquery.flot.symbol
4
+ #=require jquery.flot.pie
5
+
6
+ $.gricer =
7
+ month: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
8
+
9
+ colors: [
10
+ "#5a9bd4", "#f9a65b", "#fd8c96", "#ce7058", "#f15961", "#d77eb4",
11
+ "#9e67ac", "#8cd5f4", "#fede8f", "#fede8f", "#9e67ac", "#b6eea2",
12
+ #"#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"
13
+ ]
14
+ others_color: '#cccccc'
15
+ unknown_color: '#999999'
16
+
17
+ last_called: $('a[data-gricer-dashboard]').first()
18
+
19
+ loading: ->
20
+ $('#gricer-dashboard').hide()
21
+ $('#gricer-container').html('<div class="loading">Loading ...</div>').show()
22
+
23
+ formatPercentage: (value) ->
24
+ (value * 100).toFixed(2) + '%'
25
+
26
+ formatDate: (value, options = {}) ->
27
+ return '' if not value
28
+
29
+ if options.tb
30
+ if $.datepicker != null
31
+ return $.datepicker.formatDate('M<br/>dd', value)
32
+ else
33
+ day = value.getDate()
34
+ day = '0' + day if day < 10
35
+ return '' + @month[value.getMonth()] + '<br/>' + day
36
+ else
37
+ if $.datepicker != undefined
38
+ return $.datepicker.formatDate($.datepicker.RFC_1036, value)
39
+ else
40
+ day = value.getDate()
41
+ day = '0' + day if day < 10
42
+ month = value.getMonth() + 1
43
+ month = '0' + month if month < 10
44
+ return '' + value.getFullYear() + '-' + month + '-' + day
45
+
46
+ formatHour: (value) ->
47
+ return '' if not value
48
+
49
+ hour = value.getHours()
50
+ hour = '0' + hour if hour < 10
51
+
52
+ return hour
53
+
54
+ labelFor: (value) ->
55
+ if value == true or value == 'true'
56
+ return 'Yes'
57
+ if value == false or value == 'false'
58
+ return 'No'
59
+ if value == null or value == ''
60
+ return '(Unknown)'
61
+
62
+ return value
63
+
64
+ typeSelector: (alternatives) ->
65
+ container = $('<div class="type-selector">')
66
+
67
+ for alt in alternatives
68
+ do(alt) ->
69
+ if alt.uri
70
+ container.append($('<a>').attr('href', alt.uri).addClass(alt.type).attr('data-gricer-' + alt.type, true).attr('data-label', alt.type).attr('data-type-selector', true).append(alt.type))
71
+ else
72
+ container.append($('<span>').addClass(alt.type).append(alt.type))
73
+
74
+ return container
75
+
76
+
77
+ blowUpProcessFlotData: (data, from, thru, step) ->
78
+ output = []
79
+
80
+ for timestamp in [from..thru+86400000] by step
81
+ do(timestamp) ->
82
+ value = 0
83
+ for item in data
84
+ do(item) ->
85
+ value = item[1] if item[0] == timestamp
86
+ output.push [timestamp, value]
87
+
88
+ return output
89
+
90
+ updateBreadcrumb: (elem) ->
91
+ $.gricer.last_called = $(elem)
92
+
93
+ label = $(elem).text() || $(elem).attr('data-label')
94
+
95
+ if $(elem).parents('#gricer-menu').length > 0
96
+ $('#gricer-header .path').empty()
97
+ else if $(elem).parents('#gricer-header .path').length > 0
98
+ $(elem).nextAll().remove()
99
+ return
100
+ else if $(elem).attr('data-type-selector')
101
+ label = $('#gricer-header .path a:last').attr('data-label')
102
+ $('#gricer-header .path a:last').remove()
103
+
104
+ $('#gricer-header .path').append( $(elem).clone().attr('data-label', label).html(label) )
105
+
106
+ $('a[data-gricer-process]').live 'click', ->
107
+ $.gricer.loading()
108
+ $.gricer.updateBreadcrumb(this)
109
+
110
+ $.getJSON $(this).attr('href'), {
111
+ from: $('#gricer-from-field').val()
112
+ thru: $('#gricer-thru-field').val()
113
+ }, (data) ->
114
+
115
+ table = $('<table class="process">')
116
+ plot_data = []
117
+
118
+ row = $('<tr>')
119
+ if data.thru-data.from == 0
120
+ date = new Date
121
+ date.setTime data.from
122
+
123
+ row.append( $('<th>').append($.gricer.formatDate(date)) )
124
+ else
125
+ row.append( $('<th>') )
126
+
127
+ table_step = data.step
128
+ table_step = 86400000 if table_step < 86400000 and data.thru-data.from > 0
129
+
130
+ # Needs improvement for durations over a month
131
+
132
+ for timestamp in [data.from..data.thru+86399999] by table_step
133
+ do(timestamp) ->
134
+ date = new Date
135
+ date.setTime timestamp
136
+
137
+ if table_step >= 86400000
138
+ date_string = $.gricer.formatDate(date, {tb: (data.thru-data.from > 86400000*6)})
139
+ else
140
+ date_string = $.gricer.formatHour(date)
141
+
142
+ row.append($('<th>').append($('<span>').append date_string))
143
+
144
+ table.append row
145
+
146
+ $('#gricer-container').html($('<div class="data">').append table)
147
+
148
+ chart = $('<div class="flot-chart">').append $('<div id="flot-line-chart">')
149
+
150
+ $('#gricer-container').append(chart).append($.gricer.typeSelector data.alternatives)
151
+
152
+ i = 0
153
+ for key, value of data.data
154
+ do(key, value) ->
155
+ detail_link = null
156
+ graph = $.gricer.colors[i]
157
+
158
+ label = label_row = $('<td>')
159
+ if data.detail_uri
160
+ label = $('<a data-gricer-process="true"></a>').attr('href', data.detail_uri.replace('%25%7Bself%7D', encodeURI(key)))
161
+ label_row.append(label)
162
+
163
+ if graph
164
+ label.append($('<span class="badge" style="background:' + $.gricer.colors[i] + '">'))
165
+ else
166
+ label.append($('<span class="badge">'))
167
+
168
+ lable_text = $.gricer.labelFor key
169
+ label.attr('data-label', lable_text)
170
+ label.append(lable_text)
171
+
172
+ row = $('<tr>').append( label_row )
173
+
174
+ for timestamp in [data.from..data.thru+86399999] by table_step
175
+ do(timestamp) ->
176
+ count = 0
177
+ for item in value
178
+ do(item) ->
179
+ count += item[1] if item[0] >= timestamp and item[0] < timestamp + table_step
180
+ count = '' if count == 0
181
+ row.append($('<td class="number">').append(count))
182
+ table.append(row)
183
+
184
+ if $.gricer.colors[i]
185
+ plot_data.push
186
+ label: $.gricer.labelFor key
187
+ data: $.gricer.blowUpProcessFlotData value, data.from, data.thru, data.step
188
+ color: $.gricer.colors[i]
189
+ lines:
190
+ show: true
191
+ points:
192
+ show: false
193
+ symbol: 'cross'
194
+ i++
195
+
196
+ $.plot $("#flot-line-chart"), plot_data,
197
+ xaxis:
198
+ mode: 'time',
199
+ min: data.from,
200
+ max: data.thru+86400000
201
+ yaxis:
202
+ min: 0
203
+ legend:
204
+ show: false
205
+ grid:
206
+ color: $("#flot-line-chart").css('color')
207
+ borderColor: 'transparent'
208
+ colors: $.gricer.colors
209
+
210
+ return false
211
+
212
+ $('a[data-gricer-spread]').live 'click', ->
213
+ $.gricer.loading()
214
+ $.gricer.updateBreadcrumb(this)
215
+
216
+ $.getJSON $(this).attr('href'), {
217
+ from: $('#gricer-from-field').val()
218
+ thru: $('#gricer-thru-field').val()
219
+ }, (data) ->
220
+ table = $('<table>')
221
+ plot_data = []
222
+
223
+ row = $('<tr>')
224
+ row.append( $('<th>') )
225
+ row.append( $('<th>').append('Count') )
226
+ row.append( $('<th>').append('Percentage') )
227
+ table.append row
228
+
229
+ i = 0
230
+ others = 0
231
+ unknown = 0
232
+
233
+ for line in data.data
234
+ do(line) ->
235
+ if line[0] == null
236
+ unknown += line[1]
237
+ else
238
+ detail_link = null
239
+ graph = data.data.length < 4 or $.gricer.colors[i] and line[1]/data.total > 0.05
240
+ label = label_row = $('<td>')
241
+ if data.detail_uri
242
+ label = $('<a data-gricer-spread="true"></a>').attr('href', data.detail_uri.replace('%25%7Bself%7D', encodeURI(line[0])))
243
+ label_row.append(label)
244
+
245
+ if graph
246
+ label.append($('<span class="badge" style="background:' + $.gricer.colors[i] + '">'))
247
+ else
248
+ label.append($('<span class="badge">'))
249
+
250
+ label_text = $.gricer.labelFor(line[0])
251
+ label.attr('data-label', label_text)
252
+ label.append(label_text)
253
+
254
+ row = $('<tr>')
255
+ .append( label_row )
256
+ .append( $('<td class="number">').append(line[1]) )
257
+ .append( $('<td class="number">').append($.gricer.formatPercentage(line[1]/data.total)) )
258
+
259
+ table.append row
260
+
261
+ if graph
262
+ plot_data.push
263
+ label: $.gricer.labelFor line[0]
264
+ data: line[1]
265
+ color: $.gricer.colors[i]
266
+ i++
267
+ else
268
+ others += line[1]
269
+
270
+ if others > 0
271
+ plot_data.push
272
+ label: 'Others'
273
+ data: others
274
+ color: $.gricer.others_color
275
+
276
+ if unknown > 0
277
+ plot_data.push
278
+ label: $.gricer.labelFor null
279
+ data: unknown
280
+ color: $.gricer.unknown_color
281
+
282
+ row = $('<tr>')
283
+ .append(
284
+ $('<td>')
285
+ .append($('<span class="badge" style="background:' + $.gricer.unknown_color + '">'))
286
+ .append($.gricer.labelFor null)
287
+ )
288
+ .append( $('<td class="number">').append(unknown) )
289
+ .append( $('<td class="number">').append($.gricer.formatPercentage(unknown/data.total)) )
290
+
291
+ table.append row
292
+
293
+
294
+ $('#gricer-container').html($('<div class="data">').append table)
295
+
296
+ chart = $('<div class="flot-chart">').append $('<div id="flot-pie-chart">')
297
+
298
+ $('#gricer-container').append(chart).append($.gricer.typeSelector(data.alternatives))
299
+
300
+ $.plot $("#flot-pie-chart"), plot_data,
301
+ series:
302
+ pie:
303
+ show: true
304
+ stroke:
305
+ color: $("#flot-pie-chart").css('background-color')
306
+ label:
307
+ formatter: (label, slice) ->
308
+ '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'</div>'
309
+ legend:
310
+ show: false
311
+ colors: $.gricer.colors
312
+
313
+ return false
314
+
315
+ $('a[data-gricer-dashboard]').live 'click', ->
316
+ $.gricer.loading()
317
+ $.gricer.updateBreadcrumb(this)
318
+
319
+ $('#gricer-container').load $(this).attr('href'),
320
+ from: $('#gricer-from-field').val()
321
+ thru: $('#gricer-thru-field').val()
322
+
323
+ return false
324
+
325
+ $('#gricer-menu a').live 'click', ->
326
+ $('#gricer-menu a.active').removeClass('active')
327
+ $(this).addClass('active')
328
+ return false
329
+
330
+ jQuery ->
331
+ $('#gricer-menu a:first')?.click();
332
+
333
+ if $.datepicker != undefined
334
+ dates = $('#gricer-from-field, #gricer-thru-field').datepicker
335
+ defaultDate: "+1w"
336
+ changeMonth: true
337
+ changeYear: true
338
+ numberOfMonths: 1
339
+ dateFormat: 'yy-mm-dd'
340
+ maxDate: new Date
341
+ onSelect: (selectedDate) ->
342
+ if this.id == "gricer-from-field"
343
+ option = 'minDate'
344
+ else
345
+ option = 'maxDate'
346
+
347
+ instance = $(this).data 'datepicker'
348
+ dateFormat = instance.settings.dateFormat || $.datepicker._defaults.dateFormat
349
+ date = $.datepicker.parseDate dateFormat, selectedDate, instance.settings
350
+ dates.not(this).datepicker 'option', option, date
351
+ onClose: (dateText, inst) ->
352
+ $.gricer.last_called.click()