layrz-sdk 3.0.13__py3-none-any.whl → 3.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of layrz-sdk might be problematic. Click here for more details.

Files changed (123) hide show
  1. layrz_sdk/__init__.py +1 -1
  2. layrz_sdk/constants.py +5 -0
  3. layrz_sdk/entities/__init__.py +129 -73
  4. layrz_sdk/entities/asset.py +71 -0
  5. layrz_sdk/entities/{general/asset_operation_mode.py → asset_operation_mode.py} +31 -30
  6. layrz_sdk/entities/broadcast_request.py +12 -0
  7. layrz_sdk/entities/broadcast_response.py +12 -0
  8. layrz_sdk/entities/broadcast_result.py +20 -0
  9. layrz_sdk/entities/{broadcasts/status.py → broadcast_status.py} +28 -27
  10. layrz_sdk/entities/case.py +47 -0
  11. layrz_sdk/entities/case_ignored_status.py +26 -0
  12. layrz_sdk/entities/case_status.py +23 -0
  13. layrz_sdk/entities/charts/axis_config.py +15 -0
  14. layrz_sdk/entities/charts/{bar.py → bar_chart.py} +171 -208
  15. layrz_sdk/entities/charts/chart_alignment.py +27 -0
  16. layrz_sdk/entities/charts/chart_color.py +44 -0
  17. layrz_sdk/entities/charts/chart_configuration.py +10 -0
  18. layrz_sdk/entities/charts/chart_data_serie.py +19 -0
  19. layrz_sdk/entities/charts/chart_data_serie_type.py +28 -0
  20. layrz_sdk/entities/charts/chart_data_type.py +27 -0
  21. layrz_sdk/entities/charts/{render_technology.py → chart_render_technology.py} +30 -29
  22. layrz_sdk/entities/charts/{column.py → column_chart.py} +197 -236
  23. layrz_sdk/entities/charts/html_chart.py +34 -0
  24. layrz_sdk/entities/charts/{line.py → line_chart.py} +244 -282
  25. layrz_sdk/entities/charts/map_center_type.py +22 -0
  26. layrz_sdk/entities/charts/map_chart.py +104 -0
  27. layrz_sdk/entities/charts/map_point.py +22 -0
  28. layrz_sdk/entities/charts/number_chart.py +50 -0
  29. layrz_sdk/entities/charts/{pie.py → pie_chart.py} +127 -148
  30. layrz_sdk/entities/charts/radar_chart.py +77 -0
  31. layrz_sdk/entities/charts/{radial_bar.py → radial_bar_chart.py} +127 -148
  32. layrz_sdk/entities/charts/{scatter.py → scatter_chart.py} +206 -290
  33. layrz_sdk/entities/charts/scatter_serie.py +15 -0
  34. layrz_sdk/entities/charts/scatter_serie_item.py +8 -0
  35. layrz_sdk/entities/charts/table_chart.py +50 -0
  36. layrz_sdk/entities/charts/table_header.py +8 -0
  37. layrz_sdk/entities/charts/table_row.py +9 -0
  38. layrz_sdk/entities/charts/timeline_chart.py +75 -0
  39. layrz_sdk/entities/charts/timeline_serie.py +12 -0
  40. layrz_sdk/entities/charts/timeline_serie_item.py +12 -0
  41. layrz_sdk/entities/checkpoint.py +18 -0
  42. layrz_sdk/entities/comment.py +16 -0
  43. layrz_sdk/entities/custom_field.py +10 -0
  44. layrz_sdk/entities/custom_report_page.py +16 -0
  45. layrz_sdk/entities/device.py +13 -0
  46. layrz_sdk/entities/event.py +23 -0
  47. layrz_sdk/entities/geofence.py +11 -0
  48. layrz_sdk/entities/last_message.py +12 -0
  49. layrz_sdk/entities/message.py +23 -0
  50. layrz_sdk/entities/outbound_service.py +10 -0
  51. layrz_sdk/entities/position.py +101 -0
  52. layrz_sdk/entities/presence_type.py +16 -0
  53. layrz_sdk/entities/{reports/report.py → report.py} +257 -286
  54. layrz_sdk/entities/report_col.py +40 -0
  55. layrz_sdk/entities/report_configuration.py +8 -0
  56. layrz_sdk/entities/report_data_type.py +28 -0
  57. layrz_sdk/entities/{reports/format.py → report_format.py} +27 -26
  58. layrz_sdk/entities/report_header.py +43 -0
  59. layrz_sdk/entities/report_page.py +17 -0
  60. layrz_sdk/entities/report_row.py +28 -0
  61. layrz_sdk/entities/sensor.py +11 -0
  62. layrz_sdk/entities/{formatting/text_align.py → text_alignment.py} +26 -25
  63. layrz_sdk/entities/trigger.py +11 -0
  64. layrz_sdk/entities/user.py +10 -0
  65. layrz_sdk/entities/waypoint.py +18 -0
  66. layrz_sdk/helpers/__init__.py +8 -2
  67. layrz_sdk/helpers/color.py +41 -45
  68. layrz_sdk/lcl/__init__.py +7 -2
  69. layrz_sdk/lcl/core.py +832 -813
  70. layrz_sdk/py.typed +0 -0
  71. {layrz_sdk-3.0.13.dist-info → layrz_sdk-3.1.0.dist-info}/LICENSE +6 -6
  72. {layrz_sdk-3.0.13.dist-info → layrz_sdk-3.1.0.dist-info}/METADATA +48 -45
  73. layrz_sdk-3.1.0.dist-info/RECORD +75 -0
  74. {layrz_sdk-3.0.13.dist-info → layrz_sdk-3.1.0.dist-info}/WHEEL +1 -1
  75. layrz_sdk/entities/broadcasts/__init__.py +0 -6
  76. layrz_sdk/entities/broadcasts/request.py +0 -30
  77. layrz_sdk/entities/broadcasts/response.py +0 -30
  78. layrz_sdk/entities/broadcasts/result.py +0 -53
  79. layrz_sdk/entities/broadcasts/service.py +0 -28
  80. layrz_sdk/entities/cases/__init__.py +0 -4
  81. layrz_sdk/entities/cases/case.py +0 -120
  82. layrz_sdk/entities/cases/comment.py +0 -37
  83. layrz_sdk/entities/cases/trigger.py +0 -31
  84. layrz_sdk/entities/charts/__init__.py +0 -21
  85. layrz_sdk/entities/charts/alignment.py +0 -26
  86. layrz_sdk/entities/charts/color.py +0 -38
  87. layrz_sdk/entities/charts/configuration.py +0 -54
  88. layrz_sdk/entities/charts/data_type.py +0 -26
  89. layrz_sdk/entities/charts/exceptions.py +0 -29
  90. layrz_sdk/entities/charts/html.py +0 -44
  91. layrz_sdk/entities/charts/map.py +0 -179
  92. layrz_sdk/entities/charts/number.py +0 -52
  93. layrz_sdk/entities/charts/radar.py +0 -102
  94. layrz_sdk/entities/charts/serie.py +0 -56
  95. layrz_sdk/entities/charts/serie_type.py +0 -27
  96. layrz_sdk/entities/charts/table.py +0 -74
  97. layrz_sdk/entities/charts/timeline.py +0 -148
  98. layrz_sdk/entities/checkpoints/__init__.py +0 -4
  99. layrz_sdk/entities/checkpoints/checkpoint.py +0 -50
  100. layrz_sdk/entities/checkpoints/waypoint.py +0 -52
  101. layrz_sdk/entities/events/__init__.py +0 -2
  102. layrz_sdk/entities/events/event.py +0 -58
  103. layrz_sdk/entities/formatting/__init__.py +0 -2
  104. layrz_sdk/entities/general/__init__.py +0 -9
  105. layrz_sdk/entities/general/asset.py +0 -72
  106. layrz_sdk/entities/general/custom_field.py +0 -29
  107. layrz_sdk/entities/general/device.py +0 -45
  108. layrz_sdk/entities/general/geofence.py +0 -53
  109. layrz_sdk/entities/general/sensor.py +0 -31
  110. layrz_sdk/entities/general/user.py +0 -29
  111. layrz_sdk/entities/repcom/__init__.py +0 -2
  112. layrz_sdk/entities/repcom/transaction.py +0 -54
  113. layrz_sdk/entities/reports/__init__.py +0 -7
  114. layrz_sdk/entities/reports/col.py +0 -86
  115. layrz_sdk/entities/reports/header.py +0 -57
  116. layrz_sdk/entities/reports/page.py +0 -64
  117. layrz_sdk/entities/reports/row.py +0 -43
  118. layrz_sdk/entities/telemetry/__init__.py +0 -5
  119. layrz_sdk/entities/telemetry/last_message.py +0 -41
  120. layrz_sdk/entities/telemetry/message.py +0 -37
  121. layrz_sdk/entities/telemetry/position.py +0 -51
  122. layrz_sdk-3.0.13.dist-info/RECORD +0 -70
  123. {layrz_sdk-3.0.13.dist-info → layrz_sdk-3.1.0.dist-info}/top_level.txt +0 -0
