chart-candy 0.0.7
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/Gemfile +4 -0
- data/LICENSE +7 -0
- data/README.md +109 -0
- data/Rakefile +11 -0
- data/app/assets/javascripts/chart_candy/base.coffee +16 -0
- data/app/assets/javascripts/chart_candy/counter.coffee +50 -0
- data/app/assets/javascripts/chart_candy/donut.coffee +162 -0
- data/app/assets/javascripts/chart_candy/index.js +4 -0
- data/app/assets/javascripts/chart_candy/line.coffee +338 -0
- data/app/assets/stylesheets/chart_candy/base.css.scss +66 -0
- data/app/assets/stylesheets/chart_candy/counter.css.scss +11 -0
- data/app/assets/stylesheets/chart_candy/donut.css.scss +34 -0
- data/app/assets/stylesheets/chart_candy/index.css +6 -0
- data/app/assets/stylesheets/chart_candy/line.css.scss +107 -0
- data/app/controllers/candy_charts_controller.rb +60 -0
- data/config/locales/fr.yml +36 -0
- data/config/routes.rb +3 -0
- data/lib/chart-candy.rb +23 -0
- data/lib/chart-candy/authentication.rb +45 -0
- data/lib/chart-candy/base_chart.rb +11 -0
- data/lib/chart-candy/builder.rb +46 -0
- data/lib/chart-candy/builder/base.rb +70 -0
- data/lib/chart-candy/builder/counter.rb +12 -0
- data/lib/chart-candy/builder/donut.rb +73 -0
- data/lib/chart-candy/builder/line.rb +114 -0
- data/lib/chart-candy/builder/xls_builder.rb +159 -0
- data/lib/chart-candy/engine.rb +5 -0
- data/lib/chart-candy/helpers.rb +169 -0
- data/lib/chart-candy/implants.rb +10 -0
- data/lib/chart-candy/implants/railtie.rb +17 -0
- data/spec/chart-candy_spec.rb +11 -0
- data/spec/spec_helper.rb +12 -0
- data/vendor/assets/javascripts/d3.js +4 -0
- metadata +118 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
class ChartCandy::Builder::Base
|
2
|
+
def initialize(id, options={})
|
3
|
+
options.reverse_merge! from: nil, to: nil, step: nil
|
4
|
+
|
5
|
+
@from = options[:from] ? Time.parse(options[:from]) : nil
|
6
|
+
@to = options[:to] ? Time.parse(options[:to]) : Time.now
|
7
|
+
|
8
|
+
@chart = { id: id }
|
9
|
+
@chart[:step] = options[:step] if options[:step]
|
10
|
+
@chart[:title] = t('title')
|
11
|
+
@chart[:period] = ChartCandy::Builder.period(@from, @to, step: @chart[:step]) if @from
|
12
|
+
end
|
13
|
+
|
14
|
+
def close_chart
|
15
|
+
# Hooks before closing a chart
|
16
|
+
end
|
17
|
+
|
18
|
+
def filename
|
19
|
+
name = [title.parameterize]
|
20
|
+
name << @from.strftime('%Y%m%d') if @from
|
21
|
+
name << @to.strftime('%Y%m%d') if @to
|
22
|
+
|
23
|
+
return name.compact.join('-')
|
24
|
+
end
|
25
|
+
|
26
|
+
def id
|
27
|
+
@chart[:id]
|
28
|
+
end
|
29
|
+
|
30
|
+
def l(date, options={})
|
31
|
+
options.reverse_merge!(format: :date_long)
|
32
|
+
|
33
|
+
return ChartCandy.localize(date, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def period
|
37
|
+
@chart[:period]
|
38
|
+
end
|
39
|
+
|
40
|
+
def set_period_from_data(data)
|
41
|
+
@from = data.first
|
42
|
+
@to = data.last
|
43
|
+
|
44
|
+
@chart[:step] = ChartCandy::Builder.get_step_from_interval(data[1] - data[0]) if not @chart[:step]
|
45
|
+
|
46
|
+
@chart[:period] = ChartCandy::Builder.period @from, @to, step: @chart[:step]
|
47
|
+
end
|
48
|
+
|
49
|
+
def t(path, vars={})
|
50
|
+
vars.reverse_merge! :default => ''
|
51
|
+
|
52
|
+
ChartCandy.translate("#{id.gsub('-', '_')}.#{path}", vars)
|
53
|
+
end
|
54
|
+
|
55
|
+
def title
|
56
|
+
@chart[:title]
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_json
|
60
|
+
close_chart
|
61
|
+
|
62
|
+
return @chart.to_json
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_xls
|
66
|
+
close_chart
|
67
|
+
|
68
|
+
return ChartCandy::Builder::XlsBuilder.chart_to_xls @chart
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class ChartCandy::Builder::Counter < ChartCandy::Builder::Base
|
2
|
+
|
3
|
+
def initialize(id, options={})
|
4
|
+
super
|
5
|
+
|
6
|
+
@chart.merge! nature: 'count', data: []
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_primary(id, value)
|
10
|
+
@chart[:data] << { nature: :primary, label: t("data.#{id}.label"), id: id, value: value }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class ChartCandy::Builder::Donut < ChartCandy::Builder::Base
|
2
|
+
|
3
|
+
def initialize(id, options={})
|
4
|
+
super
|
5
|
+
|
6
|
+
@chart.merge! hole: [], label: t('label'), nature: 'donut', slices: [], show_label: true, unit: :number, value: t('value')
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_hole_item(name, value)
|
10
|
+
@chart[:hole] = [t('hole.title')].flatten if hole.empty?
|
11
|
+
hole << t("hole.#{name}", value: value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_slice(name, value, options={})
|
15
|
+
options.reverse_merge! txt_vars: {}
|
16
|
+
|
17
|
+
return if value.to_i <= 0
|
18
|
+
|
19
|
+
value = value.round(2) if money?
|
20
|
+
valuef = money? ? format_money(value) : value
|
21
|
+
|
22
|
+
options[:txt_vars][:value] = valuef
|
23
|
+
|
24
|
+
label_str = t("slices.#{name}.label", options[:txt_vars])
|
25
|
+
tooltip = t("slices.#{name}.tooltip", options[:txt_vars])
|
26
|
+
|
27
|
+
@chart[:slices] << { label: label_str, percent: 0, tooltip: tooltip, value: value, valuef: valuef }
|
28
|
+
end
|
29
|
+
|
30
|
+
def close_chart
|
31
|
+
total = @chart[:slices].sum{ |s| s[:value] }
|
32
|
+
|
33
|
+
total = total.round(2) if money?
|
34
|
+
|
35
|
+
@chart[:total] = { label: 'Total', value: total }
|
36
|
+
|
37
|
+
fill_percents
|
38
|
+
end
|
39
|
+
|
40
|
+
def format_money(value)
|
41
|
+
sprintf("%0.02f", (value.to_f).round(2)).gsub('.', ',') + ' $'
|
42
|
+
end
|
43
|
+
|
44
|
+
def hole
|
45
|
+
@chart[:hole]
|
46
|
+
end
|
47
|
+
|
48
|
+
def money?
|
49
|
+
@chart[:unit] == :money
|
50
|
+
end
|
51
|
+
|
52
|
+
def show_label=(active)
|
53
|
+
@chart[:show_label] = active
|
54
|
+
end
|
55
|
+
|
56
|
+
def show_label
|
57
|
+
@chart[:show_label]
|
58
|
+
end
|
59
|
+
|
60
|
+
def unit=(unit_sym)
|
61
|
+
@chart[:unit] = unit_sym.to_sym if [:number, :money].include? unit_sym.to_sym
|
62
|
+
end
|
63
|
+
|
64
|
+
def unit
|
65
|
+
@chart[:unit]
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def fill_percents
|
71
|
+
@chart[:slices].each { |s| s[:percent] = (s[:value].to_f * 100 / @chart[:total][:value]).round(2) }
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
class ChartCandy::Builder::Line < ChartCandy::Builder::Base
|
2
|
+
|
3
|
+
def initialize(id, options={})
|
4
|
+
super
|
5
|
+
|
6
|
+
@chart.merge! axis: {}, legend: nil, lines: [], nature: 'line', tooltip: true
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_dot(dot, id, x_name, y_name)
|
10
|
+
{
|
11
|
+
x: dot[x_name],
|
12
|
+
y: dot[y_name],
|
13
|
+
label_x: add_dot_label(id, dot[x_name], @chart[:axis][:x][:nature]),
|
14
|
+
label_y: add_dot_label(id, dot[y_name], @chart[:axis][:y][:nature])
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_dot_label(id, value, nature)
|
19
|
+
case nature
|
20
|
+
when :date then add_dot_label_date value
|
21
|
+
when :money then add_dot_label_money value
|
22
|
+
else value.to_s + ' ' + t("lines.#{id}.unit")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_dot_label_date(date)
|
27
|
+
case @chart[:step]
|
28
|
+
when 'day' then l(date, format: :date_long)
|
29
|
+
when 'week' then ChartCandy.translate('date.week') + ' ' + l(date, format: :date_long).strip
|
30
|
+
when 'month' then l(date, format: :date_without_day).capitalize
|
31
|
+
else l(date, format: :date_long)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_dot_label_money(amount)
|
36
|
+
sprintf("%0.02f", amount.round(2)).gsub('.', ',') + ' $'
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_line(id, original_data, options={})
|
40
|
+
options.reverse_merge! axis_y: "left", txt_vars: {}, key_x: "time", key_y: "value"
|
41
|
+
|
42
|
+
data = original_data.map{ |d| add_dot(d, id, options[:key_x], options[:key_y]) }
|
43
|
+
|
44
|
+
[:x, :y].each do |key|
|
45
|
+
[:min, :max].each { |m| @chart[:axis][key][m] = to_money_format(@chart[:axis][key][m]) } if money? key
|
46
|
+
end
|
47
|
+
|
48
|
+
data = original_data.map do |d|
|
49
|
+
[:key_x, :key_y].each { |key| d[options[key]] = to_money_format(d[options[key]]) if money?(key[-1,1]) }
|
50
|
+
add_dot(d, id, options[:key_x], options[:key_y])
|
51
|
+
end
|
52
|
+
|
53
|
+
@chart[:lines] << { axis_y: options[:axis_y], data: data, label: t("lines.#{id}.label", options[:txt_vars]), unit: t("lines.#{id}.unit"), total: get_total(data) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_x_axis(nature, original_data, options={})
|
57
|
+
options.reverse_merge! key: "time"
|
58
|
+
|
59
|
+
data = original_data.map{ |d| d[options[:key]] }
|
60
|
+
|
61
|
+
set_period_from_data data if not @from and nature == :date
|
62
|
+
|
63
|
+
@chart[:axis][:x] = { nature: nature, label: t("axis.x.label"), min: data.min, max: data.max, max_ticks: data.length }
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_y_axis(nature, original_data, options={})
|
67
|
+
options.reverse_merge! key: 'value', max: nil, min: nil
|
68
|
+
|
69
|
+
data = original_data.map{ |d| d[options[:key]] }
|
70
|
+
|
71
|
+
min = options[:min] ? options[:min] : data.min
|
72
|
+
max = options[:max] ? options[:max] : data.max
|
73
|
+
|
74
|
+
@chart[:axis][:y] = { nature: nature, label: t('axis.y.label'), min: min, max: max, max_ticks: data.length }
|
75
|
+
end
|
76
|
+
|
77
|
+
def close_chart
|
78
|
+
super
|
79
|
+
|
80
|
+
@chart[:legend] = (@chart[:lines].length > 1) if @chart[:legend].nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
def date_based?
|
84
|
+
@chart[:axis][:x] and @chart[:axis][:x][:nature] == :date
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_total(data)
|
88
|
+
{ label: 'Total', value: data.sum{ |d| d[:y] } }
|
89
|
+
end
|
90
|
+
|
91
|
+
def legend=(active)
|
92
|
+
@chart[:legend] = active
|
93
|
+
end
|
94
|
+
|
95
|
+
def legend
|
96
|
+
@chart[:legend]
|
97
|
+
end
|
98
|
+
|
99
|
+
def money?(key)
|
100
|
+
@chart[:axis][key.to_sym][:nature] == :money
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_money_format(value)
|
104
|
+
(BigDecimal.new(value) / 100).round(2)
|
105
|
+
end
|
106
|
+
|
107
|
+
def tooltip=(active)
|
108
|
+
@chart[:tooltip] = active
|
109
|
+
end
|
110
|
+
|
111
|
+
def tooltip
|
112
|
+
@chart[:tooltip]
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spreadsheet'
|
2
|
+
|
3
|
+
class ChartCandy::Builder::XlsBuilder
|
4
|
+
attr_reader :current_row, :current_column, :workbook
|
5
|
+
|
6
|
+
def self.chart_to_xls(chart)
|
7
|
+
xls = self.new(chart)
|
8
|
+
xls.generate
|
9
|
+
|
10
|
+
return xls.workbook
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(chart)
|
14
|
+
@chart = chart
|
15
|
+
@workbook = Spreadsheet::Workbook.new
|
16
|
+
@sheet = @workbook.create_worksheet
|
17
|
+
@formats = build_formats
|
18
|
+
|
19
|
+
@current_row = -1
|
20
|
+
@current_row_format = :normal
|
21
|
+
@current_column = 0
|
22
|
+
|
23
|
+
@columns_width = []
|
24
|
+
@max_column_width = 50
|
25
|
+
@default_column_width = 10
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_align_right_formats(formats)
|
29
|
+
align_right = {}
|
30
|
+
|
31
|
+
formats.each do |k,origin|
|
32
|
+
new_format = origin.dup
|
33
|
+
new_format.horizontal_align = :right
|
34
|
+
|
35
|
+
align_right["#{k}_right".to_sym] = new_format
|
36
|
+
end
|
37
|
+
|
38
|
+
formats.merge! align_right
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_formats
|
42
|
+
f = {}
|
43
|
+
|
44
|
+
f[:h1] = Spreadsheet::Format.new(weight: :bold, size: 16, horizontal_align: :left, vertical_align: :middle)
|
45
|
+
f[:h2] = Spreadsheet::Format.new(weight: :normal, size: 12, horizontal_align: :left, vertical_align: :middle)
|
46
|
+
f[:h3] = Spreadsheet::Format.new(weight: :normal, size: 9, horizontal_align: :left, vertical_align: :middle)
|
47
|
+
f[:h4] = Spreadsheet::Format.new(weight: :bold, size: 8, horizontal_align: :left, vertical_align: :middle)
|
48
|
+
f[:th] = Spreadsheet::Format.new(weight: :bold, size: 8, horizontal_align: :center, vertical_align: :middle, pattern_fg_color: :xls_color_19, pattern: 1)
|
49
|
+
f[:th_foot] = Spreadsheet::Format.new(weight: :bold, size: 8, horizontal_align: :left, vertical_align: :middle, pattern_fg_color: :xls_color_19, pattern: 1)
|
50
|
+
f[:normal] = Spreadsheet::Format.new(size: 8, horizontal_align: :left , vertical_align: :middle)
|
51
|
+
|
52
|
+
add_align_right_formats f
|
53
|
+
|
54
|
+
return f
|
55
|
+
end
|
56
|
+
|
57
|
+
def cell(content=nil, options={})
|
58
|
+
options.reverse_merge! format: nil, nature: :text
|
59
|
+
|
60
|
+
row_obj = @sheet.row(current_row)
|
61
|
+
|
62
|
+
row_obj.set_format current_column, @formats[options[:format]] if options[:format]
|
63
|
+
set_cell_format options[:nature]
|
64
|
+
row_obj.height = row_obj.format(0).font.size * 1.6
|
65
|
+
|
66
|
+
parsed_content = format_data(content)
|
67
|
+
|
68
|
+
@sheet[current_row, current_column] = parsed_content
|
69
|
+
|
70
|
+
@columns_width[current_column] = parsed_content.to_s.length if @columns_width[current_column].to_i < parsed_content.to_s.length
|
71
|
+
|
72
|
+
@current_column += 1
|
73
|
+
end
|
74
|
+
|
75
|
+
def format_data(data)
|
76
|
+
case
|
77
|
+
when data.is_a?(Time) then data.strftime('%d-%m-%Y')
|
78
|
+
else data
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def generate
|
83
|
+
header
|
84
|
+
|
85
|
+
case @chart[:nature]
|
86
|
+
when 'line' then generate_chart_line_table
|
87
|
+
when 'donut' then generate_chart_donut_table
|
88
|
+
end
|
89
|
+
|
90
|
+
set_columns_width
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_chart_line_table
|
94
|
+
row @chart[:axis][:x][:label], :th
|
95
|
+
|
96
|
+
@chart[:lines].map { |l| cell l[:label] }
|
97
|
+
|
98
|
+
@chart[:lines][0][:data].each_with_index do |l,i|
|
99
|
+
row
|
100
|
+
|
101
|
+
cell l[:x], nature: @chart[:axis][:x][:nature]
|
102
|
+
|
103
|
+
@chart[:lines].each { |line| cell line[:data][i][:y], nature: @chart[:axis][:y][:nature] }
|
104
|
+
end
|
105
|
+
|
106
|
+
row @chart[:lines][0][:total][:label], :th_foot
|
107
|
+
|
108
|
+
@chart[:lines].map { |l| cell l[:total][:value], nature: :number }
|
109
|
+
end
|
110
|
+
|
111
|
+
def generate_chart_donut_table
|
112
|
+
row [@chart[:label], @chart[:value]], :th
|
113
|
+
|
114
|
+
@chart[:slices].map { |s| row [s[:label], s[:value]] }
|
115
|
+
|
116
|
+
row [@chart[:total][:label], @chart[:total][:value]], :th_foot
|
117
|
+
end
|
118
|
+
|
119
|
+
def header
|
120
|
+
row @chart[:title], :h1
|
121
|
+
row @chart[:period], :h3 if @chart[:period]
|
122
|
+
|
123
|
+
reset_columns_width
|
124
|
+
|
125
|
+
skip_row
|
126
|
+
end
|
127
|
+
|
128
|
+
def reset_columns_width
|
129
|
+
@columns_width = Array.new(@columns_width.length, @default_column_width)
|
130
|
+
end
|
131
|
+
|
132
|
+
def row(data=[], format = :normal)
|
133
|
+
@current_column = 0
|
134
|
+
@current_row += 1
|
135
|
+
|
136
|
+
@sheet.row(current_row).default_format = @formats[format]
|
137
|
+
@current_row_format = format
|
138
|
+
|
139
|
+
[data].flatten.each { |d| cell(d) }
|
140
|
+
end
|
141
|
+
|
142
|
+
def set_cell_format(nature)
|
143
|
+
if nature == :number
|
144
|
+
f = "#{@current_row_format}_right".gsub('right_right', 'right').to_sym
|
145
|
+
|
146
|
+
@sheet.row(current_row).set_format(current_column, @formats[f])
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def set_columns_width
|
151
|
+
@columns_width.each_with_index do |c,i|
|
152
|
+
@sheet.column(i).width = (c.to_i < @default_column_width) ? @default_column_width : c.to_i
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def skip_row
|
157
|
+
@current_row += 1
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module ChartCandy::Helpers
|
2
|
+
def counter_chart(id, options={})
|
3
|
+
ChartCandyTagHelper.new(self, id, options[:from], options[:to], options[:step]).counter(options)
|
4
|
+
end
|
5
|
+
|
6
|
+
def d3_include_tag
|
7
|
+
('<![if ! lt IE 9]>' + javascript_include_tag("d3") + '<![endif]>').html_safe
|
8
|
+
end
|
9
|
+
|
10
|
+
def donut_chart(id, options={})
|
11
|
+
ChartCandyTagHelper.new(self, id, options[:from], options[:to], options[:step]).donut(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def line_chart(id, options={})
|
15
|
+
ChartCandyTagHelper.new(self, id, options[:from], options[:to], options[:step]).line(options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def excel_chart_button(id, options={})
|
19
|
+
ChartCandyTagHelper.new(self, id, options[:from], options[:to], options[:step]).excel_chart_button(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
class ChartCandyTagHelper
|
23
|
+
def initialize(rails_helpers, id, from, to, step)
|
24
|
+
@rails_helpers = rails_helpers
|
25
|
+
@id = id
|
26
|
+
@from = from
|
27
|
+
@to = to
|
28
|
+
@step = step || 'month'
|
29
|
+
end
|
30
|
+
|
31
|
+
def counter(options={})
|
32
|
+
options.reverse_merge! update_every: 1.minute, tools: nil
|
33
|
+
|
34
|
+
chart 'counter', options
|
35
|
+
end
|
36
|
+
|
37
|
+
def excel_chart_button(options={})
|
38
|
+
build_url 'line', options if not @url
|
39
|
+
|
40
|
+
tool_export_xls options[:label]
|
41
|
+
end
|
42
|
+
|
43
|
+
def line(options={})
|
44
|
+
options.reverse_merge! tools: {}
|
45
|
+
options[:tools].reverse_merge! export_xls: true, step: true, template: true
|
46
|
+
|
47
|
+
chart 'line', options
|
48
|
+
end
|
49
|
+
|
50
|
+
def donut(options={})
|
51
|
+
options.reverse_merge! tools: {}
|
52
|
+
options[:tools].reverse_merge! export_xls: true, step: false, template: true
|
53
|
+
|
54
|
+
chart 'donut', options
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def build_url(nature, options={})
|
60
|
+
params = { from: @from, format: 'json', id: @id, nature: nature, nonce: SecureRandom.hex(20), step: @step, timestamp: Time.now.utc.iso8601, to: @to, version: 'v1' }
|
61
|
+
|
62
|
+
options.each { |k,v| params[k] = v if not ['class', 'tools'].include? k.to_s }
|
63
|
+
|
64
|
+
params[:token] = build_url_token(params)
|
65
|
+
|
66
|
+
@url = @rails_helpers.candy_chart_url params
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_url_token(params)
|
70
|
+
compacted_params = ChartCandy::Authentication.compact_params(params)
|
71
|
+
|
72
|
+
url = @rails_helpers.candy_charts_url + compacted_params
|
73
|
+
|
74
|
+
return ChartCandy::Authentication.tokenize(url)
|
75
|
+
end
|
76
|
+
|
77
|
+
def chart(nature, options={})
|
78
|
+
options.reverse_merge! class: ""
|
79
|
+
options[:class] += " wrapper-chart chart-#{nature}"
|
80
|
+
|
81
|
+
build_url nature, options
|
82
|
+
|
83
|
+
content = ''
|
84
|
+
content += title_tag
|
85
|
+
content += chart_tools(nature, options[:tools]) if options[:tools]
|
86
|
+
content += content_tag(:div, content_tag(:div, '', class: 'chart') + content_tag(:div, '', class: 'table'), class: 'templates')
|
87
|
+
|
88
|
+
wrapper_options = { id: @id, class: options[:class], 'data-chart-candy' => nature, 'data-url' => @url}
|
89
|
+
wrapper_options['data-update-delay'] = options[:update_every].to_i if options[:update_every]
|
90
|
+
|
91
|
+
return content_tag(:div, content.html_safe, wrapper_options)
|
92
|
+
end
|
93
|
+
|
94
|
+
def chart_select_tag(name, choices, selection)
|
95
|
+
if form_candy?
|
96
|
+
candy.select(name, choices, selection)
|
97
|
+
else
|
98
|
+
select_tag(name, options_for_select(choices, selection), id: nil)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def chart_switch_tag(name, choices, selection)
|
103
|
+
if form_candy?
|
104
|
+
candy.switch(name, choices, selection)
|
105
|
+
else
|
106
|
+
select_tag(name, options_for_select(choices, selection), id: nil)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def chart_tools(nature, options={})
|
111
|
+
content = form_tag(@url) do
|
112
|
+
tools = ''
|
113
|
+
tools += tool_export_xls if options[:export_xls]
|
114
|
+
tools += tool_step if options[:step]
|
115
|
+
tools += tool_template if options[:template]
|
116
|
+
|
117
|
+
tools.html_safe
|
118
|
+
end
|
119
|
+
|
120
|
+
return content_tag(:div, content.html_safe, class: 'tools')
|
121
|
+
end
|
122
|
+
|
123
|
+
def form_candy?
|
124
|
+
begin
|
125
|
+
(candy ? true : false)
|
126
|
+
rescue
|
127
|
+
false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def t(path)
|
132
|
+
ChartCandy.translate(path)
|
133
|
+
end
|
134
|
+
|
135
|
+
def title_tag
|
136
|
+
content_tag(:h2, t("#{@id.underscore}.title").html_safe, class: 'title-chart')
|
137
|
+
end
|
138
|
+
|
139
|
+
def tool_export_xls(label=nil)
|
140
|
+
label = t('base.xls_export') if not label
|
141
|
+
|
142
|
+
content = link_to(content_tag(:span, label, class: 'text'), @url.gsub('.json', '.xls'), class: 'button', title: t('base.xls_export'))
|
143
|
+
|
144
|
+
return content_tag(:div, content.html_safe, class: 'tool holder-export-xls')
|
145
|
+
end
|
146
|
+
|
147
|
+
def tool_step
|
148
|
+
choices = ['day', 'week', 'month'].map{ |c| [t("base.steps.#{c}"), c] }
|
149
|
+
|
150
|
+
return content_tag(:div, chart_select_tag('step', choices, 'month'), class: 'tool holder-step')
|
151
|
+
end
|
152
|
+
|
153
|
+
def tool_template
|
154
|
+
choices = ['chart', 'table'].map { |c| [t("base.template.#{c}"), c] }
|
155
|
+
|
156
|
+
return content_tag(:div, chart_switch_tag('template', choices, 'chart'), class: 'tool holder-template')
|
157
|
+
end
|
158
|
+
|
159
|
+
def method_missing(*args, &block)
|
160
|
+
if [:candy, :content_tag, :form_tag, :link_to, :options_for_select, :select_tag].include?(args.first)
|
161
|
+
return @rails_helpers.send(*args, &block)
|
162
|
+
else
|
163
|
+
raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
::ActionView::Base.send :include, self
|
169
|
+
end
|