reports: add non-timeseries charts.

Add bar charts for non-timeseries data. For example, a bar chart of the
top 10 uploaders overall in the last month, rather than a timeseries
chart of the number of uploads per day for the last month.
This commit is contained in:
evazion
2022-10-23 04:42:51 -05:00
parent 9ca76dd3be
commit 203067b5ed
7 changed files with 192 additions and 110 deletions

View File

@@ -3,11 +3,123 @@
class TimeSeriesComponent < ApplicationComponent
delegate :current_page_path, :search_params, to: :helpers
attr_reader :dataframe, :group, :mode
attr_reader :dataframe, :x_axis, :y_axis, :mode
def initialize(dataframe, group: nil, mode: :table)
def initialize(dataframe, x_axis:, mode: :table)
@dataframe = dataframe
@group = group
@x_axis = x_axis
@y_axis = columns.without(x_axis)
@mode = mode.to_sym
end
def columns
dataframe.types.keys
end
def chart_height
if x_axis != "date"
dataframe[x_axis].size * 30
end
end
def chart_options
if x_axis == "date"
stacked_area_chart
else
horizontal_bar_chart
end
end
def base_options
{
dataset: {
dimensions: columns,
source: dataframe.each_row.map(&:values),
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985"
}
}
},
toolbox: {
feature: {
dataView: {},
restore: {},
saveAsImage: {}
}
},
grid: {
left: "1%",
right: "1%",
containLabel: true
},
legend: {
data: y_axis.map(&:capitalize),
type: "scroll",
left: 0,
padding: [8, 200, 0, 15],
orient: "horizontal",
},
}
end
def stacked_area_chart
base_options.deep_merge(
toolbox: {
feature: {
dataZoom: {
yAxisIndex: "none"
},
magicType: {
type: ["line", "bar"],
},
}
},
dataZoom: [
{ type: "inside" },
{ type: "slider" }
],
xAxis: { type: "time" },
yAxis: [type: "value"] * y_axis.size,
series: y_axis.map do |name|
{
name: name.capitalize,
type: "line",
areaStyle: {},
stack: "all",
emphasis: {
focus: "series"
},
encode: {
x: x_axis,
y: name
}
}
end
)
end
def horizontal_bar_chart
base_options.deep_merge(
xAxis: { type: "value" },
yAxis: [type: "category", inverse: true] * y_axis.size,
series: y_axis.map do |name|
{
name: name.capitalize,
type: "bar",
emphasis: {
focus: "series"
},
encode: {
x: name,
y: x_axis,
}
}
end
)
end
end

View File

@@ -6,7 +6,16 @@
<% end %>
</div>
<% if mode == :table %>
<% if mode == :chart && x_axis.present? %>
<div class="line-chart" style="width: 100%; height: max(90vh, <%= chart_height.to_i %>px);"></div>
<script type="text/javascript">
var chart = new Danbooru.TimeSeriesComponent({
container: $(".line-chart").get(0),
options: <%= raw chart_options.to_json %>,
});
</script>
<% else %>
<table class="striped autofit" width="100%">
<thead>
<% dataframe.types.keys.each do |column| %>
@@ -26,16 +35,4 @@
<% end %>
</tbody>
</table>
<% elsif mode == :chart %>
<div class="line-chart" style="width: 100%; height: 80vh;"></div>
<script type="text/javascript">
var data = <%= raw dataframe.each_row.map(&:values).to_json %>;
var columns = <%= raw dataframe.types.keys.without("date").to_json %>;
var chart = new Danbooru.TimeSeriesComponent({
container: $(".line-chart").get(0),
data: data,
columns: columns,
});
</script>
<% end %>