1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4use super::source::CacheConfig;
5use super::style::{FontsSpec, GridSpec, LegendSpec};
6use super::transform::TransformSpec;
7
8#[derive(Debug, Clone, Deserialize, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub struct ChartSpec {
13 pub version: u32,
14 pub title: Option<String>,
15 pub data: DataRef,
16 pub transform: Option<TransformSpec>,
17 pub visualize: VisualizeSpec,
18 pub layout: Option<LayoutSpec>,
19 pub style: Option<StyleRefOrInline>,
20 pub params: Option<Vec<super::params::ParamDef>>,
21}
22
23#[derive(Debug, Clone, Deserialize, Serialize)]
39#[serde(untagged)]
40pub enum DataRef {
41 Named(String),
42 Inline(InlineData),
43 NamedMap(IndexMap<String, InlineData>),
44}
45
46#[derive(Debug, Clone, Deserialize, Serialize)]
57#[serde(rename_all = "camelCase", deny_unknown_fields)]
58pub struct InlineData {
59 pub provider: Option<String>,
60 pub rows: Option<Vec<serde_json::Value>>,
61 pub url: Option<String>,
62 pub endpoint: Option<String>,
63 pub cache: Option<CacheConfig>,
64 pub datasource: Option<String>,
66 pub query: Option<String>,
68}
69
70#[derive(Debug, Clone, Deserialize, Serialize)]
73#[serde(untagged)]
74pub enum StyleRefOrInline {
75 Named(String),
76 Inline(Box<ChartStyleSpec>),
77}
78
79#[derive(Debug, Clone, Deserialize, Serialize)]
82#[serde(rename_all = "camelCase")]
83pub struct VisualizeSpec {
84 #[serde(rename = "type")]
85 pub chart_type: String,
86 pub mode: Option<ChartMode>,
87 pub orientation: Option<Orientation>,
88 pub columns: Option<FieldRef>,
89 pub rows: Option<FieldRef>,
90 pub marks: Option<MarksSpec>,
91 pub axes: Option<AxesSpec>,
92 pub annotations: Option<Vec<AnnotationSpec>>,
93 pub style: Option<ChartStyleSpec>,
94 pub value: Option<String>,
96 pub label: Option<String>,
97 pub format: Option<String>,
98 pub compare_with: Option<String>,
99 pub invert_trend: Option<bool>,
100 pub data_labels: Option<DataLabelsSpec>,
101}
102
103#[derive(Debug, Clone, Deserialize, Serialize)]
106#[serde(rename_all = "lowercase")]
107pub enum ChartMode {
108 Stacked,
109 Grouped,
110 Normalized,
111}
112
113#[derive(Debug, Clone, Deserialize, Serialize)]
116#[serde(rename_all = "lowercase")]
117pub enum Orientation {
118 Vertical,
119 Horizontal,
120}
121
122#[derive(Debug, Clone, Deserialize, Serialize)]
125#[serde(untagged)]
126pub enum FieldRef {
127 Simple(String),
128 Detailed(Box<FieldSpec>),
129 Multiple(Vec<FieldRefItem>),
130}
131
132#[derive(Debug, Clone, Deserialize, Serialize)]
134#[serde(untagged)]
135pub enum FieldRefItem {
136 Simple(String),
137 Detailed(Box<FieldSpec>),
138}
139
140#[derive(Debug, Clone, Deserialize, Serialize)]
147#[serde(rename_all = "camelCase")]
148pub struct FieldSpec {
149 pub field: Option<String>,
150 pub mark: Option<String>,
151 pub axis: Option<String>,
152 pub label: Option<String>,
153 pub color: Option<String>,
154 pub format: Option<String>,
155 pub data_labels: Option<DataLabelsSpec>,
156 pub line_style: Option<String>,
158 pub upper: Option<String>,
160 pub lower: Option<String>,
162 pub opacity: Option<f64>,
164}
165
166
167#[derive(Debug, Clone, Deserialize, Serialize)]
170#[serde(rename_all = "camelCase")]
171pub struct DataLabelsSpec {
172 pub show: Option<bool>,
173 pub position: Option<String>,
174 pub format: Option<String>,
175 pub color: Option<String>,
176 pub font_size: Option<f64>,
177}
178
179#[derive(Debug, Clone, Deserialize, Serialize)]
182#[serde(rename_all = "camelCase")]
183pub struct MarksSpec {
184 pub color: Option<MarkEncoding>,
185 pub size: Option<MarkEncoding>,
186 pub shape: Option<MarkEncoding>,
187 pub text: Option<MarkEncoding>,
188}
189
190#[derive(Debug, Clone, Deserialize, Serialize)]
191#[serde(untagged)]
192pub enum MarkEncoding {
193 Simple(String),
194 Detailed(MarkEncodingSpec),
195}
196
197#[derive(Debug, Clone, Deserialize, Serialize)]
198#[serde(rename_all = "camelCase")]
199pub struct MarkEncodingSpec {
200 pub field: String,
201 pub label: Option<String>,
202 pub format: Option<String>,
203}
204
205#[derive(Debug, Clone, Deserialize, Serialize)]
208#[serde(rename_all = "camelCase")]
209pub struct AxesSpec {
210 #[serde(alias = "columns", alias = "bottom")]
211 pub x: Option<AxisSpec>,
212 #[serde(alias = "rows")]
213 pub left: Option<AxisSpec>,
214 pub right: Option<AxisSpec>,
215}
216
217#[derive(Debug, Clone, Deserialize, Serialize)]
218#[serde(rename_all = "camelCase")]
219pub struct AxisSpec {
220 pub label: Option<String>,
221 pub format: Option<String>,
222 pub min: Option<f64>,
223 pub max: Option<f64>,
224 pub nice: Option<bool>,
225}
226
227#[derive(Debug, Clone, Deserialize, Serialize)]
230#[serde(rename_all = "camelCase")]
231pub struct AnnotationSpec {
232 #[serde(rename = "type")]
233 pub annotation_type: String,
234 pub axis: Option<String>,
235 pub value: Option<serde_json::Value>,
236 pub from: Option<serde_json::Value>,
237 pub to: Option<serde_json::Value>,
238 pub orientation: Option<String>,
239 pub label: Option<String>,
240 pub label_position: Option<String>,
241 pub color: Option<String>,
242 pub stroke_width: Option<f64>,
243 pub dash_array: Option<String>,
244 pub opacity: Option<f64>,
245 pub stroke_color: Option<String>,
246 pub style: Option<String>,
248}
249
250#[derive(Debug, Clone, Deserialize, Serialize)]
253#[serde(rename_all = "camelCase")]
254pub struct ChartStyleSpec {
255 pub height: Option<f64>,
256 pub width: Option<f64>,
257 pub colors: Option<Vec<String>>,
266 pub grid: Option<GridSpec>,
267 pub show_dots: Option<bool>,
268 pub stroke_width: Option<f64>,
269 pub curve_type: Option<String>,
270 pub fill_opacity: Option<f64>,
271 pub fonts: Option<FontsSpec>,
272 pub legend: Option<LegendSpec>,
273 pub page_size: Option<usize>,
275}
276
277#[derive(Debug, Clone, Deserialize, Serialize)]
280#[serde(rename_all = "camelCase")]
281pub struct LayoutSpec {
282 pub col_span: Option<u32>,
283}