generated from silverbulletmd/silverbullet-plug-template
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathattributeChart.ts
103 lines (95 loc) · 3.12 KB
/
attributeChart.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
import { YAML, system, space } from "@silverbulletmd/silverbullet/syscalls";
import { parseQuery } from "@silverbulletmd/silverbullet/lib/parse_query";
import { CodeWidgetContent } from "@silverbulletmd/silverbullet/types";
type Attribute = {
name: string;
type?: string;
label?: string;
color?: string;
};
type ChartConfig = {
query: string;
attributes: Attribute[];
options?: object;
};
export async function widget(
bodyText: string,
pageName: string
): Promise<CodeWidgetContent> {
const config = await system.getSpaceConfig();
const pageObject = await space.readPage(pageName);
try {
const chartConfig: ChartConfig = await YAML.parse(bodyText);
const query = await parseQuery(chartConfig.query);
const attributes = chartConfig.attributes || [];
const options = chartConfig.options || {};
const results = await system.invokeFunction(
"query.renderQuery",
query,
{
page: pageObject,
config,
},
);
return {
html: `
<style>
html[data-theme=dark] {
color-scheme: dark;
--root-background-color: #111;
--root-color: #fff;
--top-background-color: #262626;
}
html {
--root-background-color: #fff;
--root-color: inherit;
--top-background-color: #e1e1e1;
--ui-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"
}
body{
margin:0;
background-color:var(--root-background-color);
color:var(--root-color);
font-family: var(--ui-font);
}
</style>
<canvas id="myChart"></canvas>`,
script: `
loadJsByUrl("https://cdn.jsdelivr.net/npm/chart.js").then(() => {
const chartData = ${JSON.stringify(createChartData(results, attributes))};
const ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
data: chartData,
options: ${JSON.stringify(options)}
})
});
`
};
} catch (e: any) {
return { markdown: `**Error:** ${e.message}` };
}
}
export function createChartData(results: any, attributes: Attribute[] = []) {
const labels = results.map((d: any) => d.name.replace(/^.*\//, ""));
const datasets = [];
const nestedAttribute = (obj: any, path: string) => {
let value = path.split('.').reduce((acc, key) => (acc ? acc[key] : undefined), obj);
// If not found, look under the "attribute" key for backward compatibility
if (value === undefined && obj?.attribute) {
value = obj.attribute[path];
}
return value;
};
for (const attribute of attributes) {
if (!attribute.name) {
continue;
}
datasets.push({
type: attribute.type || 'line',
label: attribute.label || attribute.name,
data: results.map((d: any) => d && nestedAttribute(d, attribute.name)),
...(attribute.color && { backgroundColor: attribute.color, borderColor: attribute.color }),
});
}
return { labels, datasets };
}