@@ -1,282 +1,244 @@
1
- """Line chart"""
2
-
3
- import logging
4
- from typing import Any, List
5
-
6
- from .alignment import ChartAlignment
7
- from .configuration import AxisConfig
8
- from .data_type import ChartDataType
9
- from .exceptions import ChartException
10
- from .render_technology import ChartRenderTechnology
11
- from .serie import ChartDataSerie
12
- from .serie_type import ChartDataSerieType
13
-
14
- log = logging.getLogger(__name__)
15
-
16
-
17
- class LineChart:
18
- """
19
- Line chart configuration
20
-
21
- """
22
-
23
- def __init__(
24
- self,
25
- x_axis: ChartDataSerie,
26
- y_axis: List[ChartDataSerie],
27
- title: str = 'Chart',
28
- align: ChartAlignment = ChartAlignment.CENTER,
29
- x_axis_config: AxisConfig = None,
30
- y_axis_config: AxisConfig = None,
31
- ) -> None:
32
- """
33
- Constructor
34
- ----
35
- Arguments
36
- - x_axis : Defines the X Axis of the chart, uses the ChartDataSerie class.
37
- Please read the documentation to more information.
38
- - y_axis : Defines the Y Axis of the chart, uses the ChartDataSerie class.
39
- Please read the documentation to more information.
40
- - title : Title of the chart
41
- - align : Alignment of the title
42
- - x_axis_config : Configuration of the X Axis
43
- - y_axis_config : Configuration of the Y Axis
44
- """
45
- for i, serie in enumerate(y_axis):
46
- if not isinstance(serie, ChartDataSerie):
47
- raise ChartException(f'Y Axis serie {i} must be an instance of ChartDataSerie')
48
- self.y_axis = y_axis
49
-
50
- if not isinstance(x_axis, ChartDataSerie):
51
- raise ChartException('X Axis must be an instance of ChartDataSerie')
52
- self.x_axis = x_axis
53
-
54
- if not isinstance(title, str):
55
- raise ChartException('title must be an instance of str')
56
- self.title = title
57
-
58
- if not isinstance(align, ChartAlignment):
59
- raise ChartException('align must be an instance of ChartAlignment')
60
- self.align = align
61
-
62
- if x_axis_config is None:
63
- x_axis_config = AxisConfig()
64
-
65
- if not isinstance(x_axis_config, AxisConfig):
66
- raise ChartException('x_axis_config must be an instance of AxisConfig')
67
- self.x_axis_config = x_axis_config
68
-
69
- if y_axis_config is None:
70
- y_axis_config = AxisConfig()
71
-
72
- if not isinstance(y_axis_config, AxisConfig):
73
- raise ChartException('y_axis_config must be an instance of AxisConfig')
74
- self.y_axis_config = y_axis_config
75
-
76
- def render(self, technology: ChartRenderTechnology) -> Any:
77
- """
78
- Render chart to a graphic Library.
79
- We have two graphic libraries: GRAPHIC and CANVASJS.
80
-
81
- GRAPHIC is a Flutter chart library. To return this option, use the parameter use_new_definition=True.
82
- CANVASJS is a Javascript chart library. This is the default option.
83
- """
84
-
85
- if technology == ChartRenderTechnology.GRAPHIC:
86
- return {
87
- 'library': 'GRAPHIC',
88
- 'chart': 'LINE',
89
- 'configuration': self._render_graphic(),
90
- }
91
-
92
- if technology == ChartRenderTechnology.SYNCFUSION_FLUTTER_CHARTS:
93
- return {
94
- 'library': 'SYNCFUSION_FLUTTER_CHARTS',
95
- 'chart': 'LINE',
96
- 'configuration': self._render_syncfusion_flutter_charts(),
97
- }
98
-
99
- if technology == ChartRenderTechnology.CANVASJS:
100
- return {
101
- 'library': 'CANVASJS',
102
- 'chart': 'LINE',
103
- 'configuration': self._render_canvasjs(),
104
- }
105
-
106
- return {
107
- 'library': 'FLUTTER',
108
- 'chart': 'TEXT',
109
- 'configuration': [f'Unsupported {technology}'],
110
- }
111
-
112
- def _render_syncfusion_flutter_charts(self) -> Any:
113
- """
114
- Converts the configuration of the chart to a Flutter library syncfusion_flutter_charts.
115
- """
116
- series = []
117
-
118
- for serie in self.y_axis:
119
- if serie.serie_type not in [ChartDataSerieType.LINE, ChartDataSerieType.AREA]:
120
- log.warning('Serie type not supported: %s', serie.serie_type)
121
- continue
122
-
123
- points = []
124
-
125
- for i, value in enumerate(self.x_axis.data):
126
- x_value = value.timestamp() if self.x_axis.data_type == ChartDataType.DATETIME else value
127
- if not isinstance(x_value, (int, float)):
128
- continue
129
-
130
- y_value = serie.data[i]
131
- if isinstance(y_value, bool):
132
- if y_value:
133
- y_value = 1
134
- else:
135
- y_value = 0
136
-
137
- if not isinstance(y_value, (int, float)):
138
- log.debug("Value isn't a number: %s", y_value)
139
- continue
140
-
141
- points.append(
142
- {
143
- 'xAxis': x_value,
144
- 'yAxis': y_value,
145
- }
146
- )
147
-
148
- series.append(
149
- {
150
- 'color': serie.color,
151
- 'values': points,
152
- 'label': serie.label,
153
- 'type': 'AREA' if serie.serie_type == ChartDataSerieType.AREA else 'LINE',
154
- }
155
- )
156
-
157
- return {
158
- 'series': series,
159
- 'xAxis': {
160
- 'label': self.x_axis_config.label,
161
- 'measureUnit': self.x_axis_config.measure_unit,
162
- 'dataType': self.x_axis_config.data_type.value,
163
- 'minValue': self.x_axis_config.min_value,
164
- 'maxValue': self.x_axis_config.max_value,
165
- },
166
- 'yAxis': {
167
- 'label': self.y_axis_config.label,
168
- 'measureUnit': self.y_axis_config.measure_unit,
169
- 'dataType': self.y_axis_config.data_type.value,
170
- 'minValue': self.y_axis_config.min_value,
171
- 'maxValue': self.y_axis_config.max_value,
172
- },
173
- }
174
-
175
- def _render_graphic(self) -> Any:
176
- """
177
- Converts the configuration of the chart to a Flutter library Graphic.
178
- """
179
- series = []
180
-
181
- for serie in self.y_axis:
182
- if serie.serie_type not in [ChartDataSerieType.LINE, ChartDataSerieType.AREA]:
183
- continue
184
-
185
- points = []
186
-
187
- for i, value in enumerate(self.x_axis.data):
188
- points.append(
189
- {
190
- 'x_axis': {
191
- 'value': value.timestamp() if self.x_axis.data_type == ChartDataType.DATETIME else value,
192
- 'is_datetime': self.x_axis.data_type == ChartDataType.DATETIME,
193
- },
194
- 'y_axis': serie.data[i],
195
- }
196
- )
197
-
198
- series.append(
199
- {
200
- 'group': serie.label,
201
- 'color': serie.color,
202
- 'dashed': serie.serie_type == ChartDataSerieType.LINE and serie.dashed,
203
- 'type': 'AREA' if serie.serie_type == ChartDataSerieType.AREA else 'LINE',
204
- 'values': points,
205
- }
206
- )
207
-
208
- return series
209
-
210
- def _render_canvasjs(self) -> Any:
211
- """
212
- Converts the configuration of the chart to Javascript library CanvasJS.
213
- """
214
- datasets = []
215
-
216
- for serie in self.y_axis:
217
- dataset = {
218
- 'type': 'line',
219
- 'name': serie.label,
220
- 'connectNullData': True,
221
- 'nullDataLineDashType': 'solid',
222
- 'showInLegend': True,
223
- 'color': serie.color,
224
- 'markerSize': 3,
225
- }
226
-
227
- if serie.serie_type != ChartDataSerieType.NONE:
228
- dataset['type'] = serie.serie_type.value
229
-
230
- if serie.serie_type == ChartDataSerieType.AREA:
231
- dataset['fillOpacity'] = 0.3
232
-
233
- if self.x_axis.data_type == ChartDataType.DATETIME:
234
- dataset['xValueType'] = 'dateTime'
235
- dataset['xValueFormatString'] = 'YYYY-MM-DD HH:mm:ss TT'
236
-
237
- if serie.serie_type == ChartDataSerieType.LINE and serie.dashed:
238
- dataset['lineDashType'] = 'dash'
239
- dataset['markerSize'] = 0
240
-
241
- points = []
242
-
243
- if serie.serie_type == ChartDataSerieType.SCATTER:
244
- for point in serie.data:
245
- points.append({'x': point.x, 'y': point.y})
246
- else:
247
- for i, value in enumerate(self.x_axis.data):
248
- points.append(
249
- {
250
- 'x': (value.timestamp() * 1000) if self.x_axis.data_type == ChartDataType.DATETIME else value,
251
- 'y': serie.data[i],
252
- }
253
- )
254
-
255
- dataset['dataPoints'] = points
256
- datasets.append(dataset)
257
-
258
- return {
259
- 'animationEnabled': False,
260
- 'zoomEnabled': True,
261
- 'title': {
262
- 'text': self.title,
263
- 'fontFamily': 'Fira Sans Condensed',
264
- 'fontSize': 20,
265
- 'horizontalAlign': self.align.value,
266
- },
267
- 'data': datasets,
268
- 'axisX': {
269
- 'title': self.x_axis.label,
270
- 'titleFontFamily': 'Fira Sans Condensed',
271
- 'titleFontSize': 20,
272
- },
273
- 'toolTip': {'animationEnabled': False, 'shared': True},
274
- 'legend': {'cursor': 'pointer'},
275
- }
276
-
277
-
278
- class AreaChart(LineChart):
279
- """
280
- Line chart
281
- Deprecation warning: This class will be removed in the next version. Use LineChart instead.
282
- """
1
+ """Line chart"""
2
+
3
+ import logging
4
+ import sys
5
+ from typing import Any, Dict, List
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+ from .axis_config import AxisConfig
10
+ from .chart_alignment import ChartAlignment
11
+ from .chart_data_serie import ChartDataSerie
12
+ from .chart_data_serie_type import ChartDataSerieType
13
+ from .chart_data_type import ChartDataType
14
+ from .chart_render_technology import ChartRenderTechnology
15
+
16
+ if sys.version_info >= (3, 11):
17
+ from typing import Self
18
+ else:
19
+ from typing_extensions import Self
20
+
21
+ log = logging.getLogger(__name__)
22
+
23
+
24
+ class LineChart(BaseModel):
25
+ """Line chart configuration"""
26
+
27
+ x_axis: ChartDataSerie = Field(description='Defines the X Axis of the chart')
28
+ y_axis: List[ChartDataSerie] = Field(description='Defines the Y Axis of the chart', default_factory=list)
29
+ title: str = Field(default='Chart', description='Title of the chart')
30
+ align: ChartAlignment = Field(default=ChartAlignment.CENTER, description='Alignment of the title')
31
+ x_axis_config: AxisConfig = Field(
32
+ default_factory=lambda: AxisConfig(),
33
+ description='Configuration of the X Axis',
34
+ )
35
+ y_axis_config: AxisConfig = Field(
36
+ default_factory=lambda: AxisConfig(),
37
+ description='Configuration of the Y Axis',
38
+ )
39
+
40
+ def render(self: Self, technology: ChartRenderTechnology) -> Dict[str, Any]:
41
+ """
42
+ Render chart to a graphic Library.
43
+ :param technology: The technology to use to render the chart.
44
+ :return: The configuration of the chart.
45
+ """
46
+
47
+ if technology == ChartRenderTechnology.GRAPHIC:
48
+ return {
49
+ 'library': 'GRAPHIC',
50
+ 'chart': 'LINE',
51
+ 'configuration': self._render_graphic(),
52
+ }
53
+
54
+ if technology == ChartRenderTechnology.SYNCFUSION_FLUTTER_CHARTS:
55
+ return {
56
+ 'library': 'SYNCFUSION_FLUTTER_CHARTS',
57
+ 'chart': 'LINE',
58
+ 'configuration': self._render_syncfusion_flutter_charts(),
59
+ }
60
+
61
+ if technology == ChartRenderTechnology.CANVAS_JS:
62
+ return {
63
+ 'library': 'CANVASJS',
64
+ 'chart': 'LINE',
65
+ 'configuration': self._render_canvasjs(),
66
+ }
67
+
68
+ return {
69
+ 'library': 'FLUTTER',
70
+ 'chart': 'TEXT',
71
+ 'configuration': [f'Unsupported {technology}'],
72
+ }
73
+
74
+ def _render_syncfusion_flutter_charts(self: Self) -> Dict[str, Any]:
75
+ """
76
+ Converts the configuration of the chart to a Flutter library syncfusion_flutter_charts.
77
+ """
78
+ series = []
79
+
80
+ for serie in self.y_axis:
81
+ if serie.serie_type not in [ChartDataSerieType.LINE, ChartDataSerieType.AREA]:
82
+ log.warning('Serie type not supported: %s', serie.serie_type)
83
+ continue
84
+
85
+ points = []
86
+
87
+ for i, value in enumerate(self.x_axis.data):
88
+ x_value = value.timestamp() if self.x_axis.data_type == ChartDataType.DATETIME else value
89
+ if not isinstance(x_value, (int, float)):
90
+ continue
91
+
92
+ y_value = serie.data[i]
93
+ if isinstance(y_value, bool):
94
+ if y_value:
95
+ y_value = 1
96
+ else:
97
+ y_value = 0
98
+
99
+ if not isinstance(y_value, (int, float)):
100
+ log.debug("Value isn't a number: %s", y_value)
101
+ continue
102
+
103
+ points.append(
104
+ {
105
+ 'xAxis': x_value,
106
+ 'yAxis': y_value,
107
+ }
108
+ )
109
+
110
+ series.append(
111
+ {
112
+ 'color': serie.color,
113
+ 'values': points,
114
+ 'label': serie.label,
115
+ 'type': 'AREA' if serie.serie_type == ChartDataSerieType.AREA else 'LINE',
116
+ }
117
+ )
118
+
119
+ return {
120
+ 'series': series,
121
+ 'xAxis': {
122
+ 'label': self.x_axis_config.label,
123
+ 'measureUnit': self.x_axis_config.measure_unit,
124
+ 'dataType': self.x_axis_config.data_type.value,
125
+ 'minValue': self.x_axis_config.min_value,
126
+ 'maxValue': self.x_axis_config.max_value,
127
+ },
128
+ 'yAxis': {
129
+ 'label': self.y_axis_config.label,
130
+ 'measureUnit': self.y_axis_config.measure_unit,
131
+ 'dataType': self.y_axis_config.data_type.value,
132
+ 'minValue': self.y_axis_config.min_value,
133
+ 'maxValue': self.y_axis_config.max_value,
134
+ },
135
+ }
136
+
137
+ def _render_graphic(self: Self) -> List[Dict[str, Any]]:
138
+ """
139
+ Converts the configuration of the chart to a Flutter library Graphic.
140
+ """
141
+ series = []
142
+
143
+ for serie in self.y_axis:
144
+ if serie.serie_type not in [ChartDataSerieType.LINE, ChartDataSerieType.AREA]:
145
+ continue
146
+
147
+ points = []
148
+
149
+ for i, value in enumerate(self.x_axis.data):
150
+ points.append(
151
+ {
152
+ 'x_axis': {
153
+ 'value': value.timestamp() if self.x_axis.data_type == ChartDataType.DATETIME else value,
154
+ 'is_datetime': self.x_axis.data_type == ChartDataType.DATETIME,
155
+ },
156
+ 'y_axis': serie.data[i],
157
+ }
158
+ )
159
+
160
+ series.append(
161
+ {
162
+ 'group': serie.label,
163
+ 'color': serie.color,
164
+ 'dashed': serie.serie_type == ChartDataSerieType.LINE and serie.dashed,
165
+ 'type': 'AREA' if serie.serie_type == ChartDataSerieType.AREA else 'LINE',
166
+ 'values': points,
167
+ }
168
+ )
169
+
170
+ return series
171
+
172
+ def _render_canvasjs(self: Self) -> Dict[str, Any]:
173
+ """
174
+ Converts the configuration of the chart to Javascript library CanvasJS.
175
+ """
176
+ datasets = []
177
+
178
+ for serie in self.y_axis:
179
+ dataset = {
180
+ 'type': 'line',
181
+ 'name': serie.label,
182
+ 'connectNullData': True,
183
+ 'nullDataLineDashType': 'solid',
184
+ 'showInLegend': True,
185
+ 'color': serie.color,
186
+ 'markerSize': 3,
187
+ }
188
+
189
+ if serie.serie_type != ChartDataSerieType.NONE:
190
+ dataset['type'] = serie.serie_type.value
191
+
192
+ if serie.serie_type == ChartDataSerieType.AREA:
193
+ dataset['fillOpacity'] = 0.3
194
+
195
+ if self.x_axis.data_type == ChartDataType.DATETIME:
196
+ dataset['xValueType'] = 'dateTime'
197
+ dataset['xValueFormatString'] = 'YYYY-MM-DD HH:mm:ss TT'
198
+
199
+ if serie.serie_type == ChartDataSerieType.LINE and serie.dashed:
200
+ dataset['lineDashType'] = 'dash'
201
+ dataset['markerSize'] = 0
202
+
203
+ points = []
204
+
205
+ if serie.serie_type == ChartDataSerieType.SCATTER:
206
+ for point in serie.data:
207
+ points.append({'x': point.x, 'y': point.y})
208
+ else:
209
+ for i, value in enumerate(self.x_axis.data):
210
+ points.append(
211
+ {
212
+ 'x': (value.timestamp() * 1000) if self.x_axis.data_type == ChartDataType.DATETIME else value,
213
+ 'y': serie.data[i],
214
+ }
215
+ )
216
+
217
+ dataset['dataPoints'] = points
218
+ datasets.append(dataset)
219
+
220
+ return {
221
+ 'animationEnabled': False,
222
+ 'zoomEnabled': True,
223
+ 'title': {
224
+ 'text': self.title,
225
+ 'fontFamily': 'Fira Sans Condensed',
226
+ 'fontSize': 20,
227
+ 'horizontalAlign': self.align.value,
228
+ },
229
+ 'data': datasets,
230
+ 'axisX': {
231
+ 'title': self.x_axis.label,
232
+ 'titleFontFamily': 'Fira Sans Condensed',
233
+ 'titleFontSize': 20,
234
+ },
235
+ 'toolTip': {'animationEnabled': False, 'shared': True},
236
+ 'legend': {'cursor': 'pointer'},
237
+ }
238
+
239
+
240
+ class AreaChart(LineChart):
241
+ """
242
+ Line chart
243
+ Deprecation warning: This class will be removed in the next version. Use LineChart instead.
244
+ """
@@ -0,0 +1,22 @@
1
+ import sys
2
+ from enum import Enum
3
+
4
+ if sys.version_info >= (3, 11):
5
+ from typing import Self
6
+ else:
7
+ from typing_extensions import Self
8
+
9
+
10
+ class MapCenterType(Enum):
11
+ """Map Chart center type"""
12
+
13
+ FIXED = 'FIXED'
14
+ CONTAIN = 'CONTAIN'
15
+
16
+ def __str__(self: Self) -> str:
17
+ """Readable property"""
18
+ return self.name
19
+
20
+ def __repr__(self: Self) -> str:
21
+ """Readable property"""
22
+ return f'MapCenterType.{self.name}'
@@ -0,0 +1,104 @@
1
+ """Map chart"""
2
+
3
+ import sys
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ from .chart_render_technology import ChartRenderTechnology
9
+ from .map_center_type import MapCenterType
10
+ from .map_point import MapPoint
11
+
12
+ if sys.version_info >= (3, 11):
13
+ from typing import Self
14
+ else:
15
+ from typing_extensions import Self
16
+
17
+
18
+ class MapChart(BaseModel):
19
+ """Map chart configuration"""
20
+
21
+ points: List[MapPoint] = Field(description='Points of the chart', default_factory=list)
22
+ title: str = Field(description='Title of the chart', default='Chart')
23
+ center: MapCenterType = Field(description='Center of the chart', default=MapCenterType.CONTAIN)
24
+ center_latlng: Optional[List[float]] = Field(description='Center of the chart in latlng format', default=None)
25
+
26
+ def render(self: Self, technology: ChartRenderTechnology = ChartRenderTechnology.FLUTTER_MAP) -> Dict[str, Any]:
27
+ """
28
+ Render chart to a graphic Library.
29
+ :param technology: The technology to use to render the chart.
30
+ :return: The configuration of the chart.
31
+ """
32
+ if technology == ChartRenderTechnology.FLUTTER_MAP:
33
+ return {
34
+ 'library': 'FLUTTER_MAP',
35
+ 'chart': 'MAP',
36
+ 'configuration': self._render_flutter_map(),
37
+ }
38
+
39
+ return {
40
+ 'library': 'FLUTTER',
41
+ 'chart': 'TEXT',
42
+ 'configuration': [f'Unsupported {technology}'],
43
+ }
44
+
45
+ def _render_flutter_map(self: Self) -> Dict[str, Any]:
46
+ """
47
+ Converts the configuration to the chart to Flutter Map engine.
48
+ """
49
+ points = []
50
+
51
+ for point in self.points:
52
+ points.append(
53
+ {
54
+ 'label': point.label,
55
+ 'color': point.color,
56
+ 'latlng': (point.latitude, point.longitude),
57
+ }
58
+ )
59
+
60
+ center = 'CONTAIN'
61
+
62
+ if self.center == MapCenterType.FIXED:
63
+ center = 'FIXED'
64
+
65
+ config: Dict[str, Any] = {
66
+ 'points': points,
67
+ 'center': center,
68
+ }
69
+
70
+ if self.center == MapCenterType.FIXED:
71
+ if self.center_latlng is not None:
72
+ config['centerLatLng'] = self.center_latlng
73
+ else:
74
+ config['center'] = 'CONTAIN'
75
+
76
+ return config
77
+
78
+ def _render_leaflet(self: Self) -> Dict[str, Any]:
79
+ """
80
+ Converts the configuration of the chart to Leaflet map engine.
81
+ """
82
+ points = []
83
+
84
+ for point in self.points:
85
+ points.append({'label': point.label, 'color': point.color, 'latlng': (point.latitude, point.longitude)})
86
+
87
+ center = 'CONTAIN'
88
+
89
+ if self.center == MapCenterType.FIXED:
90
+ center = 'FIXED'
91
+
92
+ config: Dict[str, Any] = {
93
+ 'points': points,
94
+ 'title': self.title,
95
+ 'center': center,
96
+ }
97
+
98
+ if self.center == MapCenterType.FIXED:
99
+ if self.center_latlng is not None:
100
+ config['centerLatLng'] = self.center_latlng
101
+ else:
102
+ config['center'] = 'CONTAIN'
103
+
104
+ return config