From 0f8e7ce6b6193d291dd6df5a739af194e2a4f3ef Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Sat, 8 Oct 2022 16:23:58 +1100 Subject: [PATCH 1/2] Project in editors and remove warnings --- .../components/src/components/CodeEditor.tsx | 5 +--- .../src/components/SquiggleChart.tsx | 28 ++++++++--------- .../src/components/SquiggleEditor.tsx | 13 ++++---- .../components/src/lib/hooks/useSquiggle.ts | 30 +++++++++++++------ packages/components/test/basic.test.tsx | 27 +++++++++++++++-- 5 files changed, 64 insertions(+), 39 deletions(-) diff --git a/packages/components/src/components/CodeEditor.tsx b/packages/components/src/components/CodeEditor.tsx index ec2fdee7..57a1e9ba 100644 --- a/packages/components/src/components/CodeEditor.tsx +++ b/packages/components/src/components/CodeEditor.tsx @@ -55,10 +55,7 @@ export const CodeEditor: FC = ({ editorProps={{ $blockScrolling: true, }} - setOptions={{ - enableBasicAutocompletion: false, - enableLiveAutocompletion: false, - }} + setOptions={{}} commands={[ { name: "submit", diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 215031a7..ac913320 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -1,5 +1,10 @@ import * as React from "react"; -import { SqValue, environment, SqProject } from "@quri/squiggle-lang"; +import { + SqValue, + environment, + SqProject, + defaultEnvironment, +} from "@quri/squiggle-lang"; import { useSquiggle } from "../lib/hooks"; import { SquiggleViewer } from "./SquiggleViewer"; import { JsImports } from "../lib/jsImports"; @@ -121,23 +126,14 @@ export const SquiggleChart: React.FC = React.memo( height = 200, enableLocalSettings = false, continues = defaultContinues, + project, + environment, } = props; - const p = React.useMemo(() => { - if (props.project) { - return props.project; - } else { - const p = SqProject.create(); - if (props.environment) { - p.setEnvironment(props.environment); - } - return p; - } - }, [props.project, props.environment]); - const resultAndBindings = useSquiggle({ + environment, continues, - project: p, + project, code, jsImports, onChange, @@ -153,7 +149,9 @@ export const SquiggleChart: React.FC = React.memo( height={height} distributionPlotSettings={distributionPlotSettings} chartSettings={chartSettings} - environment={p.getEnvironment()} + environment={ + project ? project.getEnvironment() : environment ?? defaultEnvironment + } enableLocalSettings={enableLocalSettings} /> ); diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 23765f38..27d24cf0 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -35,6 +35,7 @@ export type SquiggleEditorProps = SquiggleChartProps & { const defaultOnChange = () => {}; const defaultImports: JsImports = {}; +const defaultContinues: string[] = []; export const SquiggleEditor: React.FC = (props) => { const [code, setCode] = useMaybeControlledValue({ @@ -54,17 +55,13 @@ export const SquiggleEditor: React.FC = (props) => { width, height = 200, enableLocalSettings = false, + continues = defaultContinues, + project, } = props; - const project = React.useMemo(() => { - const p = SqProject.create(); - if (environment) { - p.setEnvironment(environment); - } - return p; - }, [environment]); - const resultAndBindings = useSquiggle({ + environment, + continues, code, project, jsImports, diff --git a/packages/components/src/lib/hooks/useSquiggle.ts b/packages/components/src/lib/hooks/useSquiggle.ts index 63fa3839..1c01acb8 100644 --- a/packages/components/src/lib/hooks/useSquiggle.ts +++ b/packages/components/src/lib/hooks/useSquiggle.ts @@ -4,16 +4,18 @@ import { SqProject, SqRecord, SqValue, + environment, } from "@quri/squiggle-lang"; import { useEffect, useMemo } from "react"; import { JsImports, jsImportsToSquiggleCode } from "../jsImports"; import * as uuid from "uuid"; type SquiggleArgs = { + environment?: environment; code: string; executionId?: number; jsImports?: JsImports; - project: SqProject; + project?: SqProject; continues?: string[]; onChange?: (expr: SqValue | undefined, sourceName: string) => void; }; @@ -27,15 +29,25 @@ const importSourceName = (sourceName: string) => "imports-" + sourceName; const defaultContinues = []; export const useSquiggle = (args: SquiggleArgs): ResultAndBindings => { + const project = useMemo(() => { + if (args.project) { + return args.project; + } else { + const p = SqProject.create(); + if (args.environment) { + p.setEnvironment(args.environment); + } + return p; + } + }, [args.project, args.environment]); + const sourceName = useMemo(() => uuid.v4(), []); - const env = args.project.getEnvironment(); + const env = project.getEnvironment(); const continues = args.continues || defaultContinues; const result = useMemo( () => { - const project = args.project; - project.setSource(sourceName, args.code); let fullContinues = continues; if (args.jsImports && Object.keys(args.jsImports).length) { @@ -59,7 +71,7 @@ export const useSquiggle = (args: SquiggleArgs): ResultAndBindings => { args.executionId, sourceName, continues, - args.project, + project, env, ] ); @@ -75,11 +87,11 @@ export const useSquiggle = (args: SquiggleArgs): ResultAndBindings => { useEffect(() => { return () => { - args.project.removeSource(sourceName); - if (args.project.getSource(importSourceName(sourceName))) - args.project.removeSource(importSourceName(sourceName)); + project.removeSource(sourceName); + if (project.getSource(importSourceName(sourceName))) + project.removeSource(importSourceName(sourceName)); }; - }, [args.project, sourceName]); + }, [project, sourceName]); return result; }; diff --git a/packages/components/test/basic.test.tsx b/packages/components/test/basic.test.tsx index e77f104b..3f995207 100644 --- a/packages/components/test/basic.test.tsx +++ b/packages/components/test/basic.test.tsx @@ -1,9 +1,10 @@ -import { render } from "@testing-library/react"; +import { render, screen } from "@testing-library/react"; import React from "react"; import "@testing-library/jest-dom"; -import { SquiggleChart } from "../src/index"; +import { SquiggleChart, SquiggleEditor } from "../src/index"; +import { SqProject } from "@quri/squiggle-lang"; -test("Logs nothing on render", async () => { +test("Chart logs nothing on render", async () => { const { unmount } = render(); unmount(); @@ -11,3 +12,23 @@ test("Logs nothing on render", async () => { expect(console.warn).not.toBeCalled(); expect(console.error).not.toBeCalled(); }); + +test("Editor logs nothing on render", async () => { + const { unmount } = render(); + unmount(); + + expect(console.log).not.toBeCalled(); + expect(console.warn).not.toBeCalled(); + expect(console.error).not.toBeCalled(); +}); + +test("Project dependencies work in editors", async () => { + const project = SqProject.create(); + + render(); + const source = project.getSourceIds()[0]; + render( + + ); + screen.getByText("2"); +}); From 98454a87b587d45c585cd20f9d6ad8a5a0f5e497 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 10 Oct 2022 14:23:04 +1100 Subject: [PATCH 2/2] Get projects working in Playgrounds --- packages/components/src/components/Alert.tsx | 2 +- .../src/components/SquiggleChart.tsx | 3 +-- .../src/components/SquiggleEditor.tsx | 3 +-- .../src/components/SquigglePlayground.tsx | 12 +++------ .../components/SquiggleViewer/VariableBox.tsx | 2 +- packages/components/test/basic.test.tsx | 25 ++++++++++++++++--- 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/components/src/components/Alert.tsx b/packages/components/src/components/Alert.tsx index cb579536..52b4a3e4 100644 --- a/packages/components/src/components/Alert.tsx +++ b/packages/components/src/components/Alert.tsx @@ -24,7 +24,7 @@ export const Alert: React.FC<{ children, }) => { return ( -
+
{}; const defaultImports: JsImports = {}; -const defaultContinues: string[] = []; export const splitSquiggleChartSettings = (props: SquiggleChartProps) => { const { @@ -125,7 +124,7 @@ export const SquiggleChart: React.FC = React.memo( width, height = 200, enableLocalSettings = false, - continues = defaultContinues, + continues, project, environment, } = props; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 27d24cf0..9be3625e 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -35,7 +35,6 @@ export type SquiggleEditorProps = SquiggleChartProps & { const defaultOnChange = () => {}; const defaultImports: JsImports = {}; -const defaultContinues: string[] = []; export const SquiggleEditor: React.FC = (props) => { const [code, setCode] = useMaybeControlledValue({ @@ -55,7 +54,7 @@ export const SquiggleEditor: React.FC = (props) => { width, height = 200, enableLocalSettings = false, - continues = defaultContinues, + continues, project, } = props; diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index 59898d6b..025d5bed 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -251,6 +251,8 @@ export const SquigglePlayground: FC = ({ onSettingsChange, showEditor = true, showShareButton = false, + continues, + project, }) => { const [code, setCode] = useMaybeControlledValue({ value: controlledCode, @@ -305,15 +307,9 @@ export const SquigglePlayground: FC = ({ executionId, } = useRunnerState(code); - const project = React.useMemo(() => { - const p = SqProject.create(); - if (environment) { - p.setEnvironment(environment); - } - return p; - }, [environment]); - const resultAndBindings = useSquiggle({ + environment, + continues, code, project, jsImports: imports, diff --git a/packages/components/src/components/SquiggleViewer/VariableBox.tsx b/packages/components/src/components/SquiggleViewer/VariableBox.tsx index ca0fc875..62431d5e 100644 --- a/packages/components/src/components/SquiggleViewer/VariableBox.tsx +++ b/packages/components/src/components/SquiggleViewer/VariableBox.tsx @@ -45,7 +45,7 @@ export const VariableBox: React.FC = ({ : location.path.items[location.path.items.length - 1]; return ( -
+
{ @@ -27,8 +31,23 @@ test("Project dependencies work in editors", async () => { render(); const source = project.getSourceIds()[0]; - render( + const { container } = render( ); - screen.getByText("2"); + expect(container).toHaveTextContent("2"); +}); + +test("Project dependencies work in playgrounds", async () => { + const project = SqProject.create(); + project.setSource("depend", "x = 1"); + + render( + + ); + // We must await here because SquigglePlayground loads results asynchronously + expect(await screen.findByRole("status")).toHaveTextContent("2"); });