Skip to content

Commit 95af92e

Browse files
committed
feat: finish the editor
1 parent 466f7fc commit 95af92e

4 files changed

Lines changed: 69 additions & 19 deletions

File tree

packages/pluggableWidgets/chart-playground-web/src/helpers/useComposedEditorController.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useMemo, useState } from "react";
1+
import { useCallback, useEffect, useMemo, useState } from "react";
22
import { fallback, PlaygroundDataV1 } from "@mendix/shared-charts/main";
33
import { ComposedEditorProps } from "../components/ComposedEditor";
44
import { SelectOption } from "../components/Sidebar";
@@ -30,6 +30,13 @@ function getModelerCode(data: PlaygroundDataV1, key: ConfigKey): Partial<Data> |
3030
const entries = Object.entries(data.plotData.at(key) ?? {}).filter(([key]) => !irrelevantSeriesKeys.includes(key));
3131
return Object.fromEntries(entries) as Partial<Data>;
3232
}
33+
function prettifyJson(json: string): string {
34+
try {
35+
return JSON.stringify(JSON.parse(json), null, 2);
36+
} catch {
37+
return '{ "error": "invalid JSON" }';
38+
}
39+
}
3340

3441
export function useComposedEditorController(data: PlaygroundDataV1): ComposedEditorProps {
3542
const [key, setKey] = useState<ConfigKey>("layout");
@@ -56,8 +63,11 @@ export function useComposedEditorController(data: PlaygroundDataV1): ComposedEdi
5663
}, [data.plotData]);
5764

