From 5b433b8f5b9b75bc251ae99fc8b2f1c0b6332342 Mon Sep 17 00:00:00 2001 From: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:41:57 +0200 Subject: [PATCH 01/11] update changelog Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b5a0819..a64ee54b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.8.5] - 2024-xx-xx +## [0.9.0] - 2024-xx-xx ### Added - [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. - [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. +- [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. +- [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter. +- [[#159](https://github.com/plotly/plotly.rs/pull/159)] Make `heat_map` module public to expose `Smoothing enum`. - [[#153](https://github.com/plotly/plotly.rs/pull/153)] Added `LayoutScene`. ## [0.8.4] - 2023-07-09 From f3ffab1f1b70bb39870ad639c6b84601160ee739 Mon Sep 17 00:00:00 2001 From: baiguoname Date: Sat, 23 Sep 2023 18:08:19 +0800 Subject: [PATCH 02/11] Add `Table` trace --- examples/basic_charts/src/main.rs | 15 +++++++++++++++ plotly/src/common/mod.rs | 1 + plotly/src/lib.rs | 2 +- plotly/src/traces/mod.rs | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs index 65518e2f..106036c9 100644 --- a/examples/basic_charts/src/main.rs +++ b/examples/basic_charts/src/main.rs @@ -10,6 +10,7 @@ use plotly::{ layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder}, sankey::{Line as SankeyLine, Link, Node}, Bar, Plot, Sankey, Scatter, ScatterPolar, + Table, }; use rand_distr::{Distribution, Normal, Uniform}; @@ -604,8 +605,22 @@ fn basic_sankey_diagram() { plot.show(); } +fn table_chart() { + let trace = Table::new( + vec![String::from("col1"), String::from("col2")], + vec![ + vec![1, 2], + vec![2, 3], + ] + ); + let mut plot = Plot::new(); + plot.add_trace(table_trace); + plot.show(); +} + fn main() { // Uncomment any of these lines to display the example. + table_chart(); // Scatter Plots // simple_scatter_plot(); diff --git a/plotly/src/common/mod.rs b/plotly/src/common/mod.rs index d6cc3082..4777afb5 100644 --- a/plotly/src/common/mod.rs +++ b/plotly/src/common/mod.rs @@ -202,6 +202,7 @@ pub enum PlotType { Sankey, Surface, DensityMapbox, + Table, } #[derive(Serialize, Clone, Debug)] diff --git a/plotly/src/lib.rs b/plotly/src/lib.rs index 72dbbc34..c5337680 100644 --- a/plotly/src/lib.rs +++ b/plotly/src/lib.rs @@ -36,7 +36,7 @@ pub use traces::{ // Bring the different trace types into the top-level scope pub use traces::{ Bar, BoxPlot, Candlestick, Contour, DensityMapbox, HeatMap, Histogram, Image, Mesh3D, Ohlc, - Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, + Sankey, Scatter, Scatter3D, ScatterMapbox, ScatterPolar, Surface, Table, }; pub trait Restyle: serde::Serialize {} diff --git a/plotly/src/traces/mod.rs b/plotly/src/traces/mod.rs index 27f55f89..f12305c3 100644 --- a/plotly/src/traces/mod.rs +++ b/plotly/src/traces/mod.rs @@ -16,6 +16,7 @@ mod scatter3d; pub mod scatter_mapbox; mod scatter_polar; pub mod surface; +pub mod table; pub use bar::Bar; pub use box_plot::BoxPlot; @@ -32,5 +33,6 @@ pub use scatter3d::Scatter3D; pub use scatter_mapbox::ScatterMapbox; pub use scatter_polar::ScatterPolar; pub use surface::Surface; +pub use table::Table; pub use self::image::Image; From 0effd87f3e1a93b24597e1eca82de1307d86c2bd Mon Sep 17 00:00:00 2001 From: baiguoname Date: Sat, 23 Sep 2023 18:12:39 +0800 Subject: [PATCH 03/11] First commit --- plotly/src/traces/table.rs | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 plotly/src/traces/table.rs diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs new file mode 100644 index 00000000..d953b770 --- /dev/null +++ b/plotly/src/traces/table.rs @@ -0,0 +1,155 @@ +//! Table trace + +use plotly_derive::FieldSetter; +use serde::Serialize; + +use crate::{ + color::Color, + common::{Font, Line, PlotType, Visible}, + Trace, +}; + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +#[field_setter(box_self, kind = "trace")] +pub struct Table +where + T: Serialize + Clone + 'static, + N: Serialize + Clone + 'static, +{ + #[field_setter(default = "PlotType::Table")] + r#type: PlotType, + /// Sets the trace name. The trace name appear as the legend item and on + /// hover. + name: Option, + #[serde(rename = "columnorder")] + /// Determines whether or not this trace is visible. If + /// `Visible::LegendOnly`, the trace is not drawn, but can appear as a + /// legend item (provided that the legend itself is visible). + visible: Option, + ///Specifies the rendered order of the data columns; for example, a value `2` at position `0`, + ///means that column index `0` in the data will be rendered as the, + ///third column, as columns have an index base of zero. + column_order: Option>, + #[serde(rename = "columnwidth")] + ///The width of columns expressed as a ratio. Columns fill the available width, + ///in proportion of their specified column widths. + column_width: Option, + ///Header cell values. `values[m][n]` represents the value of the `n`th point in column `m`,, + ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, + ///will be truncated). Each value must be a finite number or a string. + header: Option>, + ///Cell values. `values[m][n]` represents the value of the `n`th point in column `m`,, + ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, + ///will be truncated). Each value must be a finite number or a string. + cells: Option>, +} + +impl Table +where + T: Serialize + Clone + Default + 'static, + N: Serialize + Clone + Default + 'static, +{ + pub fn new(header: Vec, cells: Vec>) -> Box { + Box::new(Table { + header: Header::new().values(header).into(), + cells: Cells::new().values(cells).into(), + ..Default::default() + }) + } +} + +impl Trace for Table +where + T: Serialize + Clone + 'static, + N: Serialize + Clone + 'static, +{ + fn to_json(&self) -> String { + serde_json::to_string(self).unwrap() + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +pub struct Cells { + ///Cell values. `values[m][n]` represents the value of the `n`th point in column `m`, + ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, + ///will be truncated). Each value must be a finite number or a string + values: Option>>, + ///Prefix for cell values. + prefix: Option, + ///Suffix for cell values. + suffix: Option, + height: Option, + align: Option, + line: Option, + ///Sets the cell fill color. It accepts either a specific color, + ///or an array of colors or a 2D array of colors + fill: Option>, + font: Option, +} + +impl Cells +where + N: Serialize + Clone + Default + 'static, +{ + pub fn new() -> Self { + Default::default() + } +} + +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +pub struct Header { + ///Header cell values. `values[m][n]` represents the value of the `n`th point in column `m`, + ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, + ///will be truncated). Each value must be a finite number or a string. + values: Option>, + ///Prefix for cell values. + prefix: Option, + ///Suffix for cell values. + suffix: Option, + height: Option, + align: Option, + line: Option, + ///Sets the cell fill color. It accepts either a specific color, + ///or an array of colors or a 2D array of colors + fill: Option>, + font: Option, +} + +impl Header +where + T: Serialize + Clone + Default + 'static, +{ + pub fn new() -> Self { + Default::default() + } +} + +#[cfg(test)] +mod tests { + use serde_json::{json, to_value}; + + use super::*; + + #[test] + fn test_serialize_table() { + let trace = Table::new( + vec![String::from("col1"), String::from("col2")], + vec![vec![1, 2], vec![2, 3]], + ); + + let expected = json!({ + "type": "table", + "cells": { + "values": [[1, 2], [2, 3]], + }, + "header": { + "values": ["col1", "col2"], + }, + }); + + assert_eq!(to_value(trace).unwrap(), expected); + } +} From ef994778bb02951c39493bb4f9831331803a7dd3 Mon Sep 17 00:00:00 2001 From: baiguoname Date: Sat, 23 Sep 2023 19:41:15 +0800 Subject: [PATCH 04/11] add --- plotly/src/traces/table.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs index d953b770..8b6a8a1e 100644 --- a/plotly/src/traces/table.rs +++ b/plotly/src/traces/table.rs @@ -51,6 +51,7 @@ where N: Serialize + Clone + Default + 'static, { pub fn new(header: Vec, cells: Vec>) -> Box { + Box::new(Table { header: Header::new().values(header).into(), cells: Cells::new().values(cells).into(), From 49cbe5425d38a2a2832d5965f6c2654a4ce17c29 Mon Sep 17 00:00:00 2001 From: baiguoname Date: Sat, 23 Sep 2023 20:25:58 +0800 Subject: [PATCH 05/11] reductant_code --- examples/basic_charts/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs index 106036c9..1acca655 100644 --- a/examples/basic_charts/src/main.rs +++ b/examples/basic_charts/src/main.rs @@ -620,7 +620,6 @@ fn table_chart() { fn main() { // Uncomment any of these lines to display the example. - table_chart(); // Scatter Plots // simple_scatter_plot(); @@ -644,6 +643,7 @@ fn main() { // basic_bar_chart(); // grouped_bar_chart(); // stacked_bar_chart(); + // table_chart(); // Sankey Diagrams // basic_sankey_diagram(); From e7a7b5981c14d1144e86f496104f86c0d0873473 Mon Sep 17 00:00:00 2001 From: baiguoname Date: Sun, 24 Sep 2023 09:42:00 +0800 Subject: [PATCH 06/11] Fill_Color --- plotly/src/traces/table.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs index 8b6a8a1e..ac9d6bfb 100644 --- a/plotly/src/traces/table.rs +++ b/plotly/src/traces/table.rs @@ -86,7 +86,7 @@ pub struct Cells { line: Option, ///Sets the cell fill color. It accepts either a specific color, ///or an array of colors or a 2D array of colors - fill: Option>, + fill: Option, font: Option, } @@ -115,7 +115,7 @@ pub struct Header { line: Option, ///Sets the cell fill color. It accepts either a specific color, ///or an array of colors or a 2D array of colors - fill: Option>, + fill: Option, font: Option, } @@ -128,6 +128,18 @@ where } } +#[serde_with::skip_serializing_none] +#[derive(Serialize, Clone, Debug, FieldSetter)] +pub struct Fill { + color: Option> +} + +impl Fill { + pub fn new() -> Self { + Default::default() + } +} + #[cfg(test)] mod tests { use serde_json::{json, to_value}; @@ -136,10 +148,9 @@ mod tests { #[test] fn test_serialize_table() { - let trace = Table::new( - vec![String::from("col1"), String::from("col2")], - vec![vec![1, 2], vec![2, 3]], - ); + let columns = vec![String::from("col1"), String::from("col2")]; + let values = vec![vec![1, 2], vec![2, 3]]; + let trace = Table::new(columns.clone(), values); let expected = json!({ "type": "table", From 0d9265522544f2fbe3fe0db6ed9c74fdd445d671 Mon Sep 17 00:00:00 2001 From: baiguoname Date: Sun, 24 Sep 2023 09:42:58 +0800 Subject: [PATCH 07/11] Fill --- plotly/src/traces/table.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs index ac9d6bfb..31c0d641 100644 --- a/plotly/src/traces/table.rs +++ b/plotly/src/traces/table.rs @@ -51,7 +51,6 @@ where N: Serialize + Clone + Default + 'static, { pub fn new(header: Vec, cells: Vec>) -> Box { - Box::new(Table { header: Header::new().values(header).into(), cells: Cells::new().values(cells).into(), @@ -131,7 +130,7 @@ where #[serde_with::skip_serializing_none] #[derive(Serialize, Clone, Debug, FieldSetter)] pub struct Fill { - color: Option> + color: Option>, } impl Fill { From aaabcc234a0ace4d8017bfd1190667150311b05f Mon Sep 17 00:00:00 2001 From: kylemello Date: Mon, 1 Jan 2024 14:31:15 -0500 Subject: [PATCH 08/11] Tables now take a header and cells struct --- plotly/src/traces/table.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs index 31c0d641..713e2fa9 100644 --- a/plotly/src/traces/table.rs +++ b/plotly/src/traces/table.rs @@ -50,10 +50,10 @@ where T: Serialize + Clone + Default + 'static, N: Serialize + Clone + Default + 'static, { - pub fn new(header: Vec, cells: Vec>) -> Box { + pub fn new(header: Header, cells: Cells) -> Box { Box::new(Table { - header: Header::new().values(header).into(), - cells: Cells::new().values(cells).into(), + header: Some(header), + cells: Some(cells), ..Default::default() }) } @@ -93,8 +93,11 @@ impl Cells where N: Serialize + Clone + Default + 'static, { - pub fn new() -> Self { - Default::default() + pub fn new(values: Vec>) -> Self { + Cells { + values: Some(values), + ..Default::default() + } } } @@ -122,8 +125,11 @@ impl Header where T: Serialize + Clone + Default + 'static, { - pub fn new() -> Self { - Default::default() + pub fn new(values: Vec) -> Self { + Header { + values: Some(values), + ..Default::default() + } } } @@ -147,9 +153,9 @@ mod tests { #[test] fn test_serialize_table() { - let columns = vec![String::from("col1"), String::from("col2")]; - let values = vec![vec![1, 2], vec![2, 3]]; - let trace = Table::new(columns.clone(), values); + let columns = Header::new(vec![String::from("col1"), String::from("col2")]); + let values = Cells::new(vec![vec![1, 2], vec![2, 3]]); + let trace = Table::new(columns, values); let expected = json!({ "type": "table", From df85deaaca54ebd07fffcb2f02f533c63f1a179d Mon Sep 17 00:00:00 2001 From: jack Date: Tue, 18 Jun 2024 16:43:10 +0800 Subject: [PATCH 09/11] fix some CI issues --- examples/basic_charts/src/main.rs | 10 +++----- plotly/src/traces/table.rs | 39 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs index 1acca655..527eb85c 100644 --- a/examples/basic_charts/src/main.rs +++ b/examples/basic_charts/src/main.rs @@ -9,8 +9,7 @@ use plotly::{ }, layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder}, sankey::{Line as SankeyLine, Link, Node}, - Bar, Plot, Sankey, Scatter, ScatterPolar, - Table, + Bar, Plot, Sankey, Scatter, ScatterPolar, Table, }; use rand_distr::{Distribution, Normal, Uniform}; @@ -608,13 +607,10 @@ fn basic_sankey_diagram() { fn table_chart() { let trace = Table::new( vec![String::from("col1"), String::from("col2")], - vec![ - vec![1, 2], - vec![2, 3], - ] + vec![vec![1, 2], vec![2, 3]], ); let mut plot = Plot::new(); - plot.add_trace(table_trace); + plot.add_trace(trace); plot.show(); } diff --git a/plotly/src/traces/table.rs b/plotly/src/traces/table.rs index 713e2fa9..58545a57 100644 --- a/plotly/src/traces/table.rs +++ b/plotly/src/traces/table.rs @@ -27,21 +27,24 @@ where /// `Visible::LegendOnly`, the trace is not drawn, but can appear as a /// legend item (provided that the legend itself is visible). visible: Option, - ///Specifies the rendered order of the data columns; for example, a value `2` at position `0`, - ///means that column index `0` in the data will be rendered as the, - ///third column, as columns have an index base of zero. + ///Specifies the rendered order of the data columns; for example, a value + /// `2` at position `0`, means that column index `0` in the data will be + /// rendered as the, third column, as columns have an index base of + /// zero. column_order: Option>, #[serde(rename = "columnwidth")] - ///The width of columns expressed as a ratio. Columns fill the available width, - ///in proportion of their specified column widths. + ///The width of columns expressed as a ratio. Columns fill the available + /// width, in proportion of their specified column widths. column_width: Option, - ///Header cell values. `values[m][n]` represents the value of the `n`th point in column `m`,, - ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, - ///will be truncated). Each value must be a finite number or a string. + ///Header cell values. `values[m][n]` represents the value of the `n`th + /// point in column `m`,, therefore the `values[m]` vector length for + /// all columns must be the same (longer vectors, will be truncated). + /// Each value must be a finite number or a string. header: Option>, - ///Cell values. `values[m][n]` represents the value of the `n`th point in column `m`,, - ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, - ///will be truncated). Each value must be a finite number or a string. + ///Cell values. `values[m][n]` represents the value of the `n`th point in + /// column `m`,, therefore the `values[m]` vector length for all columns + /// must be the same (longer vectors, will be truncated). Each value + /// must be a finite number or a string. cells: Option>, } @@ -72,9 +75,10 @@ where #[serde_with::skip_serializing_none] #[derive(Serialize, Clone, Debug, FieldSetter)] pub struct Cells { - ///Cell values. `values[m][n]` represents the value of the `n`th point in column `m`, - ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, - ///will be truncated). Each value must be a finite number or a string + ///Cell values. `values[m][n]` represents the value of the `n`th point in + /// column `m`, therefore the `values[m]` vector length for all columns + /// must be the same (longer vectors, will be truncated). Each value + /// must be a finite number or a string values: Option>>, ///Prefix for cell values. prefix: Option, @@ -104,9 +108,10 @@ where #[serde_with::skip_serializing_none] #[derive(Serialize, Clone, Debug, FieldSetter)] pub struct Header { - ///Header cell values. `values[m][n]` represents the value of the `n`th point in column `m`, - ///therefore the `values[m]` vector length for all columns must be the same (longer vectors, - ///will be truncated). Each value must be a finite number or a string. + ///Header cell values. `values[m][n]` represents the value of the `n`th + /// point in column `m`, therefore the `values[m]` vector length for all + /// columns must be the same (longer vectors, will be truncated). Each + /// value must be a finite number or a string. values: Option>, ///Prefix for cell values. prefix: Option, From c9930a017ada419d1d6566137b1d45f10626ecb2 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 19 Jun 2024 09:26:57 +0800 Subject: [PATCH 10/11] fix table example --- examples/basic_charts/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/basic_charts/src/main.rs b/examples/basic_charts/src/main.rs index 527eb85c..9408c755 100644 --- a/examples/basic_charts/src/main.rs +++ b/examples/basic_charts/src/main.rs @@ -9,6 +9,7 @@ use plotly::{ }, layout::{Axis, BarMode, Layout, Legend, TicksDirection, TraceOrder}, sankey::{Line as SankeyLine, Link, Node}, + traces::table::{Cells, Header}, Bar, Plot, Sankey, Scatter, ScatterPolar, Table, }; use rand_distr::{Distribution, Normal, Uniform}; @@ -606,8 +607,8 @@ fn basic_sankey_diagram() { fn table_chart() { let trace = Table::new( - vec![String::from("col1"), String::from("col2")], - vec![vec![1, 2], vec![2, 3]], + Header::new(vec![String::from("col1"), String::from("col2")]), + Cells::new(vec![vec![1, 2], vec![2, 3]]), ); let mut plot = Plot::new(); plot.add_trace(trace); From b9e621115497ec22235ba0a61507f81c2ad75405 Mon Sep 17 00:00:00 2001 From: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> Date: Wed, 19 Jun 2024 09:41:37 +0200 Subject: [PATCH 11/11] update changelog Signed-off-by: Andrei Gherghescu <8067229+andrei-ng@users.noreply.github.com> --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a64ee54b..eab1cfc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [0.9.0] - 2024-xx-xx ### Added +- [[#207](https://github.com/plotly/plotly,rs/pull/207)] Add `Table` trace. - [[#181](https://github.com/plotly/plotly,rs/pull/181)] Fix compilation error when mixing the crate with `askama/with-axum` by adding `with-axum` feature. - [[#180](https://github.com/plotly/plotly.rs/pull/180)] Add setter for `Mapbox::domain`. +- [[#178](https://github.com/plotly/plotly.rs/pull/178)] Fix setter for `Axis::matches` to take string arg. - [[#166](https://github.com/plotly/plotly.rs/pull/166)] Added subplot example with multiple titles. - [[#163](https://github.com/plotly/plotly.rs/pull/163)] Added `DensityMapbox`. - [[#161](https://github.com/plotly/plotly.rs/pull/161)] Added `Axis` `scaleanchor` settter.