/
vega.ts
110 lines (97 loc) · 3.01 KB
/
vega.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import * as p from "@bokehjs/core/properties"
import {isArray} from "@bokehjs/core/util/types"
import {HTMLBox, HTMLBoxView} from "@bokehjs/models/layouts/html_box"
export class VegaPlotView extends HTMLBoxView {
model: VegaPlot
_connected: string[]
connect_signals(): void {
super.connect_signals()
const {data, show_actions, theme} = this.model.properties
this.on_change([data, show_actions, theme], () => {
this._plot()
})
this.connect(this.model.properties.data_sources.change, () => this._connect_sources())
this._connected = []
this._connect_sources()
}
_connect_sources(): void {
for (const ds in this.model.data_sources) {
const cds = this.model.data_sources[ds]
if (this._connected.indexOf(ds) < 0) {
this.connect(cds.properties.data.change, this._plot)
this._connected.push(ds)
}
}
}
_fetch_datasets() {
const datasets: any = {}
for (const ds in this.model.data_sources) {
const cds = this.model.data_sources[ds];
const data: any = []
const columns = cds.columns()
for (let i = 0; i < cds.get_length(); i++) {
const item: any = {}
for (const column of columns) {
item[column] = cds.data[column][i]
}
data.push(item)
}
datasets[ds] = data;
}
return datasets
}
render(): void {
super.render()
this._plot()
}
_plot(): void {
const data = this.model.data
if ((data == null) || !(window as any).vegaEmbed)
return
if (this.model.data_sources && (Object.keys(this.model.data_sources).length > 0)) {
const datasets = this._fetch_datasets()
if ('data' in datasets) {
data.data['values'] = datasets['data']
delete datasets['data']
}
if (data.data != null) {
const data_objs = isArray(data.data) ? data.data : [data.data]
for (const d of data_objs) {
if (d.name in datasets) {
d['values'] = datasets[d.name]
delete datasets[d.name]
}
}
}
this.model.data['datasets'] = datasets
}
const config: any = {actions: this.model.show_actions, theme: this.model.theme};
(window as any).vegaEmbed(this.el, this.model.data, config)
}
}
export namespace VegaPlot {
export type Attrs = p.AttrsOf<Props>
export type Props = HTMLBox.Props & {
data: p.Property<any>
data_sources: p.Property<any>
show_actions: p.Property<boolean>
theme: p.Property<string | null>
}
}
export interface VegaPlot extends VegaPlot.Attrs {}
export class VegaPlot extends HTMLBox {
properties: VegaPlot.Props
constructor(attrs?: Partial<VegaPlot.Attrs>) {
super(attrs)
}
static __module__ = "panel.models.vega"
static init_VegaPlot(): void {
this.prototype.default_view = VegaPlotView
this.define<VegaPlot.Props>(({Any, Boolean, String}) => ({
data: [ Any, {} ],
data_sources: [ Any, {} ],
show_actions: [ Boolean, false ],
theme: [ String, ]
}))
}
}