Module: RailsuiCharts::ChartHelper
- Defined in:
- lib/railsui_charts/chart_helper.rb
Constant Summary collapse
- CIRCULAR_TYPES =
Forms whose placeholder should be a disc rather than a plotting area.
%i[pie donut polar_area radar].freeze
Instance Method Summary collapse
- #railsui_chart(data, type: :line, **options) ⇒ Object
-
#railsui_chart_empty(title: nil, description: nil, height: nil) ⇒ Object
Holds the chart's footprint so a card keeps its shape whether or not the query came back with anything.
- #railsui_chart_error(title: nil, description: nil, height: nil) ⇒ Object
-
#railsui_chart_skeleton(height: nil, type: :line, label: "Loading chart") ⇒ Object
Server-rendered placeholder for a chart whose data has not arrived yet — the thing a Turbo frame shows before it swaps in the real one.
-
#railsui_small_multiples(series, type: :line, height: 120, columns: 3, **options) ⇒ Object
One small chart per series, sharing a y-scale.
-
#shared_scale(entries) ⇒ Object
Facets only compare if they share a scale.
Instance Method Details
#railsui_chart(data, type: :line, **options) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/railsui_charts/chart_helper.rb', line 8 def railsui_chart(data, type: :line, **) # An empty dataset is a normal day one, not an error. Rendering axes # around nothing looks like a chart that failed rather than a chart with # nothing to show yet. return railsui_chart_empty(**()) if ApexOptionsBuilder.blank?(data) config = ApexOptionsBuilder.new(data, type: type, **).build id = [:id] || "rui-chart-#{SecureRandom.hex(4)}" table = [:accessible] != false ? accessibility_table(config, id: id) : nil content_tag(:div, id: id, class: "railsui-chart", # Charts draw when they scroll into view, so the space has to # be held from the start. Without it the page is short on # load and grows under the reader as they scroll. style: reserved_height(config), data: { controller: "railsui-chart", "railsui-chart-options-value": config.to_json }) do table end end |
#railsui_chart_empty(title: nil, description: nil, height: nil) ⇒ Object
Holds the chart's footprint so a card keeps its shape whether or not the query came back with anything.
74 75 76 |
# File 'lib/railsui_charts/chart_helper.rb', line 74 def railsui_chart_empty(title: nil, description: nil, height: nil) chart_state(:empty, title: title || "No data", description: description, height: height) end |
#railsui_chart_error(title: nil, description: nil, height: nil) ⇒ Object
78 79 80 |
# File 'lib/railsui_charts/chart_helper.rb', line 78 def railsui_chart_error(title: nil, description: nil, height: nil) chart_state(:error, title: title || "Couldn't load this chart", description: description, height: height) end |
#railsui_chart_skeleton(height: nil, type: :line, label: "Loading chart") ⇒ Object
Server-rendered placeholder for a chart whose data has not arrived yet —
the thing a Turbo frame shows before it swaps in the real one. Pass the
type: it will become so the placeholder is the shape being waited on.
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/railsui_charts/chart_helper.rb', line 85 def railsui_chart_skeleton(height: nil, type: :line, label: "Loading chart") classes = ["railsui-chart-skeleton"] classes << "railsui-chart-skeleton--circular" if CIRCULAR_TYPES.include?(type.to_sym) content_tag(:div, class: "railsui-chart-state railsui-chart-state--loading", style: state_height(height), role: "status", aria: { label: label, busy: true }) do content_tag(:span, "", class: classes.join(" "), aria: { hidden: true }) end end |
#railsui_small_multiples(series, type: :line, height: 120, columns: 3, **options) ⇒ Object
One small chart per series, sharing a y-scale.
This is the honest answer when there are more categories than a single chart can hold. Eight lines on one axis is a plate of spaghetti, and a ninth colour is not distinguishable from the others anyway — facets scale where colour does not.
<%= railsui_small_multiples @plans, type: :area, columns: 3 %>
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/railsui_charts/chart_helper.rb', line 39 def railsui_small_multiples(series, type: :line, height: 120, columns: 3, **) return railsui_chart_empty(**()) if ApexOptionsBuilder.blank?(series) entries = Array(series) shared = shared_scale(entries) content_tag(:div, class: "railsui-small-multiples", style: "--rui-small-multiple-columns: #{columns.to_i}") do safe_join(entries.each_with_index.map do |entry, index| content_tag(:div, class: "railsui-small-multiple") do safe_join([ content_tag(:p, entry[:name] || entry["name"] || "Series #{index + 1}", class: "railsui-small-multiple__title"), # Every facet takes the same colour. The title carries identity # here, so spending a hue on it would say nothing extra. railsui_chart(entry[:data] || entry["data"], type: type, height: height, yaxis: shared.merge(tickAmount: 3), **) ]) end end) end end |
#shared_scale(entries) ⇒ Object
Facets only compare if they share a scale. Left to themselves each one would fit its own data and a small series would look like a large one.
62 63 64 65 66 67 68 69 70 |
# File 'lib/railsui_charts/chart_helper.rb', line 62 def shared_scale(entries) values = entries.flat_map { |entry| Array(entry[:data] || entry["data"]).map { |point| ApexOptionsBuilder.value_of(point) } }.compact return {} if values.empty? min, max = values.minmax return {} if min == max { min: min, max: max } end |