dataviz: add pie percent chart type (#71666)
gitea/combo/pipeline/head This commit looks good
Details
gitea/combo/pipeline/head This commit looks good
Details
This commit is contained in:
parent
af473d684e
commit
32c912b978
|
@ -45,6 +45,7 @@ class Migration(migrations.Migration):
|
|||
('stacked-bar-percent', 'Stacked Bar (%)'),
|
||||
('line', 'Line'),
|
||||
('pie', 'Pie'),
|
||||
('pie-percent', 'Pie (%)'),
|
||||
('dot', 'Dot'),
|
||||
('table', 'Table'),
|
||||
('table-inverted', 'Table (inverted)'),
|
||||
|
|
|
@ -241,6 +241,7 @@ class ChartNgCell(CellBase):
|
|||
('stacked-bar-percent', _('Stacked Bar (%)')),
|
||||
('line', _('Line')),
|
||||
('pie', _('Pie')),
|
||||
('pie-percent', _('Pie (%)')),
|
||||
('dot', _('Dot')),
|
||||
('table', _('Table')),
|
||||
('table-inverted', _('Table (inverted)')),
|
||||
|
@ -381,6 +382,7 @@ class ChartNgCell(CellBase):
|
|||
'stacked-bar-percent': pygal.StackedBar,
|
||||
'line': pygal.Line,
|
||||
'pie': pygal.Pie,
|
||||
'pie-percent': pygal.Pie,
|
||||
'dot': pygal.Dot,
|
||||
'table': pygal.Bar,
|
||||
'table-inverted': pygal.Bar,
|
||||
|
@ -418,7 +420,7 @@ class ChartNgCell(CellBase):
|
|||
data['series'][0]['data'] = self.process_one_dimensional_data(
|
||||
chart, data['series'][0]['data']
|
||||
)
|
||||
if self.chart_type == 'pie':
|
||||
if self.chart_type in ('pie', 'pie-percent'):
|
||||
data['series'] = [
|
||||
{'label': chart.config.x_value_formatter(label), 'data': [data]}
|
||||
for label, data in zip(chart.x_labels, data['series'][0]['data'])
|
||||
|
@ -429,6 +431,9 @@ class ChartNgCell(CellBase):
|
|||
|
||||
if self.chart_type == 'stacked-bar-percent':
|
||||
self.make_percent([serie['data'] for serie in data['series']])
|
||||
elif self.chart_type == 'pie-percent':
|
||||
self.make_global_percent([serie['data'] for serie in data['series']])
|
||||
chart.config.value_formatter = self.get_value_formatter(measure='percent')
|
||||
|
||||
for serie in data['series']:
|
||||
chart.add(serie['label'], serie['data'])
|
||||
|
@ -586,6 +591,9 @@ class ChartNgCell(CellBase):
|
|||
elif width:
|
||||
chart.truncate_legend = width // 20
|
||||
|
||||
def configure_pie_percent_chart(self, *args, **kwargs):
|
||||
self.configure_pie_chart(*args, **kwargs)
|
||||
|
||||
def configure_chart(self, chart, width, height):
|
||||
auto_height_scale = pygal.style.DefaultStyle.legend_font_size * 1.75
|
||||
chart.config.margin = 0
|
||||
|
@ -620,7 +628,7 @@ class ChartNgCell(CellBase):
|
|||
if hasattr(self, custom_configure_method_name):
|
||||
getattr(self, custom_configure_method_name)(chart, width, height)
|
||||
|
||||
if self.chart_type != 'pie':
|
||||
if self.chart_type not in ('pie', 'pie-percent'):
|
||||
if width and width < 500:
|
||||
chart.legend_at_bottom = True
|
||||
# restore demanded chart's height
|
||||
|
@ -698,7 +706,7 @@ class ChartNgCell(CellBase):
|
|||
chart.add(gettext('Total'), line_totals)
|
||||
|
||||
def add_data_to_chart(self, chart, data, y_labels):
|
||||
if self.chart_type != 'pie':
|
||||
if self.chart_type not in ('pie', 'pie-percent'):
|
||||
series_data = []
|
||||
for i, serie_label in enumerate(y_labels):
|
||||
if chart.axis_count < 2:
|
||||
|
@ -718,7 +726,7 @@ class ChartNgCell(CellBase):
|
|||
chart.add(label, value)
|
||||
|
||||
@staticmethod
|
||||
def get_value_formatter(unit, measure='duration'):
|
||||
def get_value_formatter(unit=None, measure='duration'):
|
||||
if unit == 'seconds' or measure == 'duration':
|
||||
|
||||
def format_duration(value):
|
||||
|
@ -743,6 +751,17 @@ class ChartNgCell(CellBase):
|
|||
if values[i] is not None:
|
||||
values[i] = round(values[i] * factor, 1)
|
||||
|
||||
def make_global_percent(self, series_data):
|
||||
sum_values = sum(v for values in series_data for v in values if v is not None)
|
||||
if sum_values == 0:
|
||||
return
|
||||
|
||||
factor = 100 / sum_values
|
||||
for serie in series_data:
|
||||
for i, value in enumerate(serie):
|
||||
if value is not None:
|
||||
serie[i] = round(value * factor, 1)
|
||||
|
||||
@staticmethod
|
||||
def aggregate_data(data, interval):
|
||||
series_data = [serie['data'] for serie in data['series']]
|
||||
|
|
|
@ -1011,6 +1011,24 @@ def test_chartng_cell_new_api(app, new_api_statistics):
|
|||
assert chart.x_labels == []
|
||||
assert chart.raw_series == []
|
||||
|
||||
# pie with percent
|
||||
cell.statistic = Statistic.objects.get(slug='two-series')
|
||||
cell.chart_type = 'pie-percent'
|
||||
cell.save()
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.raw_series == [
|
||||
([None, 76.2, 9.5], {'title': 'Serie 1'}),
|
||||
([9.5, 4.8, None], {'title': 'Serie 2'}),
|
||||
]
|
||||
|
||||
cell.statistic = Statistic.objects.get(slug='no-data')
|
||||
cell.save()
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == []
|
||||
assert chart.raw_series == []
|
||||
|
||||
cell.statistic = Statistic.objects.get(slug='not-found')
|
||||
cell.save()
|
||||
with pytest.raises(HTTPError):
|
||||
|
|
Loading…
Reference in New Issue