1use {
2 crate::{objects::helper_objects::*, traits::*, utils::FnWithArgs},
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 = "FnWithArgsOrAny::is_empty", default)]
92 pub(crate) backgroundColor: FnWithArgsOrAny<2>,
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<A: Annotation> {
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<A>>,
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<A: Annotation> {
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub(crate) annotation: Option<Annotations<A>>,
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<A: Annotation> {
268 #[serde(skip_serializing_if = "Option::is_none")]
269 pub(crate) annotations: Option<HashMap<String, A>>,
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 = "String::is_empty", default, skip_deserializing)]
405 pub(crate) tickColor: String,
407 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
408 pub(crate) z: NumberString,
409}
410
411#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
412pub struct LineAnnotation {
413 #[serde(skip_serializing_if = "String::is_empty", default)]
414 pub(crate) borderColor: String,
415 #[serde(skip_serializing_if = "Vec::is_empty", default)]
416 pub(crate) borderDash: Vec<NumberString>,
417 #[serde(skip_serializing_if = "Option::is_none")]
418 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
419 #[serde(skip_serializing_if = "String::is_empty", default)]
420 pub(crate) drawTime: String,
421 #[serde(default, rename = "type")]
422 pub(crate) r#type: LineAnnotationType,
423 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
424 pub(crate) xMax: NumberOrDateString,
425 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
426 pub(crate) xMin: NumberOrDateString,
427 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
428 pub(crate) yMax: NumberOrDateString,
429 #[serde(skip_serializing_if = "NumberOrDateString::is_empty", default)]
430 pub(crate) yMin: NumberOrDateString,
431 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
432 pub(crate) yScaleID: NumberString,
433}
434#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
435pub struct LineAnnotationType;
436
437#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
438pub struct BoxAnnotation {
439 #[serde(skip_serializing_if = "String::is_empty", default)]
440 pub(crate) backgroundColor: String,
441 #[serde(skip_serializing_if = "String::is_empty", default)]
442 pub(crate) borderColor: String,
443 #[serde(skip_serializing_if = "Vec::is_empty", default)]
444 pub(crate) borderDash: Vec<NumberString>,
445 #[serde(skip_serializing_if = "Option::is_none")]
446 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
447 #[serde(skip_serializing_if = "String::is_empty", default)]
448 pub(crate) drawTime: String,
449 #[serde(default, rename = "type")]
450 pub(crate) r#type: BoxAnnotationType,
451 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
452 pub(crate) xMax: NumberString,
453 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
454 pub(crate) xMin: NumberString,
455 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
456 pub(crate) yMax: NumberString,
457 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
458 pub(crate) yMin: NumberString,
459}
460#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
461pub struct BoxAnnotationType;
462
463#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
464pub struct ScaleTime {
465 #[serde(skip_serializing_if = "Option::is_none")]
466 pub(crate) displayFormats: Option<DisplayFormats>,
467 #[serde(skip_serializing_if = "String::is_empty", default)]
468 pub(crate) unit: String,
469}
470
471#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
472pub struct DisplayFormats {
473 #[serde(skip_serializing_if = "String::is_empty", default)]
474 pub(crate) day: String,
475 #[serde(skip_serializing_if = "String::is_empty", default)]
476 pub(crate) hour: String,
477 #[serde(skip_serializing_if = "String::is_empty", default)]
478 pub(crate) minute: String,
479 #[serde(skip_serializing_if = "String::is_empty", default)]
480 pub(crate) month: String,
481 #[serde(skip_serializing_if = "String::is_empty", default)]
482 pub(crate) quarter: String,
483 #[serde(skip_serializing_if = "String::is_empty", default)]
484 pub(crate) week: String,
485 #[serde(skip_serializing_if = "String::is_empty", default)]
486 pub(crate) year: String,
487}
488
489#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
490pub struct ScaleTicks {
491 #[serde(skip_serializing_if = "Option::is_none")]
492 pub(crate) autoSkip: Option<bool>,
493 #[serde(skip_serializing_if = "String::is_empty", default)]
494 pub(crate) align: String,
495 #[serde(
496 skip_serializing_if = "FnWithArgs::is_empty",
497 default,
498 skip_deserializing )]
500 pub(crate) callback: FnWithArgs<3>,
501 #[serde(skip_serializing_if = "String::is_empty", default)]
502 pub(crate) color: String,
503 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
504 pub(crate) count: NumberString,
505 #[serde(skip_serializing_if = "Option::is_none")]
506 pub(crate) font: Option<Font>,
507 #[serde(skip_serializing_if = "Option::is_none")]
508 pub(crate) includeBounds: Option<bool>,
509 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
510 pub(crate) maxTicksLimit: NumberString,
511 #[serde(skip_serializing_if = "Option::is_none", skip_deserializing)]
512 pub(crate) padding: Option<Padding>,
514 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
515 pub(crate) precision: NumberString,
516 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
517 pub(crate) stepSize: NumberString,
518}
519
520#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
521pub struct Title {
522 #[serde(skip_serializing_if = "String::is_empty", default)]
523 pub(crate) color: String,
524 #[serde(skip_serializing_if = "Option::is_none")]
525 pub(crate) display: Option<bool>,
526 #[serde(skip_serializing_if = "Option::is_none")]
527 pub(crate) font: Option<Font>,
528 #[serde(skip_serializing_if = "String::is_empty", default)]
529 pub(crate) text: String,
530}
531
532#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
533pub struct ChartInteraction {
534 #[serde(skip_serializing_if = "String::is_empty", default)]
535 pub(crate) axis: String,
536 #[serde(skip_serializing_if = "Option::is_none")]
537 pub(crate) intersect: Option<bool>,
538 #[serde(skip_serializing_if = "String::is_empty", default)]
539 pub(crate) mode: String,
540}
541
542#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
543pub struct ChartLegend {
544 #[serde(skip_serializing_if = "Option::is_none")]
545 pub(crate) display: Option<bool>,
546 #[serde(skip_serializing_if = "Option::is_none")]
547 pub(crate) labels: Option<LegendLabel>,
548 #[serde(skip_serializing_if = "String::is_empty", default)]
549 pub(crate) position: String,
550}
551
552#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
553pub struct LegendLabel {
554 #[serde(skip_serializing_if = "Option::is_none")]
555 pub(crate) boxHeight: Option<u32>,
556 #[serde(skip_serializing_if = "Option::is_none")]
557 pub(crate) boxWidth: Option<u32>,
558 #[serde(skip_serializing_if = "String::is_empty", default)]
559 pub(crate) color: String,
560 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
561 pub(crate) filter: FnWithArgs<2>,
563 #[serde(skip_serializing_if = "Option::is_none")]
564 pub(crate) font: Option<Font>,
565 #[serde(skip_serializing_if = "String::is_empty", default)]
566 pub(crate) pointStyle: String,
567 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
568 pub(crate) pointStyleWidth: NumberString,
569 #[serde(skip_serializing_if = "Option::is_none")]
570 pub(crate) useBorderRadius: Option<bool>,
571 #[serde(skip_serializing_if = "Option::is_none")]
572 pub(crate) usePointStyle: Option<bool>,
573}
574
575#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
576pub struct ChartElements {
577 #[serde(skip_serializing_if = "Option::is_none")]
578 pub(crate) bar: Option<BarElementConfiguration>,
579 #[serde(skip_serializing_if = "Option::is_none")]
580 pub(crate) line: Option<LineElementConfiguration>,
581 #[serde(skip_serializing_if = "Option::is_none")]
582 pub(crate) point: Option<PointElementConfiguration>,
583}
584
585#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
586pub struct BarElementConfiguration {
587 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
588 pub(crate) borderRadius: NumberString,
589 #[serde(skip_serializing_if = "Option::is_none")]
590 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
591 #[serde(skip_serializing_if = "Option::is_none")]
592 pub(crate) fill: Option<bool>,
593 #[serde(skip_serializing_if = "Option::is_none")]
594 pub(crate) hoverBorderWidth: Option<NumberStringOrT<Border>>,
595}
596
597#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
598pub struct LineElementConfiguration {
599 #[serde(skip_serializing_if = "Option::is_none")]
600 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
601 #[serde(skip_serializing_if = "String::is_empty", default)]
602 pub(crate) cubicInterpolationMode: String,
603 #[serde(skip_serializing_if = "Option::is_none")]
604 pub(crate) fill: Option<bool>,
605}
606
607#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
608pub struct PointElementConfiguration {
609 #[serde(skip_serializing_if = "Option::is_none")]
610 pub(crate) borderWidth: Option<NumberStringOrT<Border>>,
611 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
612 pub(crate) hitRadius: NumberString,
613 #[serde(skip_serializing_if = "Option::is_none")]
614 pub(crate) hoverBorderWidth: Option<NumberStringOrT<Border>>,
615 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
616 pub(crate) hoverRadius: NumberString,
617 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
618 pub(crate) radius: NumberString,
619}
620
621#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
622pub struct DataLabels {
623 #[serde(skip_serializing_if = "FnWithArgsOrAny::is_empty", default)]
624 pub(crate) align: FnWithArgsOrAny<1>,
625 #[serde(skip_serializing_if = "FnWithArgsOrAny::is_empty", default)]
626 pub(crate) anchor: FnWithArgsOrAny<1>,
627 #[serde(skip_serializing_if = "FnWithArgsOrAny::is_empty", default)]
628 pub(crate) backgroundColor: FnWithArgsOrAny<1>,
629 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
630 pub(crate) borderRadius: NumberString,
631 #[serde(skip_serializing_if = "Option::is_none")]
632 pub(crate) clamp: Option<bool>,
633 #[serde(skip_serializing_if = "Option::is_none")]
634 pub(crate) clip: Option<bool>,
635 #[serde(skip_serializing_if = "String::is_empty", default)]
636 pub(crate) color: String,
637 #[serde(default = "BoolString::_false")]
638 pub(crate) display: BoolString,
639 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
640 pub(crate) drawTime: NumberString,
641 #[serde(skip_serializing_if = "Option::is_none")]
642 pub(crate) font: Option<Font>,
643 #[serde(skip_serializing_if = "FnWithArgs::is_empty", skip_deserializing)]
644 pub(crate) formatter: FnWithArgs<2>,
646 #[serde(skip_serializing_if = "FnWithArgsOrAny::is_empty", default)]
647 pub(crate) offset: FnWithArgsOrAny<1>,
649 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
650 pub(crate) opacity: NumberString,
651 #[serde(skip_serializing_if = "Option::is_none")]
652 pub(crate) padding: Option<Padding>,
653 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
654 pub(crate) z: NumberString,
655}
656
657#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
658pub struct Border {
659 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
660 pub(crate) bottom: NumberString,
661 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
662 pub(crate) left: NumberString,
663 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
664 pub(crate) right: NumberString,
665 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
666 pub(crate) top: NumberString,
667}
668#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
669pub struct Padding {
670 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
671 pub(crate) bottom: NumberString,
672 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
673 pub(crate) left: NumberString,
674 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
675 pub(crate) right: NumberString,
676 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
677 pub(crate) top: NumberString,
678}
679
680#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)]
681pub struct Font {
682 #[serde(skip_serializing_if = "String::is_empty", default)]
683 pub(crate) family: String,
684 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
685 pub(crate) lineHeight: NumberString,
686 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
687 pub(crate) size: NumberString,
688 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
689 pub(crate) style: NumberString,
690 #[serde(skip_serializing_if = "NumberString::is_empty", default)]
691 pub(crate) weight: NumberString,
692}
693
694#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)]
695pub struct Segment {
696 #[serde(
697 skip_serializing_if = "FnWithArgs::is_empty",
698 default,
699 skip_deserializing )]
701 pub(crate) borderColor: FnWithArgs<1>,
702 #[serde(
703 skip_serializing_if = "FnWithArgs::is_empty",
704 default,
705 skip_deserializing )]
707 pub(crate) borderDash: FnWithArgs<1>,
708}
709
710impl DatasetTrait for Vec<SinglePointDataset> {
712 fn labels(self) -> Vec<NumberOrDateString> {
713 let mut vec = self
714 .into_iter()
715 .map(|spd| spd.label.into())
716 .collect::<Vec<_>>();
717
718 vec.sort_by(crate::get_order_fn);
719 vec.dedup();
720 vec
721 }
722}
723impl DatasetTrait for Vec<XYDataset> {
724 fn labels(self) -> Vec<NumberOrDateString> {
725 let mut vec = self
726 .into_iter()
727 .filter_map(|xyd| {
728 let data = xyd.data.0.as_array()?;
729 let keys = data
731 .iter()
732 .filter_map(|xy| xy.as_object())
733 .filter_map(|obj| obj.get("x"))
734 .filter_map(|x| {
735 x.as_str()
736 .map(|s| s.to_string())
737 .or(x.as_number().map(|num| num.to_string()))
738 })
739 .map(|x| x.into())
740 .collect::<Vec<NumberOrDateString>>();
741 Some(keys)
742 })
743 .flatten()
744 .collect::<Vec<_>>();
745 vec.sort_by(crate::get_order_fn);
748 vec.dedup();
749 vec
750 }
751}
752impl Annotation for BoxAnnotation {}
754impl Annotation for LineAnnotation {}
755impl From<(NumberOrDateString, NumberString, Option<Value>)> for XYPoint {
757 fn from((x, y, d): (NumberOrDateString, NumberString, Option<Value>)) -> Self {
758 XYPoint {
759 x,
760 y,
761 description: d.unwrap_or_default(),
762 }
763 }
764}
765impl Ord for XYPoint {
767 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
768 self.x.cmp(&other.x)
769 }
770}
771impl PartialOrd for XYPoint {
773 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
774 Some(self.cmp(other))
775 }
776}
777impl Serialize for BoxAnnotationType {
779 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
780 where
781 S: serde::Serializer,
782 {
783 serializer.serialize_str("box")
784 }
785}
786impl Serialize for LineAnnotationType {
788 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
789 where
790 S: serde::Serializer,
791 {
792 serializer.serialize_str("line")
793 }
794}
795impl<'de> Deserialize<'de> for BoxAnnotationType {
797 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
798 where
799 D: serde::Deserializer<'de>,
800 {
801 match String::deserialize(deserializer)?.to_lowercase().as_str() {
802 "box" => Ok(BoxAnnotationType),
803 other => Err(de::Error::custom(format!(
804 "`{other}` is not a valid BoxAnnotationType."
805 ))),
806 }
807 }
808}
809impl<'de> Deserialize<'de> for LineAnnotationType {
810 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
811 where
812 D: serde::Deserializer<'de>,
813 {
814 match String::deserialize(deserializer)?.to_lowercase().as_str() {
815 "line" => Ok(LineAnnotationType),
816 other => Err(de::Error::custom(format!(
817 "`{other}` is not a valid LineAnnotationType."
818 ))),
819 }
820 }
821}
822