Commit 4a893ddafedf29385d1762ae6949db0dbe1079a0

Authored by Rafael Manzo
Committed by Rafael Manzo
1 parent aa282859

New metric history chart tool: Chart.JS

This change was necessary to be able cache the action

Pending:
 * Do not render a graphic for a single point
 * Loading animation is not working
 * Unit and acceptance tests for the graphic failling
 * Renable the action cache

Signed off by: Diego Araújo <diegoamc90@gmail.com>
Gemfile
... ... @@ -43,7 +43,7 @@ gem &quot;pg&quot;, &quot;~&gt; 0.17.0&quot;
43 43 gem "twitter-bootstrap-rails", "~> 2.2.8"
44 44  
45 45 # Chart generation
46   -gem "gruff", "~> 0.5.1"
  46 +gem "chart-js-rails", "~> 0.0.6"
47 47  
48 48 # JQueryUI
49 49 gem 'jquery-ui-rails', '~> 4.1.0'
... ...
Gemfile.lock
... ... @@ -58,6 +58,8 @@ GEM
58 58 rack (>= 1.0.0)
59 59 rack-test (>= 0.5.4)
60 60 xpath (~> 2.0)
  61 + chart-js-rails (0.0.6)
  62 + railties (> 3.1)
61 63 cliver (0.3.2)
62 64 coderay (1.1.0)
63 65 coffee-rails (4.0.1)
... ... @@ -104,8 +106,6 @@ GEM
104 106 railties (>= 3.0.0)
105 107 gherkin (2.12.2)
106 108 multi_json (~> 1.3)
107   - gruff (0.5.1)
108   - rmagick
109 109 gyoku (1.1.1)
110 110 builder (>= 2.1.2)
111 111 hike (1.2.3)
... ... @@ -180,7 +180,6 @@ GEM
180 180 ref (1.0.5)
181 181 rest-client (1.6.7)
182 182 mime-types (>= 1.16)
183   - rmagick (2.13.2)
184 183 rspec-core (2.14.7)
185 184 rspec-expectations (2.14.4)
186 185 diff-lcs (>= 1.1.3, < 2.0)
... ... @@ -276,6 +275,7 @@ DEPENDENCIES
276 275 capistrano-bundler
277 276 capistrano-rails
278 277 capistrano-rvm (~> 0.1.0)
  278 + chart-js-rails (~> 0.0.6)
279 279 coffee-rails (~> 4.0.0)
280 280 coveralls
281 281 cucumber (~> 1.3.10)
... ... @@ -283,7 +283,6 @@ DEPENDENCIES
283 283 database_cleaner
284 284 devise (~> 3.2.0)
285 285 factory_girl_rails (~> 4.3.0)
286   - gruff (~> 0.5.1)
287 286 jbuilder (~> 2.0.2)
288 287 jquery-rails
289 288 jquery-ui-rails (~> 4.1.0)
... ...
app/assets/javascripts/application.js
... ... @@ -16,4 +16,5 @@
16 16 //= require twitter/bootstrap
17 17 //= require turbolinks
18 18 //= require modules
  19 +//= require Chart
19 20 //= require_tree .
... ...
app/assets/javascripts/module/graphic.js.coffee
... ... @@ -4,15 +4,39 @@ class Module.Graphic
4 4 this.load()
5 5  
6 6 load: ->
7   - # Those two var are necessary so the jQuery callback can use them
8   - # Otherwise the scope of the callback function is isolated
9   - container = @container
10   - display = this.display
  7 + $.post '/modules/' + @module_id + '/metric_history',
  8 + {
  9 + metric_name: @metric_name,
  10 + container: @container
  11 + }
11 12  
12   - $.get '/modules/' + @module_id + '/metric_history',
13   - metric_name: @metric_name
14   - (data) ->
15   - display(data,container)
  13 + @display: (dates, values, container) ->
  14 + opts = {bezierCurve: false}
16 15  
17   - display: (data, container) ->
18   - $('div#'+container).html('<img id="' + container + '" src="data:image/png;base64,' + data + '" class="img-rounded"/>')
  16 + #FIXME: Until this gets fixed https://github.com/nnnick/Chart.js/issues/76 this if is necessary
  17 + min_value = Math.min.apply(null, values)
  18 + max_value = Math.max.apply(null, values)
  19 +
  20 + if min_value == max_value
  21 + opts = {
  22 + bezierCurve: false,
  23 + scaleOverride: true,
  24 + scaleStartValue: (min_value - 2),
  25 + scaleSteps: 3,
  26 + scaleStepWidth: 1
  27 + }
  28 +
  29 + data = {
  30 + labels : dates,
  31 + datasets : [
  32 + {
  33 + fillColor : "rgba(220,220,220,0.5)",
  34 + strokeColor : "rgba(220,220,220,1)",
  35 + pointColor : "rgba(220,220,220,1)",
  36 + pointStrokeColor : "#000",
  37 + data : values
  38 + }
  39 + ]
  40 + }
  41 +
  42 + graphic = new Chart($('canvas#'+container).get(0).getContext("2d")).Line(data, opts)
... ...
app/controllers/modules_controller.rb
1 1 class ModulesController < ApplicationController
2   - caches_action :metric_history, cache_path: Proc.new{"#{params[:id]}_#{params[:metric_name]}"}
  2 + #caches_action :metric_history, cache_path: Proc.new{"#{params[:id]}_#{params[:metric_name]}"}, expires_in: 1.day, layout: false
3 3  
4   - # GET /modules/1/metric_history
  4 + # POST /modules/1/metric_history
