forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathc3.rb
189 lines (163 loc) · 6.68 KB
/
c3.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
require_dependency 'manageiq/reporting/formatter/c3_series'
module ManageIQ
module Reporting
module Formatter
class C3 < Ruport::Formatter
include ActionView::Helpers::UrlHelper
include ChartCommon
include MiqReport::Formatting
renders :c3, :for => ReportRenderer
# series handling methods
def series_class
ManageIQ::Reporting::Formatter::C3Series
end
CONVERT_TYPES = {
"ColumnThreed" => "Column",
"ParallelThreedColumn" => "Column",
"StackedThreedColumn" => "StackedColumn",
"PieThreed" => "Pie",
"AreaThreed" => "Area",
"StackedAreaThreed" => "StackedArea"
}
def add_series(label, data)
@counter ||= 0
@counter += 1
series_id = @counter.to_s
limit = pie_type? ? LEGEND_LENGTH : LABEL_LENGTH
if chart_is_2d?
mri.chart[:data][:columns] << [series_id, *data.map { |a| a[:value] }]
mri.chart[:data][:names][series_id] = slice_legend(_(label), limit)
mri.chart[:miq][:name_table][series_id] = label
else
data.each_with_index do |a, index|
id = index.to_s
mri.chart[:data][:columns].push([id, a[:value]])
mri.chart[:data][:names][id] = slice_legend(_(a[:tooltip]), limit)
mri.chart[:miq][:name_table][id] = a[:tooltip]
end
end
if chart_is_stacked?
mri.chart[:data][:groups][0] << series_id
end
end
def add_axis_category_text(categories)
if chart_is_2d?
category_labels = categories.collect { |c| c.kind_of?(Array) ? c.first : c }
limit = pie_type? ? LEGEND_LENGTH : LABEL_LENGTH
mri.chart[:axis][:x][:categories] = category_labels.collect { |c| slice_legend(c, limit) }
mri.chart[:miq][:category_table] = category_labels
end
end
# report building methods
def build_document_header
super
type = c3_convert_type(mri.graph[:type].to_s)
mri.chart = {
:miqChart => type,
:data => {:columns => [], :names => {}, :empty => {:label => {:text => _('No data available.')}}},
:axis => {:x => {:tick => {}}, :y => {:tick => {}, :padding => {:bottom => 0}}},
:tooltip => {:format => {}},
:miq => {:name_table => {}, :category_table => {}},
:legend => {}
}
if chart_is_2d?
mri.chart[:axis][:x] = {
:categories => [],
:tick => {}
}
end
if chart_is_stacked?
mri.chart[:data][:groups] = [[]]
end
# chart is numeric
if mri.graph[:mode] == 'values'
custom_format = Array(mri[:col_formats])[Array(mri[:col_order]).index(raw_column_name)]
format, options = javascript_format(mri.graph[:column].split(/(?<!:):(?!:)/)[0], custom_format)
if format
axis_formatter = {:function => format, :options => options}
mri.chart[:axis][:y] = {:tick => {:format => axis_formatter}}
end
end
# C&U chart
if graph_options[:chart_type] == :performance
unless mri.graph[:type] == 'Donut' || mri.graph[:type] == 'Pie'
mri.chart[:legend] = {:position => 'bottom'}
end
return if mri.graph[:columns].blank?
column = grouped_by_tag_category? ? mri.graph[:columns][0].split(/_+/)[0..-2].join('_') : mri.graph[:columns][0]
format, options = javascript_format(column, nil)
return unless format
axis_formatter = {:function => format, :options => options}
mri.chart[:axis][:y][:tick] = {:format => axis_formatter}
mri.chart[:miq][:format] = axis_formatter
end
end
def c3_convert_type(type)
CONVERT_TYPES[type] || type
end
def chart_is_2d?
['Bar', 'Column', 'StackedBar', 'StackedColumn', 'Line', 'Area', 'StackedArea'].include?(c3_convert_type(mri.graph[:type]))
end
def chart_is_stacked?
%w(StackedBar StackedColumn StackedArea).include?(mri.graph[:type])
end
# change structure of chart JSON to performance chart with timeseries data
def build_performance_chart_area(maxcols)
super
change_structure_to_timeseries
end
def no_records_found_chart(*)
mri.chart = {
:axis => {:y => {:show => false}},
:data => {:columns => [], :empty => {:label => {:text => _('No data available.')}}},
:miq => {:empty => true},
}
end
def finalize_document
mri.chart
end
private
# change structure of hash from standard chart to timeseries chart
def change_structure_to_timeseries
# add 'x' as first element and move mri.chart[:axis][:x][:categories] to mri.chart[:data][:columns] as first column
x = mri.chart[:axis][:x][:categories]
x.unshift('x')
mri.chart[:data][:columns].unshift(x)
mri.chart[:data][:x] = 'x'
# set x axis type to timeseries and remove categories
mri.chart[:axis][:x] = {:type => 'timeseries', :tick => {}}
# set flag for performance chart
mri.chart[:miq][:performance_chart] = true
# this conditions are taken from build_performance_chart_area method from chart_commons.rb
if mri.db.include?("Daily") || (mri.where_clause && mri.where_clause.include?("daily"))
# set format for parsing
mri.chart[:data][:xFormat] = '%m/%d'
# set format for labels
mri.chart[:axis][:x][:tick][:format] = '%m/%d'
elsif mri.extras[:realtime] == true
mri.chart[:data][:xFormat] = '%H:%M:%S'
mri.chart[:axis][:x][:tick][:format] = '%H:%M:%S'
else
mri.chart[:data][:xFormat] = '%H:%M'
mri.chart[:axis][:x][:tick][:format] = '%H:%M'
end
end
def build_reporting_chart(_maxcols)
mri.chart[:miq][:expand_tooltip] = true
super
end
def build_reporting_chart_numeric(_maxcols)
mri.chart[:miq][:expand_tooltip] = true
super
end
def build_performance_chart_pie(_maxcols)
mri.chart[:miq][:expand_tooltip] = true
super
end
def grouped_by_tag_category?
!!(mri.performance && mri.performance.fetch_path(:group_by_category))
end
end
end
end
end