mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 08:00:45 +00:00
feat(frontend): add plotly support
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user