Skip to content

Commit 7fc1130

Browse files
authored
Merge pull request #19 from bcdev/yogesh-dashi-vega
Use Vega instead of Plotly
2 parents 45921d4 + 9d33b5d commit 7fc1130

File tree

11 files changed

+1356
-82
lines changed

11 files changed

+1356
-82
lines changed

dashi/package-lock.json

Lines changed: 1249 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dashi/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
"react": "^18.3.1",
5151
"react-dom": "^18.3.1",
5252
"react-plotly.js": "^2.6.0",
53-
"zustand": "^5.0.0"
53+
"zustand": "^5.0.0",
54+
"react-vega": "^7.6.0"
5455
},
5556
"peerDependencies": {
5657
"react": ">=18",

dashi/src/lib/actions/applyPropertyChange.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const componentState: ComponentState = {
1717
type: "Box",
1818
id: "b1",
1919
components: [
20-
{ type: "Plot", id: "p1", figure: null } as PlotState,
20+
{ type: "Plot", id: "p1", chart: null } as PlotState,
2121
{
2222
type: "Box",
2323
id: "b2",
Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Plot from "react-plotly.js";
1+
import { VegaLite } from "react-vega";
22

33
import { type PlotState } from "@/lib/types/state/component";
44
import { type PropertyChangeHandler } from "@/lib/types/model/event";
@@ -10,29 +10,30 @@ export interface DashiPlotProps extends Omit<PlotState, "type"> {
1010
export function DashiPlot({
1111
id,
1212
style,
13-
figure,
13+
chart,
1414
onPropertyChange,
1515
}: DashiPlotProps) {
16-
if (!figure) {
16+
if (!chart) {
1717
return <div id={id} style={style} />;
1818
}
19+
const { datasets, ...spec } = chart;
20+
const handleSignal = (_signalName: string, value: unknown) => {
21+
if (id) {
22+
return onPropertyChange({
23+
componentType: "Plot",
24+
componentId: id,
25+
propertyName: "points",
26+
propertyValue: value,
27+
});
28+
}
29+
};
1930
return (
20-
<Plot
21-
divId={id}
31+
<VegaLite
32+
spec={spec}
33+
data={datasets}
2234
style={style}
23-
data={figure.data}
24-
layout={figure.layout}
25-
config={figure.config}
26-
onClick={(event) => {
27-
if (id) {
28-
onPropertyChange({
29-
componentType: "Plot",
30-
componentId: id,
31-
propertyName: "points",
32-
propertyValue: event.points,
33-
});
34-
}
35-
}}
35+
signalListeners={{ onClick: handleSignal }}
36+
actions={false}
3637
/>
3738
);
3839
}

dashi/src/lib/types/state/component.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type CSSProperties } from "react";
2-
import { type Config, type Layout, type PlotData } from "plotly.js";
2+
import type { VisualizationSpec } from "react-vega";
33

44
export type ComponentType = "Button" | "Checkbox" | "Dropdown" | "Plot" | "Box";
55

@@ -37,11 +37,11 @@ export interface CheckboxState extends ComponentState {
3737

3838
export interface PlotState extends ComponentState {
3939
type: "Plot";
40-
figure: {
41-
data: PlotData[];
42-
layout: Partial<Layout>;
43-
config: Partial<Config>;
44-
} | null;
40+
chart:
41+
| (VisualizationSpec & {
42+
datasets?: Record<string, unknown>; // Add the datasets property
43+
})
44+
| null;
4545
}
4646

4747
export interface BoxState extends ContainerState {

dashipy/dashipy/callback.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ def _parameter_to_dict(parameter: inspect.Parameter) -> dict[str, Any]:
205205
}
206206

207207
_object_types = {
208-
"Figure": "Figure",
209208
"Component": "Component",
209+
"Chart": "Chart"
210210
}
211211

212212

dashipy/dashipy/components/plot.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
from dataclasses import dataclass
22
from typing import Any
33

4-
import plotly.graph_objects as go
4+
import altair as alt
55

66
from dashipy import Component
77

88

99
@dataclass(frozen=True)
1010
class Plot(Component):
11-
figure: go.Figure | None = None
11+
chart: alt.Chart | None = None
1212

1313
def to_dict(self) -> dict[str, Any]:
1414
d = super().to_dict()
15-
if self.figure is not None:
16-
d.update(figure=self.figure.to_dict())
15+
if self.chart is not None:
16+
d.update(chart=self.chart.to_dict())
1717
else:
18-
d.update(figure=None)
18+
d.update(chart=None)
1919
return d

dashipy/dashipy/demo/context.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
from typing import Union
2+
import pandas as pd
3+
4+
15
class Context:
26
def __init__(self):
3-
self.datasets: dict[int, list[int]] = {
4-
0: [10, 20, 30],
5-
1: [20, 30, 10],
6-
2: [30, 10, 20],
7+
self.datasets= {
8+
0: pd.DataFrame({
9+
'a': ['A', 'B', 'C', 'D', 'E'],
10+
'b': [28, 55, 43, 91, 81]
11+
}),
12+
1: pd.DataFrame({
13+
'a': ['V', 'W', 'X', 'Y', 'Z'],
14+
'b': [99, 1, 7, 43, 49]
15+
})
716
}

dashipy/environment.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ name: dashi
22
channels:
33
- conda-forge
44
dependencies:
5-
- python
5+
- python >=3.12,<3.13
66
# Dependencies
77
- pandas
8-
- plotly
8+
- altair
99
- pyaml
1010
- tornado
1111
# Dev Dependencies

dashipy/my_extension/my_panel_1.py

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import plotly.graph_objects as go
2-
from plotly.graph_objs import Layout
1+
import altair as alt
32

43
from dashipy import (Component, Input, Output)
54
from dashipy.components import (Plot, Box, Dropdown)
@@ -14,7 +13,7 @@
1413
def render_panel(ctx: Context) -> Component:
1514
selected_dataset: int = 0
1615
plot = Plot(
17-
id="plot", figure=make_figure(ctx, selected_dataset), style={"flexGrow": 1}
16+
id="plot", chart=make_figure(ctx, selected_dataset), style={"flexGrow": 1}
1817
)
1918
dropdown = Dropdown(
2019
id="selected_dataset",
@@ -46,16 +45,33 @@ def render_panel(ctx: Context) -> Component:
4645

4746
@panel.callback(
4847
Input("selected_dataset"),
49-
Output("plot", "figure"),
48+
Output("plot", "chart"),
5049
)
51-
def make_figure(ctx: Context, selected_dataset: int = 0) -> go.Figure:
50+
def make_figure(ctx: Context, selected_dataset: int = 0) -> alt.Chart:
5251
dataset = ctx.datasets[selected_dataset]
53-
fig = go.Figure(
54-
layout=Layout(
55-
title=f"DS #{selected_dataset + 1}",
56-
margin=dict(t=40, r=4, b=4, l=4),
57-
autosize=True,
58-
)
59-
)
60-
fig.add_trace(go.Bar(x=["A", "B", "C"], y=dataset))
61-
return fig
52+
53+
# Create a slider
54+
corner_slider = alt.binding_range(min=0, max=50, step=1)
55+
# Create a parameter and bind that to the slider
56+
corner_var = alt.param(bind=corner_slider, value=0, name="cornerRadius")
57+
# Create another parameter to handle the click events and send the data as
58+
# specified in the fields
59+
click_param = alt.selection_point(on="click", name="onClick",
60+
fields=["a", "b"])
61+
# Create a chart type using mark_* where * could be any kind of chart
62+
# supported by Vega. We can add properties and parameters as shown below.
63+
chart = alt.Chart(dataset).mark_bar(cornerRadius=corner_var).encode(
64+
x=alt.X('a:N', title='a'),
65+
y=alt.Y('b:Q', title='b'),
66+
tooltip=[
67+
alt.Tooltip('a:N'),
68+
alt.Tooltip('b:Q'),
69+
],
70+
color='b:Q',
71+
).properties(
72+
width=300,
73+
height=300,
74+
title="Vega charts"
75+
).add_params(corner_var, click_param)
76+
77+
return chart

0 commit comments

Comments
 (0)