Skip to content

Commit

Permalink
Add YAxisProps to the result
Browse files Browse the repository at this point in the history
  • Loading branch information
ecarreras committed Jul 16, 2024
1 parent e68bece commit 682206c
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 5 deletions.
5 changes: 5 additions & 0 deletions ooui/graph/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def __init__(self, element):
"""
self._string = element.get('string')
self._timerange = element.get('timerange', None)
self._y_range = element.get('y_range', "default")

interval = element.get('interval', None)
self._interval = int(interval) if interval is not None else 1
Expand All @@ -26,6 +27,10 @@ def timerange(self):
def interval(self):
return self._interval

@property
def y_range(self):
return self._y_range

@property
def type(self):
return self._type
Expand Down
14 changes: 12 additions & 2 deletions ooui/graph/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from ooui.graph.fields import get_value_for_operator
from ooui.graph.axis import get_y_axis_fieldname
from ooui.graph.timerange import process_timerange_data
from ooui.graph.processor import get_values_grouped_by_field, get_values_for_y_field
from ooui.graph.processor import (
get_values_grouped_by_field, get_values_for_y_field, get_min_max
)


class GraphChart(Graph):
Expand Down Expand Up @@ -156,10 +158,18 @@ def process(self, values, fields, options=None):
final_data, key=lambda x: '{x}-{type}'.format(**x)
)

return {
result = {
'data': final_data,
'isGroup': is_stack or is_group,
'isStack': is_stack,
'type': self.type,
'num_items': len(values),
}

if self.type == "line" and self.y_range:
y_axis_props = {'mode': self.y_range}
if self.y_range == "auto":
y_axis_props.update(get_min_max(final_data))
result['yAxisProps'] = y_axis_props

return result
21 changes: 21 additions & 0 deletions ooui/graph/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,24 @@ def get_all_objects_in_grouped_values(grouped):
total_objects.extend(group['entries'])

return total_objects


def get_min_max(values, margin=0.1):
"""
Calculate the minimum and maximum values from a list of dictionaries.
:param values: List of dictionaries.
:param margin: Margin to add to the min and max values.
:return: Dictionary with 'min' and 'max' keys.
"""
if not values:
raise ValueError("The values array cannot be empty.")

value_list = [d['value'] for d in values]
min_value = min(value_list)
max_value = max(value_list)
calculated_margin = (max_value - min_value) * margin

return {
'min': int(min_value - calculated_margin),
'max': int(max_value + calculated_margin),
}
47 changes: 45 additions & 2 deletions spec/graph/graph_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

with it("should parse a chart graph XML with type line"):
xml = """<?xml version="1.0"?>
<graph type="line">
<graph type="line" y_range="auto">
<field name="data_alta" axis="x"/>
<field name="data_alta" operator="+" axis="y"/>
</graph>
Expand All @@ -50,4 +50,47 @@
expect(graph.y[0].name).to(equal('data_alta'))
expect(graph.x.axis).to(equal('x'))
expect(graph.y[0].axis).to(equal('y'))
expect(graph.y[0].operator).to(equal('+'))
expect(graph.y[0].operator).to(equal('+'))
expect(graph.y_range).to(equal('auto'))

with description("Processing a Graph"):
with description("A line graph with y_range auto"):
with it("should return yAxisProps to the result with min and max values"):
xml = """<?xml version="1.0"?>
<graph type="line" y_range="auto" timerange="day">
<field name="date" axis="x"/>
<field name="v" operator="+" axis="y"/>
</graph>
"""
graph = parse_graph(xml)
values = [
{'date': '2024-01-01', 'v': 10},
{'date': '2024-01-02', 'v': 20},
{'date': '2024-01-03', 'v': 30}
]
fields = {'date': {'type': 'date'}, 'v': {'type': 'integer'}}
result = graph.process(values, fields)
expect(result['yAxisProps']).to(equal({
'mode': 'auto',
'min': 8,
'max': 32
}))
with description("A line graph with y_range to full"):
with it("should return yAxisProps to the result with mode full"):
xml = """<?xml version="1.0"?>
<graph type="line" y_range="full" timerange="day">
<field name="date" axis="x"/>
<field name="v" operator="+" axis="y"/>
</graph>
"""
graph = parse_graph(xml)
values = [
{'date': '2024-01-01', 'v': 10},
{'date': '2024-01-02', 'v': 20},
{'date': '2024-01-03', 'v': 30}
]
fields = {'date': {'type': 'date'}, 'v': {'type': 'integer'}}
result = graph.process(values, fields)
expect(result['yAxisProps']).to(equal({
'mode': 'full',
}))
76 changes: 75 additions & 1 deletion spec/graph/processor_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ooui.graph import parse_graph
from ooui.graph.processor import (
get_values_grouped_by_field, get_all_objects_in_grouped_values,
get_values_for_y_field, process_graph_data
get_values_for_y_field, process_graph_data, get_min_max
)

current_dir = os.path.dirname(os.path.abspath(__file__))
Expand Down Expand Up @@ -470,3 +470,77 @@ def get_graph_data(xml, model):
entries_data, 'category', fields_data
)
expect(labels).to(equal(['Fruit', 'Vegetable', 'Fruit']))

with description('Testing get_min_max') as self:
with it('should return correct min and max with default margin'):
data = [
{'value': 10},
{'value': 20},
{'value': 30},
]

result = get_min_max(data)

min_value = 10
max_value = 30
margin = (max_value - min_value) * 0.1
expected = {
'min': min_value - margin,
'max': max_value + margin,
}

expect(result).to(equal(expected))

with it('should return correct min and max with custom margin'):
data = [
{'value': 10},
{'value': 20},
{'value': 30},
]

result = get_min_max(data, 0.2)

min_value = 10
max_value = 30
margin = (max_value - min_value) * 0.2
expected = {
'min': min_value - margin,
'max': max_value + margin,
}

expect(result).to(equal(expected))

with it('should return correct min and max for single element'):
data = [{'value': 10}]

result = get_min_max(data)

expected = {
'min': 10,
'max': 10,
}

expect(result).to(equal(expected))

with it('should handle negative values correctly'):
data = [
{'value': -10},
{'value': 0},
{'value': 10},
]

result = get_min_max(data)

min_value = -10
max_value = 10
margin = (max_value - min_value) * 0.1
expected = {
'min': min_value - margin,
'max': max_value + margin,
}

expect(result).to(equal(expected))

with it('should throw an error for empty array'):
expect(lambda: get_min_max([])).to(
raise_error(ValueError, "The values array cannot be empty."))

0 comments on commit 682206c

Please sign in to comment.