Skip to content

Commit

Permalink
Devops Report: Grouped + Stacked bar chart (#572)
Browse files Browse the repository at this point in the history
- Simpler datastructures
- Cache reports
  • Loading branch information
kitallis authored Oct 31, 2023
1 parent 4e370f6 commit b69224b
Show file tree
Hide file tree
Showing 15 changed files with 338 additions and 322 deletions.
3 changes: 3 additions & 0 deletions app/assets/images/cog.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/user.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 5 additions & 15 deletions app/components/chart_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,18 @@
<div>
<h5 class="flex leading-none text-lg font-normal text-gray-900 items-center gap-x-1">
<%= title %>
<%= inline_svg("question_mark.svg", classname: "w-4 inline-flex fill-current shrink-0 text-gray-400") %>
<%#= help_icon %>
</h5>

<p class="text-sm font-normal text-gray-400"><%= chart_scope %></p>
</div>

<div class="flex items-center py-0.5 text-base font-semibold text-green-700 text-center">
<%= inline_svg("thermometer.svg", classname: "w-6 fill-current shrink-0") %>
</div>
<div class="flex py-0.5 text-base font-semibold text-green-700"><%= corner_icon %></div>
</div>

<% if area? %>
<div data-controller="charts"
data-charts-type-value="area"
data-charts-format-value="<%= value_format %>"
data-charts-area-names-value="<%= legends %>"
data-charts-area-series-value="<%= series %>"
data-charts-area-categories-value="<%= categories %>">
data-charts-series-value="<%= series %>">
<div data-charts-target="chart"></div>
</div>
<% end %>
Expand All @@ -29,9 +23,7 @@
<div data-controller="charts"
data-charts-type-value="line"
data-charts-format-value="<%= value_format %>"
data-charts-line-names-value="<%= legends %>"
data-charts-line-series-value="<%= series %>"
data-charts-line-categories-value="<%= categories %>">
data-charts-series-value="<%= series %>">
<div data-charts-target="chart"></div>
</div>
<% end %>
Expand All @@ -40,9 +32,7 @@
<div data-controller="charts"
data-charts-type-value="stacked-bar"
data-charts-format-value="<%= value_format %>"
data-charts-stacked-bar-names-value="<%= legends %>"
data-charts-stacked-bar-series-value="<%= series %>"
data-charts-stacked-bar-categories-value="<%= categories %>">
data-charts-series-value="<%= series %>">
<div data-charts-target="chart"></div>
</div>
<% end %>
Expand Down
112 changes: 91 additions & 21 deletions app/components/chart_component.rb
Original file line number Diff line number Diff line change
@@ -1,52 +1,122 @@
class ChartComponent < ViewComponent::Base
include AssetsHelper
using RefinedHash
CHART_TYPES = %w[area line donut stacked-bar]
InvalidChartType = Class.new(StandardError)

def initialize(chart)
def initialize(chart, icon:)
@chart = chart
@icon = icon
raise InvalidChartType unless chart[:type].in?(CHART_TYPES)
end

attr_reader :chart

def area?
type == "area"
def type
@type ||= chart[:type]
end

def line?
type == "line"
def value_format
chart[:value_format]
end

def stacked_bar?
type == "stacked-bar"
def series
ungroup_series.to_json
end

def type
@type ||= chart[:type]
def series_raw
chart[:data]
end

def legends
chart[:legends].to_json
def title
I18n.t("charts.#{chart[:name]}.title")
end

def series
chart[:series].to_json
def chart_scope
I18n.t("charts.#{chart[:name]}.scope")
end

def categories
chart[:x_axis].to_json
def help_text
I18n.t("charts.#{chart[:name]}.help_text")
end

def value_format
chart[:value_format]
def corner_icon
inline_svg(@icon, classname: "w-6 fill-current shrink-0")
end

def title
I18n.t("charts.#{chart[:name]}.title")
def help_icon
inline_svg("question_mark.svg", classname: "w-4 inline-flex fill-current shrink-0 text-gray-400")
end

def chart_scope
I18n.t("charts.#{chart[:name]}.scope")
def subgroup? = chart[:subgroup]

def stacked? = chart[:stacked]

def line? = chart[:type] == "line"

def area? = chart[:type] == "area"

def donut? = chart[:type] == "donut"

def stacked_bar? = chart[:type] == "stacked-bar"

# {"8.0.2"=>{"android"=>1, "ios"=>0}}
# Input:
# {
# "8.0.1": {
# "android": {
# "QA Android Review": 2,
# "Android Release": 4
# },
# "ios": {
# "QA iOS Review": 6,
# "iOS Release": 8
# }
# },
# "8.0.2": {
# "android": {
# "QA Android Review": 3,
# "Android Release": 5
# },
# "ios": {
# "QA iOS Review": 7,
# "iOS Release": 9
# }
# }
# }
#
# Output:
# [{:name=>"QA Android Review", :group=>"android", :data=>{"8.0.1"=>2, "8.0.2"=>3}},
# {:name=>"Android Release", :group=>"android", :data=>{"8.0.1"=>4, "8.0.2"=>5}},
# {:name=>"QA iOS Review", :group=>"ios", :data=>{"8.0.1"=>6, "8.0.2"=>7}},
# {:name=>"iOS Release", :group=>"ios", :data=>{"8.0.1"=>8, "8.0.2"=>9}}]
def ungroup_series(input = series_raw)
input.each_with_object([]) do |(category, grouped_maps), result|
grouped_maps.each do |group, inner_data|
if inner_data.is_a?(Hash) && stacked?
inner_data.each do |name, value|
item = result.find { |r| r[:name] == name && r[:group] == group }
item ||= {name: name, group: group, data: {}}
item[:data][category] = value
result.push(item) unless result.include?(item)
end
else
item = result.find { |r| r[:name] == group }
item ||= {name: group, data: {}}
item[:data][category] = inner_data
result.push(item) unless result.include?(item)
end
end
end.then { cartesian_series(_1) }
end

def cartesian_series(input = series_raw)
input.map do |series|
series.update_key(:data) do |data|
data.map do |x, y|
{x: x, y: y}
end
end
end
end
end
1 change: 0 additions & 1 deletion app/controllers/apps_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ def show
@app_setup_instructions = @app.app_setup_instructions
@train_setup_instructions = @app.train_setup_instructions
@train_in_creation = @app.train_in_creation
@devops_report = Charts::DevopsReport.all(@app.trains.last) if current_user.release_health?
end

def new
Expand Down
1 change: 1 addition & 0 deletions app/controllers/trains_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class TrainsController < SignedInApplicationController
before_action :set_notification_channels, only: %i[new create edit update]

def show
@devops_report = @train.devops_report if @train.devops_report?(current_user)
end

def new
Expand Down
Loading

0 comments on commit b69224b

Please sign in to comment.