feat(frontend): add plotly support

This commit is contained in:
Ruben Fiszel
2023-01-31 08:04:38 +01:00
parent dfae34d9b4
commit a4f8f9e1cf
8 changed files with 122 additions and 3 deletions
@@ -0,0 +1,52 @@
<script lang="ts">
import { Loader2 } from 'lucide-svelte'
import { onMount } from 'svelte'
import type { AppInput } from '../../inputType'
import InputValue from '../helpers/InputValue.svelte'
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
export let id: string
export let componentInput: AppInput | undefined
export let configuration: Record<string, AppInput>
export const staticOutputs: string[] = ['result', 'loading']
let result: object | undefined = undefined
let divEl: HTMLDivElement | null = null
let Plotly
onMount(async () => {
if (divEl) {
//@ts-ignore
await import('https://cdn.plot.ly/plotly-2.18.0.min.js')
Plotly = window['Plotly']
}
})
let h: number | undefined = undefined
let w: number | undefined = undefined
$: Plotly &&
result &&
divEl &&
h &&
w &&
Plotly.newPlot(
divEl,
[result],
{ width: w, height: h, margin: { l: 40, r: 40, b: 40, t: 40, pad: 4 } },
{ responsive: true, displayModeBar: false }
)
</script>
<div class="w-full h-full" bind:clientHeight={h} bind:clientWidth={w}>
<RunnableWrapper flexWrap bind:componentInput {id} bind:result>
{#if !Plotly}
<div class="p-2">
<Loader2 class="animate-spin" />
</div>
{/if}
<div on:pointerdown bind:this={divEl} />
</RunnableWrapper>
</div>
@@ -1,9 +1,7 @@
<script lang="ts">
import { Loader2 } from 'lucide-svelte'
import { parse } from 'path'
import { onMount } from 'svelte'
import type { AppInput } from '../../inputType'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
import InputValue from '../helpers/InputValue.svelte'
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
@@ -21,6 +21,7 @@
import AppSliderInputs from '../components/numberInputs/AppSliderInputs.svelte'
import AppFormButton from '../components/form/AppFormButton.svelte'
import VegaLiteHtml from '../components/dataDisplay/VegaLiteHtml.svelte'
import PlotlyHtml from '../components/dataDisplay/PlotlyHtml.svelte'
export let component: AppComponent
export let selected: boolean
@@ -86,6 +87,12 @@
bind:componentInput={component.componentInput}
bind:staticOutputs={$staticOutputs[component.id]}
/>
{:else if component.type === 'plotlycomponent'}
<PlotlyHtml
{...component}
bind:componentInput={component.componentInput}
bind:staticOutputs={$staticOutputs[component.id]}
/>
{:else if component.type === 'scatterchartcomponent'}
<AppScatterChart
{...component}
@@ -39,7 +39,8 @@
'piechartcomponent',
'displaycomponent',
'scatterchartcomponent',
'vegalitecomponent'
'vegalitecomponent',
'plotlycomponent'
],
'3:10-6:10': ['tablecomponent']
}
@@ -328,6 +328,28 @@ const display: ComponentSet = {
},
card: false
},
{
softWrap: false,
id: 'plotlycomponent',
type: 'plotlycomponent',
componentInput: {
type: 'static',
fieldType: 'object',
value: {
type: 'bar',
x: [1, 2, 3, 4],
y: [5, 10, 2, 8],
marker: {
color: '#C8A2C8',
line: {
width: 2.5
}
}
}
},
configuration: {},
card: false
},
{
softWrap: true,
horizontalAlignment: 'left',
@@ -147,6 +147,39 @@ def main():
"y": { "field": "b", "type": "quantitative" },
},
}
`
},
plotlycomponent: {
deno:
`
export async function main() {
return {
type: 'bar',
x: [1, 2, 3, 4],
y: [5, 10, 2, 8],
marker: {
color: '#C8A2C8',
line: {
width: 2.5
}
}
};
}
`,
python3:
`
def main():
return {
"type": "bar",
"x": [1, 2, 3, 4],
"y": [5, 10, 2, 8],
"marker": {
"color": "#C8A2C8",
"line": {
"width": 2.5
}
}
}
`
},
piechartcomponent: {
@@ -25,6 +25,7 @@ export type NumberInputComponent = BaseComponent<'numberinputcomponent'>
export type SliderComponent = BaseComponent<'slidercomponent'>
export type HtmlComponent = BaseComponent<'htmlcomponent'>
export type VegaLiteComponent = BaseComponent<'vegalitecomponent'>
export type PlotlyComponent = BaseComponent<'plotlycomponent'>
export type TimeseriesComponent = BaseComponent<'timeseriescomponent'>
export type ButtonComponent = BaseComponent<'buttoncomponent'> & {
recomputeIds: string[] | undefined
@@ -107,6 +108,7 @@ export type AppComponent = BaseAppComponent &
| FormComponent
| FormButtonComponent
| VegaLiteComponent
| PlotlyComponent
)
export type ComponentSet = {
@@ -122,6 +122,10 @@ export const displayData: Record<AppComponent['type'], { name: string; icon: any
name: 'Vega Lite',
icon: PieChart
},
plotlycomponent: {
name: 'Plotly',
icon: PieChart
},
timeseriescomponent: {
name: 'Timeseries',
icon: GripHorizontal