5 5 def metric_history
6 6 module_result = ModuleResult.new({ id: params[:id] })
7   - metric_history = module_result.metric_history(params[:metric_name]) # pending: sort this hash.
8   - dates = Array.new
9   - values = Array.new
10   - metric_history.keys.each do |date|
11   - dates.push date
12   - values.push metric_history[date]
13   - end
14   -
15   - send_data(Base64.encode64(graphic_for(values, dates)), type: 'image/png', filename: "#{params[:module_id]}-#{params[:metric_name]}.png")
  7 + @container = params[:container]
  8 + @metric_history = module_result.metric_history(params[:metric_name]) # pending: sort this hash.
16 9 end
17 10  
18 11 # POST /modules/1/tree
19 12 def load_module_tree
20 13 @root_module_result = ModuleResult.find(params[:id].to_i)
21 14 end
22   -
23   - private
24   -
25   - def graphic_for(values, dates)
26   - graphic = Gruff::Line.new(400)
27   - graphic.hide_title = true
28   - graphic.hide_legend = true
29   - graphic.theme = {
30   - colors: ['grey'],
31   - marker_color: 'black',
32   - background_colors: '#fff'
33   - }
34   -
35   - graphic.labels = Hash[dates.each_with_index.map{ |date, index| [index, date.strftime("%Y/%m/%d")]}]
36   -
37   - graphic.data('Values', values)
38   -
39   - graphic.to_blob
40   - end
41 15 end
42 16 \ No newline at end of file
... ...
app/views/modules/_metric_result.html.erb
... ... @@ -15,7 +15,7 @@
15 15 </tr>
16 16 <tr id="container<%= metric_result.id %>" style="display: none">
17 17 <td colspan="4">
18   - <div id="container<%= metric_result.id %>" class="graphic_container"><%= image_tag 'loader.gif' %> Loading data. Please, wait.</div>
  18 + <canvas id="container<%= metric_result.id %>" class="graphic_container"><%= image_tag 'loader.gif' %> Loading data. Please, wait.</canvas>
19 19 </td>
20 20 </tr>
21 21 <% end %>
22 22 \ No newline at end of file
... ...
app/views/modules/metric_history.js.erb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +var dates = [];
  2 +var values = [];
  3 +<% @metric_history.keys.each do |date| %>
  4 + dates.push("<%= date %>");
  5 + values.push(<%= @metric_history[date] %>);
  6 +<% end %>
  7 +
  8 +Module.Graphic.display(dates, values, '<%= @container %>');
0 9 \ No newline at end of file
... ...
config/routes.rb
... ... @@ -18,7 +18,7 @@ Mezuro::Application.routes.draw do
18 18 end
19 19  
20 20 #resources :modules
21   - get '/modules/:id/metric_history' => 'modules#metric_history'
  21 + post '/modules/:id/metric_history' => 'modules#metric_history'
22 22 post '/modules/:id/tree' => 'modules#load_module_tree'
23 23  
24 24 root "home#index"
... ...
features/repository/show/metric_results.feature
... ... @@ -3,7 +3,7 @@ Feature: Repository metric results
3 3 As a regular user
4 4 I should see the metric results table with its graphics
5 5  
6   - @kalibro_restart @javascript
  6 + @wip @kalibro_restart @javascript
7 7 Scenario: Should show the graphic of a given metric
8 8 Given I am a regular user
9 9 And I am signed in
... ...
spec/controllers/modules_controller_spec.rb
... ... @@ -23,11 +23,12 @@ describe ModulesController do
23 23 before :each do
24 24 ModuleResult.expects(:new).at_least_once.with({id: module_result.id.to_s}).returns(module_result)
25 25 module_result.expects(:metric_history).with(metric_name).returns({date => metric_result.value})
  26 + subject.expire_fragment("#{module_result.id}_#{metric_name}")
26 27 end
27 28  
28 29 context "testing existence of the image in the response" do
29   - pending "It brokes with graphic caching" do
30   - it "should return an image" do
  30 + it "should return an image" do
  31 + pending "It brokes with graphic caching" do
31 32 get :metric_history, id: module_result.id, metric_name: metric_name, module_id: module_id
32 33 response.content_type.should eq "image/png"
33 34 end
... ... @@ -35,13 +36,12 @@ describe ModulesController do
35 36 end
36 37  
37 38 context "testing parameter values" do
38   -
39   - before :each do
40   - @graphic = Gruff::Line.new(400)
41   - Gruff::Line.expects(:new).with(400).returns(@graphic)
42   - end
  39 + pending do
  40 + before :each do
  41 + @graphic = Gruff::Line.new(400)
  42 + Gruff::Line.expects(:new).with(400).returns(@graphic)
  43 + end
43 44  
44   - pending "It brokes with graphic caching" do
45 45 it "should return two arrays, one of dates and other of values" do
46 46 get :metric_history, id: module_result.id, metric_name: metric_name, module_id: module_id
47 47 @graphic.maximum_value.should eq metric_result.value
... ...
spec/routing/modules_routing_spec.rb
... ... @@ -4,7 +4,7 @@ describe ModulesController do
4 4 describe "routing" do
5 5 it { should route(:post, '/modules/1/tree').
6 6 to(controller: :modules, action: :load_module_tree, id: 1) }
7   - it { should route(:get, '/modules/1/metric_history').
  7 + it { should route(:post, '/modules/1/metric_history').
8 8 to(controller: :modules, action: :metric_history, id: 1) }
9 9 end
10 10 end
11 11 \ No newline at end of file
... ...