i_wonder 0.0.1 → 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.
- data/README.rdoc +1 -24
- data/app/assets/javascripts/i_wonder/application.js +1 -0
- data/app/assets/javascripts/i_wonder/reports.js +11 -1
- data/app/assets/stylesheets/i_wonder/_shared.css.scss +6 -0
- data/app/assets/stylesheets/i_wonder/application.css.scss +2 -5
- data/app/assets/stylesheets/i_wonder/reports.css.scss +7 -0
- data/app/controllers/i_wonder/reports_controller.rb +36 -3
- data/app/models/i_wonder/event.rb +16 -6
- data/app/models/i_wonder/metric.rb +57 -14
- data/app/models/i_wonder/report.rb +2 -2
- data/app/models/i_wonder/snapshot.rb +2 -1
- data/app/views/i_wonder/events/index.html.erb +4 -0
- data/app/views/i_wonder/metrics/_options_for_custom.html.erb +2 -2
- data/app/views/i_wonder/metrics/_options_for_model_counter.html.erb +2 -2
- data/app/views/i_wonder/metrics/index.html.erb +3 -1
- data/app/views/i_wonder/reports/_form.html.erb +1 -1
- data/app/views/i_wonder/reports/_line_report.html.erb +10 -33
- data/app/views/i_wonder/reports/_line_report.js.erb +20 -0
- data/app/views/layouts/i_wonder.html.erb +4 -0
- data/db/migrate/20111022230720_i_wonder_migrations.rb +5 -0
- data/lib/i_wonder/configuration.rb +3 -3
- data/lib/i_wonder/logging/middleware.rb +5 -4
- data/lib/i_wonder/version.rb +1 -1
- data/lib/tasks/i_wonder_tasks.rake +4 -0
- data/test/dummy/app/assets/javascripts/application.js +1 -0
- data/test/dummy/db/schema.rb +5 -0
- data/test/dummy/log/development.log +1941 -0
- data/test/dummy/log/test.log +25698 -0
- data/test/dummy/tmp/cache/assets/D8E/250/sprockets%2Fefe57e932e1d26c3b6af42a5311f0a1c +0 -0
- data/test/dummy/tmp/cache/assets/DA7/BA0/sprockets%2F463a9dd811f2418d96fa72cfe05fb8cd +0 -0
- data/test/integration/i_wonder/reports_controller_test.rb +3 -3
- data/test/unit/i_wonder/event_test.rb +25 -0
- data/test/unit/i_wonder/metric_collection_test.rb +53 -29
- data/test/unit/i_wonder/metric_creation_test.rb +9 -7
- data/test/unit/i_wonder/report_test.rb +9 -9
- metadata +22 -23
- data/test/dummy/tmp/pids/server.pid +0 -1
data/README.rdoc
CHANGED
@@ -54,29 +54,6 @@ Add the engine to your routes. This is where the dashboard will be hosted
|
|
54
54
|
mount IWonder::Engine => "/super_analytics_engine"
|
55
55
|
end
|
56
56
|
|
57
|
-
This engine will use your standard application layout (unless you set a different layout in the configurations explained later). Whichever layout you use, you
|
58
|
-
must include a yield in the HTML header so the CSS and Javascript can be loaded.
|
59
|
-
|
60
|
-
<%= yield :extra_scripts_and_styles %>
|
61
|
-
|
62
|
-
This engine also assumes that your layout will handle the flash notifications.
|
63
|
-
|
64
|
-
===== Example application layout:
|
65
|
-
|
66
|
-
<html>
|
67
|
-
<head>
|
68
|
-
|
69
|
-
... your javascript/css/meta/header stuff here ...
|
70
|
-
|
71
|
-
<%= yield :extra_scripts_and_styles %>
|
72
|
-
</head>
|
73
|
-
<body>
|
74
|
-
<%= notifications %>
|
75
|
-
<%= yield %>
|
76
|
-
</body>
|
77
|
-
</html
|
78
|
-
|
79
|
-
|
80
57
|
=== Setting up the hourly cron task
|
81
58
|
|
82
59
|
This gem hooks into the "<code>rake cron</code>" request. It can't take snapshots of your metrics any faster than this cron is run. We recommend every hour.
|
@@ -103,7 +80,7 @@ You can choose to navigate directly to the dashboard. If you want to include a l
|
|
103
80
|
|
104
81
|
If you want to configure this gem, add this to an initializer.
|
105
82
|
|
106
|
-
IWonder.
|
83
|
+
IWonder.configure do |c|
|
107
84
|
c.controllers_to_ignore = [] # These are all the controllers which don't log any events (i_wonder is also ignored)
|
108
85
|
c.only_log_hits_on_200 = true # By default hits and new visitors won't be logged on anything but a 200 or 304 (not modified). Your custom events will still be recorded.
|
109
86
|
c.back_to_app_link = "/" # this is the link hitting the home button in IWonder will take you to.
|
@@ -1,4 +1,14 @@
|
|
1
1
|
// Place all the behaviors and hooks related to the matching controller here.
|
2
2
|
// All this logic will automatically be available in application.js.
|
3
|
+
//= require highcharts
|
3
4
|
//= require_self
|
4
|
-
|
5
|
+
|
6
|
+
|
7
|
+
$(function(){
|
8
|
+
$("#chart_holder .calendar").datepicker({ dateFormat: 'yy/mm/dd' });
|
9
|
+
$("#ui-datepicker-div").hide(); // this shouldn't be needed, but there seems to be a bug
|
10
|
+
|
11
|
+
$("#chart_holder #chart_options input").change(function(){
|
12
|
+
$(this).closest("form").submit();
|
13
|
+
});
|
14
|
+
});
|
@@ -13,6 +13,12 @@ $pale_red: #ffd2d2;
|
|
13
13
|
box-shadow:$x_offset $y_offset $size $color;
|
14
14
|
}
|
15
15
|
|
16
|
+
@mixin inset_shadow($x_offset: 0px, $y_offset: 1px, $size: 8px, $color: rgba(0, 0, 0, 0.5)) {
|
17
|
+
-webkit-box-shadow:$x_offset $y_offset $size $color inset;
|
18
|
+
-moz-box-shadow:$x_offset $y_offset $size $color inset;
|
19
|
+
box-shadow:$x_offset $y_offset $size $color inset;
|
20
|
+
}
|
21
|
+
|
16
22
|
@mixin gradiant ($color_a:#aaa, $color_b:#bbb) {
|
17
23
|
position:relative;
|
18
24
|
background-image: -webkit-linear-gradient(top, $color_a, $color_b); /* Chrome 10+, Saf5.1+ */
|
@@ -30,6 +30,8 @@ html, body { background-color: #e5e5e5; font-family: Verdana, Helvetica, Arial;
|
|
30
30
|
}
|
31
31
|
#container { padding: 20px 40px; }
|
32
32
|
|
33
|
+
p.description { font-size:90%; color:#555;}
|
34
|
+
|
33
35
|
p.empty_list {color:#666; }
|
34
36
|
|
35
37
|
ul.primary_list { padding:0px; margin:10px 0; border:1px solid $light_blue_box_border; border-bottom:none; background-color:$light_blue_box_background;
|
@@ -45,11 +47,6 @@ html, body { background-color: #e5e5e5; font-family: Verdana, Helvetica, Arial;
|
|
45
47
|
}
|
46
48
|
}
|
47
49
|
}
|
48
|
-
|
49
|
-
.show {
|
50
|
-
p.description { font-size:90%; color:#555;}
|
51
|
-
}
|
52
|
-
|
53
50
|
|
54
51
|
form.main_form { background-color:$light_blue_box_background; border:1px solid $light_blue_box_border; padding:10px 15px; display:inline-block;
|
55
52
|
h3 {margin:0 0 10px 0;}
|
@@ -16,4 +16,11 @@ form.report {
|
|
16
16
|
.report_metric_ids { padding:0px; margin:10px 0;
|
17
17
|
li {padding:0px; margin:0px; list-style:none;}
|
18
18
|
}
|
19
|
+
}
|
20
|
+
|
21
|
+
#chart_holder {background-color:#f0f1fa; padding:8px; border:1px solid #ddd; @include rounded_corners(4px); @include inset_shadow(1px, 1px, 3px, rgba(0,0,0,0.3));
|
22
|
+
#chart_options {
|
23
|
+
label {color:#555; font-size:90%; font-weight:bold;}
|
24
|
+
}
|
25
|
+
#iw_chart_container {background-color:#fff; margin-top:5px; border:1px solid #ddd; @include shadow(1px, 1px, 3px, rgba(0,0,0,0.3));}
|
19
26
|
}
|
@@ -9,9 +9,20 @@ module IWonder
|
|
9
9
|
def show
|
10
10
|
@report = Report.find(params[:id])
|
11
11
|
|
12
|
-
@start_time = Time.zone.
|
13
|
-
@end_time = (params[:end_time]
|
14
|
-
@interval_length =
|
12
|
+
@start_time = (params[:start_time] ? Time.zone.parse(params[:start_time]) : Time.zone.now - 1.month)
|
13
|
+
@end_time = (params[:end_time] ? Time.zone.parse(params[:end_time]) : Time.zone.now)
|
14
|
+
@interval_length = default_interval_length
|
15
|
+
|
16
|
+
respond_to {|format|
|
17
|
+
format.html { }
|
18
|
+
format.js {
|
19
|
+
if @report.line?
|
20
|
+
render :partial => "line_report.js"
|
21
|
+
else
|
22
|
+
render :text => "?"
|
23
|
+
end
|
24
|
+
}
|
25
|
+
}
|
15
26
|
end
|
16
27
|
|
17
28
|
def new
|
@@ -49,5 +60,27 @@ module IWonder
|
|
49
60
|
redirect_to reports_path, :notice => "Report has been destroyed"
|
50
61
|
end
|
51
62
|
|
63
|
+
protected
|
64
|
+
|
65
|
+
def default_interval_length
|
66
|
+
length = @end_time - @start_time
|
67
|
+
|
68
|
+
if length > 2.months
|
69
|
+
interval_length = 1.week
|
70
|
+
elsif length > 1.week
|
71
|
+
interval_length = 1.days
|
72
|
+
else
|
73
|
+
interval_length = 1.hours
|
74
|
+
end
|
75
|
+
|
76
|
+
# can't show a smaller frequency than the snampshots get taken in.
|
77
|
+
longest_metric_frequency = @report.metrics.collect(&:frequency).max
|
78
|
+
if longest_metric_frequency > interval_length
|
79
|
+
interval_length = longest_metric_frequency
|
80
|
+
end
|
81
|
+
|
82
|
+
return interval_length
|
83
|
+
end
|
84
|
+
|
52
85
|
end
|
53
86
|
end
|
@@ -7,16 +7,28 @@ module IWonder
|
|
7
7
|
|
8
8
|
class << self
|
9
9
|
def merge_session_to_user(session_id, user_id)
|
10
|
-
|
10
|
+
# grab the session_id off of the new_visitor attached to that user
|
11
|
+
new_visitor_event = Event.where(:user_id => user_id, :event_type => "new_visitor").first
|
12
|
+
original_session_id = (new_visitor_event ? new_visitor_event.session_id : session_id)
|
11
13
|
|
12
|
-
|
14
|
+
|
15
|
+
# for all events on the current session, attach the user and session from that first event
|
16
|
+
update_all({:user_id => user_id, :session_id => original_session_id}, ["session_id = ? AND user_id IS NULL", session_id])
|
17
|
+
|
18
|
+
# clear our any new_visitor events other than the first one
|
19
|
+
if new_visitor_event and original_session_id != session_id
|
20
|
+
Event.where(:user_id => user_id, :event_type => "new_visitor").where("id <> ?", new_visitor_event.id).delete_all
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
return original_session_id
|
13
25
|
end
|
14
26
|
# handle_asynchronously :merge_session_to_user
|
15
27
|
|
16
28
|
|
17
29
|
def fast_create(attr_hash)
|
18
|
-
attr_hash[:created_at] = Time.now.utc
|
19
|
-
attr_hash[:updated_at] = Time.now.utc
|
30
|
+
attr_hash[:created_at] = Time.zone.now.utc
|
31
|
+
attr_hash[:updated_at] = Time.zone.now.utc
|
20
32
|
|
21
33
|
keys = [:event_type, :account_id, :user_id, :session_id, :controller, :action, :extra_details, :remote_ip, :user_agent, :referrer, :created_at, :updated_at]
|
22
34
|
key_str = keys.collect(&:to_s).join(", ")
|
@@ -54,8 +66,6 @@ module IWonder
|
|
54
66
|
}.first
|
55
67
|
end
|
56
68
|
|
57
|
-
|
58
|
-
|
59
69
|
end
|
60
70
|
end
|
61
71
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module IWonder
|
2
2
|
class Metric < ActiveRecord::Base
|
3
|
-
|
4
|
-
|
3
|
+
BACK_DATE_ITERATIONS = 30
|
4
|
+
|
5
|
+
attr_accessible :name, :frequency, :archived, :collection_method, :back_date_snapshots
|
6
|
+
attr_accessor :back_date_snapshots
|
7
|
+
attr_writer :back_date_snapshots
|
5
8
|
|
6
9
|
serialize :options, Hash
|
7
10
|
attr_accessible :collection_type, :combination_rule, :takes_snapshots
|
@@ -20,9 +23,10 @@ module IWonder
|
|
20
23
|
has_many :reports, :through => :report_memberships
|
21
24
|
has_many :snapshots do
|
22
25
|
def most_recent
|
23
|
-
order("
|
26
|
+
order("end_time DESC").first
|
24
27
|
end
|
25
28
|
end
|
29
|
+
accepts_nested_attributes_for :snapshots, :allow_destroy => true
|
26
30
|
|
27
31
|
# ==============================================================================================================================
|
28
32
|
# The following methods are for creating the metrics with the coorect values ===================================================
|
@@ -55,6 +59,14 @@ module IWonder
|
|
55
59
|
true # this preventing it from thinking the validation failed
|
56
60
|
end
|
57
61
|
|
62
|
+
before_validation :remove_existing_snapshots
|
63
|
+
def remove_existing_snapshots
|
64
|
+
if collection_method_changed? or frequency_changed?
|
65
|
+
self.earliest_measurement = nil
|
66
|
+
self.snapshots.each(&:mark_for_destruction)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
58
70
|
validate :avoid_dangerous_words
|
59
71
|
def avoid_dangerous_words
|
60
72
|
if collection_method.present? and collection_method.gsub(QUOTE_REMOVER, "") =~ DANGEROUS_WORDS
|
@@ -82,6 +94,11 @@ module IWonder
|
|
82
94
|
}
|
83
95
|
end
|
84
96
|
end
|
97
|
+
|
98
|
+
if self.model_counter_method == "Creation Rate" and !self.model_counter_class.constantize.new.respond_to?("created_at")
|
99
|
+
errors.add(:base, "Can't calculate creation rate on models without a :created_at column")
|
100
|
+
end
|
101
|
+
|
85
102
|
rescue Exception => e
|
86
103
|
errors.add(:model_counter_class, "is not a valid class")
|
87
104
|
end
|
@@ -117,10 +134,19 @@ module IWonder
|
|
117
134
|
query += model_counter_scopes.dup
|
118
135
|
end
|
119
136
|
|
137
|
+
#TODO: these queries should be scoped under the table name
|
120
138
|
if model_counter_method == "Creation Rate"
|
139
|
+
self.combination_rule = "sum"
|
121
140
|
self.collection_method = "#{query}.where(\"created_at >= ? AND created_at < ?\", start_time, end_time).count"
|
122
141
|
else # total numbers
|
123
|
-
|
142
|
+
|
143
|
+
self.combination_rule = "average"
|
144
|
+
if self.model_counter_class.constantize.new.respond_to?("created_at")
|
145
|
+
# this is more accurate for guessing backwards
|
146
|
+
self.collection_method = "#{query}.where(\"created_at < ?\", end_time).count"
|
147
|
+
else
|
148
|
+
self.collection_method = "#{query}.count"
|
149
|
+
end
|
124
150
|
end
|
125
151
|
end
|
126
152
|
|
@@ -145,7 +171,7 @@ module IWonder
|
|
145
171
|
# returns a hash with all the key values between the two times. If it has been collecting integers, the key will be the name of the metric
|
146
172
|
def value_from(start_time, end_time)
|
147
173
|
if takes_snapshots?
|
148
|
-
data = self.snapshots.where("
|
174
|
+
data = self.snapshots.where("start_time < ? AND end_time > ?", end_time, start_time).collect(&:data)
|
149
175
|
else
|
150
176
|
data = [run_collection_method_from(start_time, end_time)]
|
151
177
|
end
|
@@ -177,16 +203,31 @@ module IWonder
|
|
177
203
|
#TODO: some code to avoid overlap in snapshots needs to be added
|
178
204
|
def take_snapshot
|
179
205
|
start_time, end_time = timeframe_for_next_snapshot
|
180
|
-
|
206
|
+
while end_time <= Time.zone.now do
|
207
|
+
self.snapshots.create(:data => run_collection_method_from(start_time, end_time), :start_time => start_time, :end_time => end_time)
|
181
208
|
|
182
|
-
|
183
|
-
|
209
|
+
if self.earliest_measurement.nil? or self.earliest_measurement > start_time
|
210
|
+
self.update_attribute(:earliest_measurement, start_time)
|
211
|
+
end
|
212
|
+
|
213
|
+
start_time, end_time = timeframe_for_next_snapshot
|
184
214
|
end
|
185
215
|
end
|
186
216
|
|
187
217
|
after_save :back_date_if_chosen
|
188
218
|
def back_date_if_chosen
|
189
|
-
if @
|
219
|
+
if @back_date_snapshots and @back_date_snapshots.to_s =~ /1|true|on/i and takes_snapshots? and self.earliest_measurement.nil?
|
220
|
+
|
221
|
+
self.reload # this keeps bad variables and change states from sneaking in
|
222
|
+
|
223
|
+
start_time = Time.zone.now - BACK_DATE_ITERATIONS * frequency
|
224
|
+
end_time = start_time + frequency
|
225
|
+
start_time += 1.second
|
226
|
+
self.snapshots.create(:data => run_collection_method_from(start_time, end_time), :start_time => start_time, :end_time => end_time)
|
227
|
+
self.update_attribute(:earliest_measurement, start_time)
|
228
|
+
|
229
|
+
# not that the first snapshot is taken, running the :take_snapshot command will fill in the rest
|
230
|
+
take_snapshot
|
190
231
|
end
|
191
232
|
end
|
192
233
|
|
@@ -210,13 +251,15 @@ module IWonder
|
|
210
251
|
def timeframe_for_next_snapshot
|
211
252
|
recent = self.snapshots.most_recent
|
212
253
|
if recent.present?
|
213
|
-
|
214
|
-
|
254
|
+
start_time = recent.end_time
|
255
|
+
end_time = start_time + frequency
|
256
|
+
start_time += 1.second # this avoids overlap with the previous snapshot
|
215
257
|
else
|
216
|
-
|
217
|
-
|
258
|
+
start_time = Time.zone.now - frequency
|
259
|
+
end_time = Time.zone.now
|
218
260
|
end
|
219
|
-
|
261
|
+
|
262
|
+
[start_time, end_time]
|
220
263
|
end
|
221
264
|
|
222
265
|
end
|
@@ -67,7 +67,7 @@ module IWonder
|
|
67
67
|
master_hashes_array << master_hash_for_time_slice
|
68
68
|
|
69
69
|
time_iterator += interval_length
|
70
|
-
end while time_iterator <= end_time
|
70
|
+
end while (time_iterator + interval_length) <= end_time
|
71
71
|
|
72
72
|
# set the value to zero for any
|
73
73
|
master_hashes_array.each{|hash_for_slice_of_time|
|
@@ -77,7 +77,7 @@ module IWonder
|
|
77
77
|
}
|
78
78
|
|
79
79
|
keys_list.collect{|key|
|
80
|
-
{:name => key, :pointInterval => interval_length*1000, :data => master_hashes_array.collect{|mha| mha[key] }}
|
80
|
+
{:name => key, :pointStart => start_time.to_i * 1000, :pointInterval => interval_length*1000, :data => master_hashes_array.collect{|mha| mha[key] }}
|
81
81
|
}
|
82
82
|
end
|
83
83
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module IWonder
|
2
2
|
class Snapshot < ActiveRecord::Base
|
3
|
-
attr_accessible :data
|
3
|
+
attr_accessible :data, :start_time, :end_time
|
4
4
|
serialize :complex_data, Hash
|
5
5
|
|
6
6
|
belongs_to :metric
|
@@ -28,5 +28,6 @@ module IWonder
|
|
28
28
|
def complex?
|
29
29
|
self.complex_data.present?
|
30
30
|
end
|
31
|
+
|
31
32
|
end
|
32
33
|
end
|
@@ -28,8 +28,8 @@
|
|
28
28
|
</div>
|
29
29
|
|
30
30
|
<div class="field">
|
31
|
-
<%= f.check_box :
|
32
|
-
<%= f.label :
|
31
|
+
<%= f.check_box :back_date_snapshots%>
|
32
|
+
<%= f.label :back_date_snapshots, "Try and guess values for the last 30 snapshots?" %>
|
33
33
|
</div>
|
34
34
|
|
35
35
|
</div>
|
@@ -26,8 +26,8 @@
|
|
26
26
|
</div>
|
27
27
|
|
28
28
|
<div class="field">
|
29
|
-
<%= f.check_box :
|
30
|
-
<%= f.label :
|
29
|
+
<%= f.check_box :back_date_snapshots%>
|
30
|
+
<%= f.label :back_date_snapshots, "Try and guess values for the last 30 snapshots?" %>
|
31
31
|
</div>
|
32
32
|
|
33
33
|
</div>
|
@@ -1,5 +1,7 @@
|
|
1
1
|
<h1>Metrics</h1>
|
2
|
-
<
|
2
|
+
<p class="description">
|
3
|
+
Metrics are anything you want to track. They can be set up to monitor pretty much anything. To view the data collected, try creating a report for the metrics you wish to display.
|
4
|
+
</p>
|
3
5
|
|
4
6
|
<% if @metrics.empty? %>
|
5
7
|
<p class="empty_list">You don't have any metrics</p>
|
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
<div class="field">
|
24
24
|
<%= f.label :report_type %>
|
25
|
-
<%= f.select :report_type, {"Line" => {:value => "Line"}, "Bar" => {:disabled => true}, "
|
25
|
+
<%= f.select :report_type, {"Line" => {:value => "Line"}, "Bar" => {:disabled => true}, "Pie" => {:disabled => true}} %>
|
26
26
|
</div>
|
27
27
|
|
28
28
|
<hr/>
|
@@ -1,38 +1,15 @@
|
|
1
|
-
<div id="
|
1
|
+
<div id="chart_holder">
|
2
|
+
<%= form_tag report_path(@report), :method => :get, :remote => true, :id => "chart_options" do %>
|
3
|
+
<%= label_tag :start_time, "Range" %>
|
4
|
+
<%= text_field_tag :start_time, @start_time.strftime("%Y/%m/%d"), :size => 12, :class => "calendar" %>
|
5
|
+
-
|
6
|
+
<%= text_field_tag :end_time, @end_time.strftime("%Y/%m/%d"), :size => 12, :class => "calendar" %>
|
7
|
+
<% end %>
|
8
|
+
<div id="iw_chart_container"></div>
|
9
|
+
</div>
|
2
10
|
|
3
11
|
<script type="text/javascript" charset="utf-8">
|
4
12
|
$(function() {
|
5
|
-
|
6
|
-
options ||= {}
|
7
|
-
options[:chart] ||= {}
|
8
|
-
options[:chart][:renderTo] = "iw_chart_container";
|
9
|
-
|
10
|
-
options[:title] ||= { :text => "I wonder "+@report.name }
|
11
|
-
|
12
|
-
options[:series] = @report.collect_series_data(@start_time, @end_time, @interval_length);
|
13
|
-
|
14
|
-
# options[:chart][:defaultSeriesType] =
|
15
|
-
#
|
16
|
-
options[:credits] = false
|
17
|
-
#
|
18
|
-
options[:xAxis] = {}
|
19
|
-
# new_options[:xAxis][:categories] = options[:x_axis_categories]
|
20
|
-
options[:xAxis][:dateTimeLabelFormats] ||= { :day => '%b %e', :hour => '%b %e' }
|
21
|
-
options[:xAxis][:type] ||= 'datetime'
|
22
|
-
#
|
23
|
-
# new_options[:series] = options[:series]
|
24
|
-
#
|
25
|
-
# new_options[:yAxis] = (options[:yAxis] || {})
|
26
|
-
# new_options[:yAxis][:allow_decimals] = (options[:y_axis_allow_decimals] ? 'true' : 'false')
|
27
|
-
# new_options[:yAxis][:min] = (options[:y_axis_min] || 0)
|
28
|
-
# new_options[:yAxis][:title] = { :text => options[:y_axis_title] } if options[:y_axis_title].present?
|
29
|
-
#
|
30
|
-
# new_options[:legend] = (options[:legend] || { :enabled => false })
|
31
|
-
#
|
32
|
-
|
33
|
-
#
|
34
|
-
# new_options[:tooltip] = options[:tooltip] if options[:tooltip].present?
|
35
|
-
%>
|
36
|
-
var chart = new Highcharts.Chart(<%= raw options.to_json %>);
|
13
|
+
<%= render :partial => "line_report.js" %>
|
37
14
|
});
|
38
15
|
</script>
|