diff --git a/frontend/src/lib/components/apps/components/display/AppChartJsV2.svelte b/frontend/src/lib/components/apps/components/display/AppChartJsV2.svelte new file mode 100644 index 0000000000..eacf22023f --- /dev/null +++ b/frontend/src/lib/components/apps/components/display/AppChartJsV2.svelte @@ -0,0 +1,159 @@ + + +{#if datasets} + +{/if} + +{#if xData} + +{/if} + +{#if resolvedDatasets} + {#each resolvedDatasets as resolvedDataset, index (resolvedDataset.name + index)} + + {/each} +{/if} + +{#each Object.keys(components['chartjscomponentv2'].initialData.configuration) as key (key)} + +{/each} + +{#each Object.keys(css ?? {}) as key (key)} + +{/each} + + +
+ {#if data && resolvedConfig.type} + {#key resolvedConfig.type} + {#key options} + + {/key} + {/key} + {/if} +
+
diff --git a/frontend/src/lib/components/apps/editor/component/Component.svelte b/frontend/src/lib/components/apps/editor/component/Component.svelte index a1d45e8314..7afd6b2de4 100644 --- a/frontend/src/lib/components/apps/editor/component/Component.svelte +++ b/frontend/src/lib/components/apps/editor/component/Component.svelte @@ -55,6 +55,7 @@ import AppLogsComponent from '../../components/display/AppLogsComponent.svelte' import AppFlowStatusComponent from '../../components/display/AppFlowStatusComponent.svelte' import AppChartJs from '../../components/display/AppChartJs.svelte' + import AppChartJsV2 from '../../components/display/AppChartJsV2.svelte' import AppQuillEditor from '../../components/inputs/AppQuillEditor.svelte' import AppList from '../../components/layout/AppList.svelte' import AppJobIdLogComponent from '../../components/display/AppJobIdLogComponent.svelte' @@ -645,6 +646,17 @@ componentInput={component.componentInput} {render} /> + {:else if component.type === 'chartjscomponentv2'} + {:else if component.type === 'carousellistcomponent'} export type BarChartComponent = BaseComponent<'barchartcomponent'> export type PieChartComponent = BaseComponent<'piechartcomponent'> export type ChartJsComponent = BaseComponent<'chartjscomponent'> +export type ChartJsComponentV2 = BaseComponent<'chartjscomponentv2'> & { + xData: RichConfiguration | undefined + datasets: RichConfiguration | undefined +} export type ScatterChartComponent = BaseComponent<'scatterchartcomponent'> @@ -208,6 +212,7 @@ export type TypedComponent = | ChartJsComponent | CarouselListComponent | PlotlyComponentV2 + | ChartJsComponentV2 export type AppComponent = BaseAppComponent & TypedComponent @@ -1112,6 +1117,33 @@ export const components = { } } }, + chartjscomponentv2: { + name: 'ChartJs', + icon: PieChart, + documentationLink: `${documentationBaseUrl}/chartjs`, + dims: '2:8-6:8' as AppComponentDimensions, + customCss: { + container: { class: '', style: '' } + }, + initialData: { + configuration: { + type: { + type: 'static', + + fieldType: 'select', + selectOptions: selectOptions.chartTypeOptions, + value: 'pie' + }, + options: { + type: 'static', + fieldType: 'object', + value: {}, + tooltip: 'ChartJs options object' + } + }, + componentInput: undefined + } + }, barchartcomponent: { name: 'Bar/Line Chart', icon: BarChart4, diff --git a/frontend/src/lib/components/apps/editor/component/sets.ts b/frontend/src/lib/components/apps/editor/component/sets.ts index 9c20fb1ea2..ff6121a26a 100644 --- a/frontend/src/lib/components/apps/editor/component/sets.ts +++ b/frontend/src/lib/components/apps/editor/component/sets.ts @@ -74,15 +74,7 @@ const tables: ComponentSet = { const charts: ComponentSet = { title: 'Charts', - components: [ - 'barchartcomponent', - 'piechartcomponent', - 'vegalitecomponent', - 'plotlycomponentv2', - 'scatterchartcomponent', - 'timeseriescomponent', - 'chartjscomponent' - ] + components: ['plotlycomponentv2', 'chartjscomponentv2', 'vegalitecomponent'] } as const export const COMPONENT_SETS = [layout, tabs, buttons, inputs, tables, display, charts] as const diff --git a/frontend/src/lib/components/apps/editor/componentsPanel/quickStyleProperties.ts b/frontend/src/lib/components/apps/editor/componentsPanel/quickStyleProperties.ts index 5f467b15d5..42ad822d29 100644 --- a/frontend/src/lib/components/apps/editor/componentsPanel/quickStyleProperties.ts +++ b/frontend/src/lib/components/apps/editor/componentsPanel/quickStyleProperties.ts @@ -670,6 +670,9 @@ export const quickStyleProperties: Record< chartjscomponent: { container: containerDefaultProps }, + chartjscomponentv2: { + container: containerDefaultProps + }, vegalitecomponent: {}, containercomponent: { container: containerDefaultProps diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte index a8b8a91ef5..8bb44e2e4e 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte @@ -66,6 +66,16 @@ .toString(16) .padEnd(6, '0')}` }) + } else if (subFieldType === 'chartjs') { + value.push({ + value: { + type: 'static', + fieldType: 'array', + subFieldType: 'number', + value: [2, 4, 5, 6] + }, + name: 'New dataset' + }) } } else { value.push('') @@ -181,6 +191,7 @@ subFieldType={raw ? 'object' : subFieldType} bind:componentInput bind:value={item.value} + on:remove={() => deleteElementByType(index)} /> diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ChartJSRichEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ChartJSRichEditor.svelte new file mode 100644 index 0000000000..0573cb63db --- /dev/null +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ChartJSRichEditor.svelte @@ -0,0 +1,58 @@ + + + +
+ {#if xData} + + {/if} + + {#if datasets} + + {/if} +
+
diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanelDataSource.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanelDataSource.svelte index 2f7637f52e..e69b39e484 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanelDataSource.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/ComponentPanelDataSource.svelte @@ -4,6 +4,7 @@ import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte' import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte' import PlotlyRichEditor from './PlotlyRichEditor.svelte' + import ChartJSRichEditor from './ChartJSRichEditor.svelte' import { onMount } from 'svelte' import type { RichConfiguration } from '../../types' import type { InputConnectionEval } from '../../inputType' @@ -17,7 +18,7 @@ onMount(() => { if ( - component.type === 'plotlycomponentv2' && + (component.type === 'plotlycomponentv2' || component.type === 'chartjscomponentv2') && component.componentInput === undefined && component.datasets === undefined ) { @@ -37,30 +38,80 @@ color: string } + function resolveConfiguration( + x: RichConfiguration | undefined, + connections: InputConnectionEval[] + ): string | undefined { + if (!x) return undefined + if (x.type === 'evalv2') { + connections.push(...x.connections) + return x.expr + } + if (x.type === 'static') return `[${x.value}]` + return undefined + } + function handleSelected(selected: string) { - if (component.type !== 'plotlycomponentv2') return + if (component.type === 'plotlycomponentv2') { + if (selected === 'ui-editor') { + convertToUIEditorCallback = () => { + component.componentInput = undefined + setUpUIEditor() + } - if (selected === 'ui-editor') { - convertToUIEditorCallback = () => { - component.componentInput = undefined - setUpUIEditor() + setTimeout(() => { + const activeElement = document.activeElement as HTMLElement + activeElement?.blur() + document.body.focus() + }) + } else if (selected === 'json') { + convertToJson() } + } else if (component.type === 'chartjscomponentv2') { + if (selected === 'ui-editor') { + convertToUIEditorCallback = () => { + component.componentInput = undefined + setUpUIEditor() + } - setTimeout(() => { - const activeElement = document.activeElement as HTMLElement - activeElement?.blur() - document.body.focus() - }) - } else if (selected === 'json') { - convertToJson(component) + setTimeout(() => { + const activeElement = document.activeElement as HTMLElement + activeElement?.blur() + document.body.focus() + }) + } else if (selected === 'json') { + convertChartJSToJson() + } } } function setUpUIEditor() { - if (component.type !== 'plotlycomponentv2') return + if (component.type === 'plotlycomponentv2') { + component.datasets = createPlotlyComponentDataset() + component.xData = createXData() + } else if (component.type === 'chartjscomponentv2') { + component.datasets = createChartjsComponentDataset() + component.xData = createXData() + } + } - component.datasets = createPlotlyComponentDataset() - component.xData = createXData() + function createChartjsComponentDataset(): RichConfiguration { + return { + type: 'static', + fieldType: 'array', + subFieldType: 'chartjs', + value: [ + { + value: { + type: 'static', + fieldType: 'array', + subFieldType: 'number', + value: [25, 25, 50] + }, + name: 'Dataset 1' + } + ] + } } function createPlotlyComponentDataset(): RichConfiguration { @@ -95,20 +146,11 @@ } } - function resolveConfiguration( - x: RichConfiguration | undefined, - connections: InputConnectionEval[] - ): string | undefined { - if (!x) return undefined - if (x.type === 'evalv2') { - connections.push(...x.connections) - return x.expr + function convertToJson() { + if (component.type !== 'plotlycomponentv2') { + return } - if (x.type === 'static') return `[${x.value}]` - return undefined - } - function convertToJson(component: any) { const connections: InputConnectionEval[] = [] const xDataResolved = resolveConfiguration(component.xData, connections) @@ -133,6 +175,42 @@ component.xData = undefined } + function convertChartJSToJson() { + if (component.type !== 'chartjscomponentv2') { + return + } + + const connections: InputConnectionEval[] = [] + const xDataResolved = resolveConfiguration(component.xData, connections) + + if (component.datasets === undefined || component.datasets.type !== 'static') return + + const datasets = component.datasets?.value + + component.componentInput = { + type: 'evalv2', + fieldType: 'object', + noStatic: true, + expr: `({ +\t"labels": ${xDataResolved}, +\t"datasets": [\n${ + datasets + .map( + (rawDataset: Dataset) => `\t\t{ +\t\t\tdata:${resolveConfiguration(rawDataset.value, connections)}, +\t\t\tlabel: "${rawDataset.name}" +\t\t}` + ) + .join(',\n') || '' + }\n\t] +})`, + connections: connections.filter(Boolean) + } + + component.datasets = undefined + component.xData = undefined + } + function datasetToJson( dataset: Dataset, xDataExpr: string | undefined, @@ -151,7 +229,7 @@ } -{#if component.type === 'plotlycomponentv2'} +{#if component.type === 'plotlycomponentv2' || component.type === 'chartjscomponentv2'}
+ {#if component.type === 'plotlycomponentv2'} + + {:else if component.type === 'chartjscomponentv2'} + + {/if} {/key} {:else} diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/SubTypeEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/SubTypeEditor.svelte index 5c0786c70c..77dd5e9bcc 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/SubTypeEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/SubTypeEditor.svelte @@ -15,4 +15,4 @@ $: fakeComponentInput && (value = fakeComponentInput.value) - + diff --git a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte index 001293114a..8b2cd719ad 100644 --- a/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +++ b/frontend/src/lib/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte @@ -16,6 +16,7 @@ import AgGridWizard from '$lib/components/wizards/AgGridWizard.svelte' import TableColumnWizard from '$lib/components/wizards/TableColumnWizard.svelte' import PlotlyWizard from '$lib/components/wizards/PlotlyWizard.svelte' + import ChartJSWizard from '$lib/components/wizards/ChartJSWizard.svelte' export let componentInput: StaticInput | undefined export let fieldType: InputType | undefined = undefined @@ -171,7 +172,7 @@ placeholder="Dataset name" />
- +
+ {:else if fieldType === 'chartjs'} +
+
+ +
+ + + + + +
+
+
{:else}