1use {
2 crate::{objects::helper_objects::*, traits::*},
3 serde::{de, Deserialize, Serialize},
4 serde_json::Value,
5 std::{collections::HashMap, fmt::Debug},
6};
7
8#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
9pub struct SinglePointDataset {
10 #[serde(skip_serializing_if = "Vec::is_empty", default)]
11 pub(crate) backgroundColor: Vec<String>,
12 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
13 pub(crate) barPercentage: NumberString,
14 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
15 pub(crate) barThickness: NumberString,
16 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
17 pub(crate) base: NumberString,
18 #[serde(skip_serializing_if = "String::is_empty", default)]
19 pub(crate) borderColor: String,
20 #[serde(skip_serializing_if = "String::is_empty", default)]
21 pub(crate) borderJoinStyle: String,
22 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
23 pub(crate) borderRadius: NumberString,
24 #[serde(skip_serializing_if = "String::is_empty", default)]
25 pub(crate) borderSkipped: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
28 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
29 pub(crate) categoryPercentage: NumberString,
30 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
31 pub(crate) clip: NumberString,
32 #[serde(skip_serializing_if = "Vec::is_empty", default)]
33 pub(crate) data: Vec<NumberString>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub(crate) datalabels: Option<DataLabels>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub(crate) grouped: Option<bool>,
38 #[serde(skip_serializing_if = "String::is_empty", default)]
39 pub(crate) hoverBackgroundColor: String,
40 #[serde(skip_serializing_if = "String::is_empty", default)]
41 pub(crate) hoverBorderColor: String,
42 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
43 pub(crate) hoverBorderRadius: NumberString,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub(crate) hoverBorderWidth: Option<NumberStringOrT<Border>>,
46 #[serde(skip_serializing_if = "String::is_empty", default)]
47 pub(crate) indexAxis: String,
48 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
49 pub(crate) inflateAmount: NumberString,
50 #[serde(skip_serializing_if = "String::is_empty", default)]
51 pub(crate) label: String,
52 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
53 pub(crate) maxBarThickness: NumberString,
54 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
55 pub(crate) minBarLength: NumberString,
56 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
57 pub(crate) order: NumberString,
58 #[serde(skip_serializing_if = "String::is_empty", default)]
59 pub(crate) pointBackgroundColor: String,
60 #[serde(skip_serializing_if = "String::is_empty", default)]
61 pub(crate) pointBorderColor: String,
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub(crate) pointBorderWidth: Option<NumberStringOrT<Border>>,
64 #[serde(skip_serializing_if = "String::is_empty", default)]
65 pub(crate) pointHoverBackgroundColor: String,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub(crate) pointHoverBorderWidth: Option<NumberStringOrT<Border>>,
68 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
69 pub(crate) pointHoverRadius: NumberOrDateString,
70 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
71 pub(crate) pointRadius: NumberString,
72 #[serde(skip_serializing_if = "String::is_empty", default)]
73 pub(crate) pointStyle: String,
74 #[serde(rename = "type")]
75 #[serde(skip_serializing_if = "String::is_empty", default)]
76 pub(crate) r#type: String,
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub(crate) skipNull: Option<bool>,
79 #[serde(skip_serializing_if = "String::is_empty", default)]
80 pub(crate) stack: String,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub(crate) stepped: Option<bool>,
83 #[serde(skip_serializing_if = "String::is_empty", default)]
84 pub(crate) xAxisID: String,
85 #[serde(skip_serializing_if = "String::is_empty", default)]
86 pub(crate) yAxisID: String,
87}
88
89#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
90pub struct XYDataset {
91 #[serde(skip_serializing_if = "FnWithArgsOrT::is_empty", default)]
92 pub(crate) backgroundColor: FnWithArgsOrT<2, String>,
93 #[serde(
94 skip_serializing_if = "Vec::is_empty",
95 default,
96 rename(serialize = "backgroundColor")
97 )]
98 pub(crate) backgroundColorArray: Vec<String>,
99 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
100 pub(crate) barPercentage: NumberString,
101 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
102 pub(crate) barThickness: NumberString,
103 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
104 pub(crate) base: NumberString,
105 #[serde(skip_serializing_if = "String::is_empty", default)]
106 pub(crate) borderColor: String,
107 #[serde(skip_serializing_if = "Vec::is_empty", default)]
108 pub(crate) borderDash: Vec<NumberString>,
109 #[serde(skip_serializing_if = "String::is_empty", default)]
110 pub(crate) borderJoinStyle: String,
111 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
112 pub(crate) borderRadius: NumberString,
113 #[serde(skip_serializing_if = "String::is_empty", default)]
114 pub(crate) borderSkipped: String,
115 #[serde(skip_serializing_if = "Option::is_none")]
116 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
117 #[serde(skip_serializing_if = "String::is_empty", default)]
118 pub(crate) category_label: String,
119 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
120 pub(crate) categoryPercentage: NumberString,
121 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
122 pub(crate) clip: NumberString,
123 #[serde(skip_serializing_if = "DatasetData::is_empty", default)]
124 pub(crate) data: DatasetData,
125 pub(crate) datalabels: DataLabels,
127 #[serde(skip_serializing_if = "String::is_empty", default)]
128 pub(crate) description: String,
129 #[serde(skip_serializing_if = "String::is_empty", default)]
130 pub(crate) fill: String,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub(crate) grouped: Option<bool>,
133 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
134 pub(crate) hitRadius: NumberString,
135 #[serde(skip_serializing_if = "String::is_empty", default)]
136 pub(crate) hoverBackgroundColor: String,
137 #[serde(skip_serializing_if = "String::is_empty", default)]
138 pub(crate) hoverBorderColor: String,
139 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
140 pub(crate) hoverBorderRadius: NumberString,
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub(crate) hoverBorderWidth: Option<NumberStringOrT<Border>>,
143 #[serde(skip_serializing_if = "String::is_empty", default)]
144 pub(crate) axis: String,
145 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
146 pub(crate) inflateAmount: NumberString,
147 #[serde(skip_serializing_if = "String::is_empty", default)]
148 pub(crate) label: String,
149 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
150 pub(crate) maxBarThickness: NumberString,
151 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
152 pub(crate) minBarLength: NumberString,
153 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
154 pub(crate) order: NumberString,
155 #[serde(skip_serializing_if = "String::is_empty", default)]
156 pub(crate) pointBackgroundColor: String,
157 #[serde(skip_serializing_if = "String::is_empty", default)]
158 pub(crate) pointBorderColor: String,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub(crate) pointBorderWidth: Option<NumberStringOrT<Border>>,
161 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
162 pub(crate) pointHitRadius: NumberString,
163 #[serde(skip_serializing_if = "String::is_empty", default)]
164 pub(crate) pointHoverBackgroundColor: String,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub(crate) pointHoverBorderWidth: Option<NumberStringOrT<Border>>,
167 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
168 pub(crate) pointHoverRadius: NumberOrDateString,
169 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
170 pub(crate) pointRadius: NumberString,
171 #[serde(skip_serializing_if = "String::is_empty", default)]
172 pub(crate) pointStyle: String,
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub(crate) segment: Option<Segment>,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub(crate) skipNull: Option<bool>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub(crate) spanGaps: Option<bool>,
179 #[serde(skip_serializing_if = "String::is_empty", default)]
180 pub(crate) stack: String,
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub(crate) stepped: Option<BoolString>,
183 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
184 pub(crate) tension: NumberString,
185 #[serde(rename = "type")]
186 #[serde(skip_serializing_if = "String::is_empty", default)]
187 pub(crate) r#type: String,
188 #[serde(skip_serializing_if = "String::is_empty", default)]
189 pub(crate) xAxisID: String,
190 #[serde(skip_serializing_if = "String::is_empty", default)]
191 pub(crate) yAxisID: String,
192 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
193 pub(crate) z: NumberString,
194}
195
196#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)]
197pub struct XYPoint {
198 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
199 pub(crate) x: NumberOrDateString,
200
201 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
202 pub(crate) y: NumberString,
203
204 #[serde(skip_serializing_if = "serde_json::Value::is_null", default)]
205 pub(crate) description: serde_json::Value,
206}
207
208#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)]
209pub struct ChartOptions {
210 #[serde(skip_serializing_if = "Option::is_none")]
211 pub(crate) animation: Option<Animation>,
212 #[serde(skip_serializing_if = "Option::is_none")]
213 pub(crate) elements: Option<ChartElements>,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub(crate) interaction: Option<ChartInteraction>,
216 #[serde(skip_serializing_if = "String::is_empty", default)]
217 pub(crate) indexAxis: String,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub(crate) legend: Option<ChartLegend>,
220 #[serde(skip_serializing_if = "Option::is_none")]
221 pub(crate) layout: Option<ChartLayout>,
222 #[serde(skip_serializing_if = "Option::is_none")]
223 pub(crate) maintainAspectRatio: Option<bool>,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub(crate) plugins: Option<ChartPlugins>,
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub(crate) responsive: Option<bool>,
228 #[serde(skip_serializing_if = "Option::is_none")]
229 pub(crate) scales: Option<HashMap<String, ChartScale>>,
230 #[serde(skip_serializing_if = "Option::is_none")]
231 pub(crate) spanGaps: Option<bool>,
232}
233
234#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
235pub struct Animation {
236 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
237 pub(crate) duration: NumberString,
238}
239
240#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)]
241pub struct ChartPlugins {
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub(crate) annotation: Option<Annotations>,
244 #[serde(skip_serializing_if = "Option::is_none")]
245 pub(crate) autocolors: Option<AutoColors>,
246 #[serde(skip_serializing_if = "Option::is_none")]
247 pub(crate) legend: Option<PluginLegend>,
248 #[serde(skip_serializing_if = "Option::is_none")]
249 pub(crate) title: Option<Title>,
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub(crate) tooltip: Option<TooltipPlugin>,
252}
253
254#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
255pub struct PluginLegend {
256 #[serde(skip_serializing_if = "Option::is_none")]
257 pub(crate) display: Option<bool>,
258 #[serde(skip_serializing_if = "Option::is_none")]
259 pub(crate) labels: Option<LegendLabel>,
260 #[serde(skip_serializing_if = "String::is_empty", default)]
261 pub(crate) position: String,
262 #[serde(skip_serializing_if = "Option::is_none")]
263 pub(crate) reverse: Option<bool>,
264}
265
266#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq)]
267pub struct Annotations {
268 #[serde(skip_serializing_if = "Option::is_none")]
269 pub(crate) annotations: Option<HashMap<String, Annotation>>,
270}
271
272#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
273pub struct AutoColors {
274 #[serde(skip_serializing_if = "String::is_empty", default)]
275 pub(crate) mode: String,
276}
277
278#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
279pub struct TooltipPlugin {
280 #[serde(skip_serializing_if = "String::is_empty", default)]
281 pub(crate) backgroundColor: String,
282 #[serde(skip_serializing_if = "String::is_empty", default)]
283 pub(crate) bodyAlign: String,
284 #[serde(skip_serializing_if = "String::is_empty", default)]
285 pub(crate) bodyColor: String,
286 #[serde(skip_serializing_if = "Option::is_none")]
287 pub(crate) callbacks: Option<TooltipCallbacks>,
288 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
289 pub(crate) filter: FnWithArgs<1>,
291 #[serde(skip_serializing_if = "Option::is_none")]
292 pub(crate) displayColors: Option<bool>,
293 #[serde(skip_serializing_if = "Option::is_none")]
294 pub(crate) enabled: Option<bool>,
295 #[serde(skip_serializing_if = "String::is_empty", default)]
296 pub(crate) titleAlign: String,
297 #[serde(skip_serializing_if = "String::is_empty", default)]
298 pub(crate) titleColor: String,
299 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
300 pub(crate) titleMarginBottom: NumberString,
301}
302
303#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
304pub struct ChartLayout {
305 #[serde(skip_serializing_if = "Option::is_none")]
306 pub(crate) padding: Option<Padding>,
307}
308
309#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
310pub struct TooltipCallbacks {
311 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
312 pub(crate) label: FnWithArgs<1>,
314 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
315 pub(crate) title: FnWithArgs<1>,
317}
318
319#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
320pub struct ChartScale {
321 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
322 pub(crate) afterBuildTicks: FnWithArgs<1>,
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub(crate) alignToPixels: Option<bool>,
326 #[serde(skip_serializing_if = "String::is_empty", default)]
327 pub(crate) backgroundColor: String,
328 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
329 pub(crate) barPercentage: NumberString,
330 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
331 pub(crate) beforeFit: FnWithArgs<1>,
333 #[serde(skip_serializing_if = "Option::is_none")]
334 pub(crate) beginAtZero: Option<bool>,
335 #[serde(skip_serializing_if = "Option::is_none")]
336 pub(crate) border: Option<ScaleBorder>,
337 #[serde(skip_serializing_if = "String::is_empty", default)]
338 pub(crate) bounds: String,
339 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
340 pub(crate) categoryPercentage: NumberString,
341 #[serde(skip_serializing_if = "Option::is_none")]
342 pub(crate) display: Option<bool>,
343 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
344 pub(crate) grace: NumberOrDateString,
345 #[serde(skip_serializing_if = "Option::is_none")]
346 pub(crate) grid: Option<Grid>,
347 #[serde(skip_serializing_if = "Option::is_none")]
348 pub(crate) grouped: Option<bool>,
349 #[serde(skip_serializing_if = "Option::is_none")]
350 pub(crate) labels: Option<Vec<NumberOrDateString>>,
351 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
352 pub(crate) max: NumberOrDateString,
353 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
354 pub(crate) min: NumberOrDateString,
355 #[serde(skip_serializing_if = "Option::is_none")]
356 pub(crate) offset: Option<bool>,
357 #[serde(skip_serializing_if = "String::is_empty", default)]
358 pub(crate) position: String,
359 #[serde(skip_serializing_if = "Option::is_none")]
360 pub(crate) reverse: Option<bool>,
361 #[serde(skip_serializing_if = "Option::is_none")]
362 pub(crate) stacked: Option<bool>,
363 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
364 pub(crate) suggestedMax: NumberOrDateString,
365 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
366 pub(crate) suggestedMin: NumberOrDateString,
367 #[serde(skip_serializing_if = "Option::is_none")]
368 pub(crate) ticks: Option<ScaleTicks>,
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub(crate) time: Option<ScaleTime>,
371 #[serde(skip_serializing_if = "Option::is_none")]
372 pub(crate) title: Option<Title>,
373 #[serde(skip_serializing_if = "String::is_empty", default)]
374 #[serde(rename = "type")]
375 pub(crate) r#type: String,
376 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
377 pub(crate) weight: NumberString,
378}
379
380#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
381pub struct ScaleBorder {
382 #[serde(skip_serializing_if = "String::is_empty", default)]
383 pub(crate) color: String,
384 #[serde(skip_serializing_if = "Vec::is_empty", default)]
385 pub(crate) dash: Vec<NumberString>,
386 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
387 pub(crate) dashOffset: NumberString,
388 #[serde(skip_serializing_if = "Option::is_none")]
389 pub(crate) display: Option<bool>,
390 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
391 pub(crate) width: NumberString,
392 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
393 pub(crate) z: NumberString,
394}
395
396#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
397pub struct Grid {
398 #[serde(skip_serializing_if = "String::is_empty", default)]
399 pub(crate) color: String,
400 #[serde(skip_serializing_if = "Option::is_none")]
401 pub(crate) display: Option<bool>,
402 #[serde(skip_serializing_if = "Option::is_none")]
403 pub(crate) drawOnChartArea: Option<bool>,
404 #[serde(skip_serializing_if = "Option::is_none")]
405 pub(crate) offset: Option<bool>,
406 #[serde(skip_serializing_if = "String::is_empty", default, skip_deserializing)]
407 pub(crate) tickColor: String,
409 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
410 pub(crate) z: NumberString,
411}
412
413#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
414pub struct Callout {
415 #[serde(skip_serializing_if = "String::is_empty", default)]
416 pub(crate) backgroundColor: String,
417 #[serde(skip_serializing_if = "String::is_empty", default)]
418 pub(crate) borderColor: String,
419 #[serde(skip_serializing_if = "Vec::is_empty", default)]
420 pub(crate) borderDash: Vec<NumberString>,
421 #[serde(skip_serializing_if = "Option::is_none")]
422 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
423 #[serde(skip_serializing_if = "Option::is_none")]
424 pub(crate) display: Option<bool>,
425 #[serde(skip_serializing_if = "String::is_empty", default)]
426 pub(crate) position: String,
427 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
428 pub(crate) start: NumberString,
429}
430
431#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
432pub struct LabelAnnotation {
433 #[serde(skip_serializing_if = "String::is_empty", default)]
434 pub(crate) backgroundColor: String,
435 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
436 pub(crate) borderRadius: NumberString,
437 #[serde(skip_serializing_if = "String::is_empty", default)]
438 pub(crate) borderColor: String,
439 #[serde(skip_serializing_if = "Vec::is_empty", default)]
440 pub(crate) borderDash: Vec<NumberString>,
441 #[serde(skip_serializing_if = "Option::is_none")]
442 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub(crate) callout: Option<Callout>,
445 #[serde(skip_serializing_if = "String::is_empty", default)]
446 pub(crate) color: String,
447 #[serde(skip_serializing_if = "Vec::is_empty", default)]
448 pub(crate) content: Vec<String>,
449 #[serde(skip_serializing_if = "String::is_empty", default)]
450 pub(crate) drawTime: String,
451 #[serde(skip_serializing_if = "Option::is_none")]
452 pub(crate) display: Option<bool>,
453 #[serde(skip_serializing_if = "Option::is_none")]
454 pub(crate) font: Option<Font>,
455 #[serde(skip_serializing_if = "Option::is_none", skip_deserializing)]
456 pub(crate) padding: Option<Padding>,
458 #[serde(skip_serializing_if = "String::is_empty", default)]
459 pub(crate) position: String,
460 #[serde(default, rename = "type")]
461 pub(crate) r#type: LabelAnnotationType,
462 #[serde(skip_serializing_if = "String::is_empty", default)]
463 pub(crate) textAlign: String,
464 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
465 pub(crate) xValue: NumberOrDateString,
466 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
467 pub(crate) xAdjust: NumberOrDateString,
468 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
469 pub(crate) yValue: NumberOrDateString,
470 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
471 pub(crate) yAdjust: NumberOrDateString,
472 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
473 pub(crate) xMax: NumberOrDateString,
474 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
475 pub(crate) xMin: NumberOrDateString,
476 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
477 pub(crate) yMax: NumberOrDateString,
478 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
479 pub(crate) yMin: NumberOrDateString,
480 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
481 pub(crate) yScaleID: NumberString,
482}
483#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
484pub struct LabelAnnotationType;
485
486#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
487pub struct LineAnnotation {
488 #[serde(skip_serializing_if = "String::is_empty", default)]
489 pub(crate) borderColor: String,
490 #[serde(skip_serializing_if = "Vec::is_empty", default)]
491 pub(crate) borderDash: Vec<NumberString>,
492 #[serde(skip_serializing_if = "Option::is_none")]
493 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
494 #[serde(skip_serializing_if = "String::is_empty", default)]
495 pub(crate) drawTime: String,
496 #[serde(skip_serializing_if = "Option::is_none")]
497 pub(crate) label: Option<LabelAnnotation>,
498 #[serde(default, rename = "type")]
499 pub(crate) r#type: LineAnnotationType,
500 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
501 pub(crate) xMax: NumberOrDateString,
502 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
503 pub(crate) xMin: NumberOrDateString,
504 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
505 pub(crate) yMax: NumberOrDateString,
506 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
507 pub(crate) yMin: NumberOrDateString,
508 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
509 pub(crate) yScaleID: NumberString,
510}
511#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
512pub struct LineAnnotationType;
513
514#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
515pub struct BoxAnnotation {
516 #[serde(skip_serializing_if = "String::is_empty", default)]
517 pub(crate) backgroundColor: String,
518 #[serde(skip_serializing_if = "String::is_empty", default)]
519 pub(crate) borderColor: String,
520 #[serde(skip_serializing_if = "Vec::is_empty", default)]
521 pub(crate) borderDash: Vec<NumberString>,
522 #[serde(skip_serializing_if = "Option::is_none")]
523 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
524 #[serde(skip_serializing_if = "String::is_empty", default)]
525 pub(crate) drawTime: String,
526 #[serde(default, rename = "type")]
527 pub(crate) r#type: BoxAnnotationType,
528 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
529 pub(crate) xMax: NumberString,
530 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
531 pub(crate) xMin: NumberString,
532 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
533 pub(crate) yMax: NumberString,
534 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
535 pub(crate) yMin: NumberString,
536}
537#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
538pub struct BoxAnnotationType;
539
540#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
541pub struct ScaleTime {
542 #[serde(skip_serializing_if = "Option::is_none")]
543 pub(crate) displayFormats: Option<DisplayFormats>,
544 #[serde(skip_serializing_if = "String::is_empty", default)]
545 pub(crate) unit: String,
546}
547
548#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
549pub struct DisplayFormats {
550 #[serde(skip_serializing_if = "String::is_empty", default)]
551 pub(crate) day: String,
552 #[serde(skip_serializing_if = "String::is_empty", default)]
553 pub(crate) hour: String,
554 #[serde(skip_serializing_if = "String::is_empty", default)]
555 pub(crate) minute: String,
556 #[serde(skip_serializing_if = "String::is_empty", default)]
557 pub(crate) month: String,
558 #[serde(skip_serializing_if = "String::is_empty", default)]
559 pub(crate) quarter: String,
560 #[serde(skip_serializing_if = "String::is_empty", default)]
561 pub(crate) week: String,
562 #[serde(skip_serializing_if = "String::is_empty", default)]
563 pub(crate) year: String,
564}
565
566#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
567pub struct ScaleTicks {
568 #[serde(skip_serializing_if = "Option::is_none")]
569 pub(crate) autoSkip: Option<bool>,
570 #[serde(skip_serializing_if = "String::is_empty", default)]
571 pub(crate) align: String,
572 #[serde(
573 skip_serializing_if = "FnWithArgs::is_empty",
574 default,
575 skip_deserializing )]
577 pub(crate) callback: FnWithArgs<3>,
578 #[serde(skip_serializing_if = "String::is_empty", default)]
579 pub(crate) color: String,
580 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
581 pub(crate) count: NumberString,
582 #[serde(skip_serializing_if = "Option::is_none")]
583 pub(crate) font: Option<Font>,
584 #[serde(skip_serializing_if = "Option::is_none")]
585 pub(crate) includeBounds: Option<bool>,
586 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
587 pub(crate) maxTicksLimit: NumberString,
588 #[serde(skip_serializing_if = "Option::is_none", skip_deserializing)]
589 pub(crate) padding: Option<Padding>,
591 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
592 pub(crate) precision: NumberString,
593 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
594 pub(crate) stepSize: NumberString,
595}
596
597#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
598pub struct Title {
599 #[serde(skip_serializing_if = "String::is_empty", default)]
600 pub(crate) color: String,
601 #[serde(skip_serializing_if = "Option::is_none")]
602 pub(crate) display: Option<bool>,
603 #[serde(skip_serializing_if = "Option::is_none")]
604 pub(crate) font: Option<Font>,
605 #[serde(skip_serializing_if = "String::is_empty", default)]
606 pub(crate) text: String,
607}
608
609#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
610pub struct ChartInteraction {
611 #[serde(skip_serializing_if = "String::is_empty", default)]
612 pub(crate) axis: String,
613 #[serde(skip_serializing_if = "Option::is_none")]
614 pub(crate) intersect: Option<bool>,
615 #[serde(skip_serializing_if = "String::is_empty", default)]
616 pub(crate) mode: String,
617}
618
619#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
620pub struct ChartLegend {
621 #[serde(skip_serializing_if = "Option::is_none")]
622 pub(crate) display: Option<bool>,
623 #[serde(skip_serializing_if = "Option::is_none")]
624 pub(crate) labels: Option<LegendLabel>,
625 #[serde(skip_serializing_if = "String::is_empty", default)]
626 pub(crate) position: String,
627}
628
629#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
630pub struct LegendLabel {
631 #[serde(skip_serializing_if = "Option::is_none")]
632 pub(crate) boxHeight: Option<u32>,
633 #[serde(skip_serializing_if = "Option::is_none")]
634 pub(crate) boxWidth: Option<u32>,
635 #[serde(skip_serializing_if = "String::is_empty", default)]
636 pub(crate) color: String,
637 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
638 pub(crate) filter: FnWithArgs<2>,
640 #[serde(skip_serializing_if = "Option::is_none")]
641 pub(crate) font: Option<Font>,
642 #[serde(skip_serializing_if = "String::is_empty", default)]
643 pub(crate) pointStyle: String,
644 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
645 pub(crate) pointStyleWidth: NumberString,
646 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
647 pub(crate) sort: FnWithArgs<3>,
649 #[serde(skip_serializing_if = "Option::is_none")]
650 pub(crate) useBorderRadius: Option<bool>,
651 #[serde(skip_serializing_if = "Option::is_none")]
652 pub(crate) usePointStyle: Option<bool>,
653}
654
655#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
656pub struct ChartElements {
657 #[serde(skip_serializing_if = "Option::is_none")]
658 pub(crate) bar: Option<BarElementConfiguration>,
659 #[serde(skip_serializing_if = "Option::is_none")]
660 pub(crate) line: Option<LineElementConfiguration>,
661 #[serde(skip_serializing_if = "Option::is_none")]
662 pub(crate) point: Option<PointElementConfiguration>,
663}
664
665#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
666pub struct BarElementConfiguration {
667 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
668 pub(crate) borderRadius: NumberString,
669 #[serde(skip_serializing_if = "Option::is_none")]
670 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
671 #[serde(skip_serializing_if = "Option::is_none")]
672 pub(crate) fill: Option<bool>,
673 #[serde(skip_serializing_if = "Option::is_none")]
674 pub(crate) hoverBorderWidth: Option<NumberStringOrT<Border>>,
675}
676
677#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
678pub struct LineElementConfiguration {
679 #[serde(skip_serializing_if = "Option::is_none")]
680 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
681 #[serde(skip_serializing_if = "String::is_empty", default)]
682 pub(crate) cubicInterpolationMode: String,
683 #[serde(skip_serializing_if = "Option::is_none")]
684 pub(crate) fill: Option<bool>,
685}
686
687#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
688pub struct PointElementConfiguration {
689 #[serde(skip_serializing_if = "Option::is_none")]
690 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
691 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
692 pub(crate) hitRadius: NumberString,
693 #[serde(skip_serializing_if = "Option::is_none")]
694 pub(crate) hoverBorderWidth: Option<NumberStringOrT<Border>>,
695 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
696 pub(crate) hoverRadius: NumberString,
697 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
698 pub(crate) radius: NumberString,
699}
700
701#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
702pub struct DataLabels {
703 #[serde(skip_serializing_if = "FnWithArgsOrT::is_empty", default)]
704 pub(crate) align: FnWithArgsOrT<1, String>,
705 #[serde(skip_serializing_if = "FnWithArgsOrT::is_empty", default)]
706 pub(crate) anchor: FnWithArgsOrT<1, String>,
707 #[serde(skip_serializing_if = "FnWithArgsOrT::is_empty", default)]
708 pub(crate) backgroundColor: FnWithArgsOrT<1, String>,
709 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
710 pub(crate) borderRadius: NumberString,
711 #[serde(skip_serializing_if = "Option::is_none")]
712 pub(crate) clamp: Option<bool>,
713 #[serde(skip_serializing_if = "Option::is_none")]
714 pub(crate) clip: Option<bool>,
715 #[serde(skip_serializing_if = "String::is_empty", default)]
716 pub(crate) color: String,
717 #[serde(skip_serializing_if = "FnWithArgsOrT::is_empty", default)]
718 pub(crate) display: FnWithArgsOrT<1, BoolString>,
719 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
720 pub(crate) drawTime: NumberString,
721 #[serde(skip_serializing_if = "Option::is_none")]
722 pub(crate) font: Option<Font>,
723 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
724 pub(crate) formatter: FnWithArgs<2>,
726 #[serde(skip_serializing_if = "FnWithArgsOrT::is_empty", default)]
727 pub(crate) offset: FnWithArgsOrT<1, NumberString>,
729 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
730 pub(crate) opacity: NumberString,
731 #[serde(skip_serializing_if = "Option::is_none")]
732 pub(crate) padding: Option<Padding>,
733 #[serde(skip_serializing_if = "Option::is_none")]
734 pub(crate) rotation: Option<i16>,
735 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
736 pub(crate) z: NumberString,
737}
738
739#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
740pub struct Border {
741 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
742 pub(crate) bottom: NumberString,
743 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
744 pub(crate) left: NumberString,
745 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
746 pub(crate) right: NumberString,
747 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
748 pub(crate) top: NumberString,
749}
750#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
751pub struct Padding {
752 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
753 pub(crate) bottom: NumberString,
754 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
755 pub(crate) left: NumberString,
756 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
757 pub(crate) right: NumberString,
758 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
759 pub(crate) top: NumberString,
760}
761
762#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
763pub struct Font {
764 #[serde(skip_serializing_if = "String::is_empty", default)]
765 pub(crate) family: String,
766 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
767 pub(crate) lineHeight: NumberString,
768 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
769 pub(crate) size: NumberString,
770 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
771 pub(crate) style: NumberString,
772 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
773 pub(crate) weight: NumberString,
774}
775
776#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)]
777pub struct Segment {
778 #[serde(
779 skip_serializing_if = "FnWithArgs::is_empty",
780 default,
781 skip_deserializing )]
783 pub(crate) borderColor: FnWithArgs<1>,
784 #[serde(
785 skip_serializing_if = "FnWithArgs::is_empty",
786 default,
787 skip_deserializing )]
789 pub(crate) borderDash: FnWithArgs<1>,
790}
791
792impl DatasetTrait for Vec<SinglePointDataset> {
794 fn labels(self) -> Vec<NumberOrDateString> {
795 let mut vec = self
796 .into_iter()
797 .map(|spd| spd.label.into())
798 .collect::<Vec<_>>();
799
800 vec.sort_by(crate::get_order_fn);
801 vec.dedup();
802 vec
803 }
804}
805impl DatasetTrait for Vec<XYDataset> {
806 fn labels(self) -> Vec<NumberOrDateString> {
807 let mut vec = self
808 .into_iter()
809 .filter_map(|xyd| {
810 let data = xyd.data.0.as_array()?;
811 let keys = data
813 .iter()
814 .filter_map(|xy| xy.as_object())
815 .filter_map(|obj| obj.get("x"))
816 .filter_map(|x| {
817 x.as_str()
818 .map(|s| s.to_string())
819 .or(x.as_number().map(|num| num.to_string()))
820 })
821 .map(|x| x.into())
822 .collect::<Vec<NumberOrDateString>>();
823 Some(keys)
824 })
825 .flatten()
826 .collect::<Vec<_>>();
827 vec.sort_by(crate::get_order_fn);
830 vec.dedup();
831 vec
832 }
833}
834#[allow(clippy::large_enum_variant)]
836#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
837#[serde(untagged)]
838pub enum Annotation {
839 Box(BoxAnnotation),
840 Line(LineAnnotation),
841 Label(LabelAnnotation),
842}
843
844impl Default for Annotation {
845 fn default() -> Self {
846 Self::Line(Default::default())
847 }
848}
849impl From<BoxAnnotation> for Annotation {
850 fn from(value: BoxAnnotation) -> Self {
851 Self::Box(value)
852 }
853}
854impl From<LineAnnotation> for Annotation {
855 fn from(value: LineAnnotation) -> Self {
856 Self::Line(value)
857 }
858}
859impl From<LabelAnnotation> for Annotation {
860 fn from(value: LabelAnnotation) -> Self {
861 Self::Label(value)
862 }
863}
864impl From<(NumberOrDateString, NumberString, Option<Value>)> for XYPoint {
866 fn from((x, y, d): (NumberOrDateString, NumberString, Option<Value>)) -> Self {
867 XYPoint {
868 x,
869 y,
870 description: d.unwrap_or_default(),
871 }
872 }
873}
874impl Ord for XYPoint {
876 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
877 self.x.cmp(&other.x)
878 }
879}
880impl PartialOrd for XYPoint {
882 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
883 Some(self.cmp(other))
884 }
885}
886impl Serialize for BoxAnnotationType {
888 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
889 where
890 S: serde::Serializer,
891 {
892 serializer.serialize_str("box")
893 }
894}
895impl Serialize for LineAnnotationType {
897 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
898 where
899 S: serde::Serializer,
900 {
901 serializer.serialize_str("line")
902 }
903}
904impl Serialize for LabelAnnotationType {
906 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
907 where
908 S: serde::Serializer,
909 {
910 serializer.serialize_str("label")
911 }
912}
913impl<'de> Deserialize<'de> for BoxAnnotationType {
915 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
916 where
917 D: serde::Deserializer<'de>,
918 {
919 match String::deserialize(deserializer)?.to_lowercase().as_str() {
920 "box" => Ok(BoxAnnotationType),
921 other => Err(de::Error::custom(format!(
922 "`{other}` is not a valid BoxAnnotationType."
923 ))),
924 }
925 }
926}
927impl<'de> Deserialize<'de> for LineAnnotationType {
929 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
930 where
931 D: serde::Deserializer<'de>,
932 {
933 match String::deserialize(deserializer)?.to_lowercase().as_str() {
934 "line" => Ok(LineAnnotationType),
935 other => Err(de::Error::custom(format!(
936 "`{other}` is not a valid LineAnnotationType."
937 ))),
938 }
939 }
940}
941impl<'de> Deserialize<'de> for LabelAnnotationType {
943 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
944 where
945 D: serde::Deserializer<'de>,
946 {
947 match String::deserialize(deserializer)?.to_lowercase().as_str() {
948 "label" => Ok(LabelAnnotationType),
949 other => Err(de::Error::custom(format!(
950 "`{other}` is not a valid LabelAnnotationType."
951 ))),
952 }
953 }
954}
955