5865
const store = data.store;
66+
const code = prettifyJson(getEditorCode(data, key));
67+
const [input, setInput] = useState(() => code);
5968
const onEditorChange = useCallback(
6069
(value: string): void => {
70+
setInput(value);
6171
try {
6272
const json = fallback(value);
6373
JSON.parse(value);
@@ -68,11 +78,18 @@ export function useComposedEditorController(data: PlaygroundDataV1): ComposedEdi
6878
[store, key]
6979
);
7080

81+
useEffect(
82+
() =>
83+
// eslint-disable-next-line react-hooks/set-state-in-effect
84+
setInput(code),
85+
[code]
86+
);
87+
7188
return {
7289
viewSelectValue: key.toString(),
7390
viewSelectOptions: options,
7491
onViewSelectChange,
75-
value: getEditorCode(data, key),
92+
value: input,
7693
modelerCode: useMemo(() => JSON.stringify(getModelerCode(data, key), null, 2), [data, key]),
7794
onEditorChange
7895
};

packages/pluggableWidgets/chart-playground-web/src/helpers/useV2EdtiorController.ts

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useCallback, useMemo, useState } from "react";
1+
import { observable, reaction, runInAction } from "mobx";
2+
import { useCallback, useEffect, useMemo, useState } from "react";
23
import { PlaygroundDataV2 } from "@mendix/shared-charts/main";
34
import { ComposedEditorProps } from "../components/ComposedEditor";
45
import { SelectOption } from "../components/Sidebar";
@@ -7,7 +8,7 @@ type ConfigKey = "layout" | "config" | number;
78

89
const irrelevantSeriesKeys = ["x", "y", "z", "customSeriesOptions", "dataSourceItems"];
910

10-
function getEditorCode({ store }: PlaygroundDataV2, key: ConfigKey): string {
11+
function getEditorCode(store: PlaygroundDataV2["store"], key: ConfigKey): string {
1112
if (key === "layout") {
1213
return store.layoutJson ?? '{ "error": "value is unavailable" }';
1314
}
@@ -28,38 +29,56 @@ function getModelerCode(data: PlaygroundDataV2, key: ConfigKey): object {
2829
return Object.fromEntries(entries);
2930
}
3031

31-
export function useV2EditorController(data: PlaygroundDataV2): ComposedEditorProps {
32+
function prettifyJson(json: string): string {
33+
try {
34+
return JSON.stringify(JSON.parse(json), null, 2);
35+
} catch {
36+
return '{ "error": "invalid JSON" }';
37+
}
38+
}
39+
40+
export function useV2EditorController(context: PlaygroundDataV2): ComposedEditorProps {
3241
const [key, setKey] = useState<ConfigKey>("layout");
42+
const keyBox = useState(() => observable.box<ConfigKey>(key))[0];
3343

3444
const onViewSelectChange = (value: string): void => {
45+
let newKey: ConfigKey;
3546
if (value === "layout" || value === "config") {
36-
setKey(value);
47+
newKey = value;
3748
} else {
3849
const n = parseInt(value, 10);
39-
setKey(isNaN(n) ? "layout" : n);
50+
newKey = isNaN(n) ? "layout" : n;
4051
}
52+
setKey(newKey);
53+
runInAction(() => keyBox.set(newKey));
4154
};
4255

56+
const store = context.store;
57+
4358
const options: SelectOption[] = useMemo(() => {
4459
return [
4560
{ name: "Layout", value: "layout", isDefaultSelected: true },
46-
...data.plotData.map((trace, index) => ({
47-
name: trace.name || `trace ${index}`,
61+
...store.data.map((trace, index) => ({
62+
name: (trace.name as string) || `trace ${index}`,
4863
value: index,
4964
isDefaultSelected: false
5065
})),
5166
{ name: "Configuration", value: "config", isDefaultSelected: false }
5267
];
53-
}, [data.plotData]);
68+
}, [store.data]);
5469

55-
const store = data.store;
70+
const code = prettifyJson(getEditorCode(store, key));
71+
const [input, setInput] = useState(() => code);
5672
const onEditorChange = useCallback(
5773
(value: string): void => {
74+
setInput(value);
5875
try {
76+
// Parse string before sending to store
77+
const obj = JSON.parse(value);
5978
if (key === "layout") {
60-
store.setLayout(JSON.parse(value));
79+
store.setLayout(obj);
6180
} else if (key === "config") {
62-
store.setConfig(JSON.parse(value));
81+
store.setConfig(obj);
6382
} else {
6483
store.setDataAt(key, value);
6584
}
@@ -69,12 +88,21 @@ export function useV2EditorController(data: PlaygroundDataV2): ComposedEditorPro
6988
[store, key]
7089
);
7190

91+
useEffect(
92+
() =>
93+
reaction(
94+
() => getEditorCode(store, keyBox.get()),
95+
code => setInput(prettifyJson(code))
96+
),
97+
[store, keyBox]
98+
);
99+
72100
return {
73101
viewSelectValue: key.toString(),
74102
viewSelectOptions: options,
75103
onViewSelectChange,
76-
value: getEditorCode(data, key),
77-
modelerCode: useMemo(() => JSON.stringify(getModelerCode(data, key), null, 2), [data, key]),
104+
value: input,
105+
modelerCode: useMemo(() => JSON.stringify(getModelerCode(context, key), null, 2), [context, key]),
78106
onEditorChange
79107
};
80108
}

packages/pluggableWidgets/custom-chart-web/src/hooks/useCustomChart.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ export function useCustomChart(props: CustomChartContainerProps): UseCustomChart
5656
type: "editor.data.v2",
5757
store,
5858
plotData: store.data,
59-
layoutOptions: store.layout,
60-
configOptions: store.config
59+
layoutOptions: {},
60+
configOptions: {}
6161
})
6262
).get();
6363

packages/shared/charts/src/model/stores/EditableChart.store.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { autorun, makeAutoObservable, observable } from "mobx";
1+
import { action, autorun, makeAutoObservable, observable } from "mobx";
22
import { SetupComponentHost, SetupComponent, disposeBatch, ComputedAtom } from "@mendix/widget-plugin-mobx-kit/main";
33

44
export type JSONString = string;
@@ -38,7 +38,12 @@ export class EditableChartStore implements SetupComponent {
3838
makeAutoObservable(this, {
3939
layout: observable.ref,
4040
config: observable.ref,
41-
data: observable.ref
41+
data: observable.ref,
42+
setup: false,
43+
setLayout: action,
44+
setConfig: action,
45+
setDataAt: action,
46+
reset: action
4247
});
4348
}
4449

0 commit comments

Comments
 (0)