diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index bcb137a12..4c3f4f73b 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -8,11 +8,10 @@ import * as uuid from "uuid"; import { MultiProvider } from "@solid-primitives/context"; import { Navigate, type RouteDefinition, type RouteSectionProps, Router } from "@solidjs/router"; import { FirebaseProvider } from "solid-firebase"; -import { Show, createResource, lazy, useContext } from "solid-js"; +import { Show, createResource, lazy } from "solid-js"; -import type { JsonValue } from "catcolab-api"; -import { RepoContext, RpcContext, createRpcClient } from "./api"; -import { newModelDocument } from "./model/document"; +import { RepoContext, RpcContext, createRpcClient, useApi } from "./api"; +import { createModel } from "./model/document"; import { HelpContainer, lazyMdx } from "./page/help_page"; import { TheoryLibraryContext, stdTheories } from "./stdlib"; @@ -46,21 +45,9 @@ const Root = (props: RouteSectionProps) => { }; function CreateModel() { - const rpc = useContext(RpcContext); - invariant(rpc, "Missing context to create model"); + const api = useApi(); - const init = newModelDocument(); - - const [ref] = createResource(async () => { - const result = await rpc.new_ref.mutate({ - content: init as JsonValue, - permissions: { - anyone: "Read", - }, - }); - invariant(result.tag === "Ok", "Failed to create model"); - return result.content; - }); + const [ref] = createResource(() => createModel(api)); return {(ref) => }; } diff --git a/packages/frontend/src/analysis/analysis_editor.tsx b/packages/frontend/src/analysis/analysis_editor.tsx index 1ef5b6319..c4b8b25bb 100644 --- a/packages/frontend/src/analysis/analysis_editor.tsx +++ b/packages/frontend/src/analysis/analysis_editor.tsx @@ -1,12 +1,20 @@ import Resizable, { type ContextValue } from "@corvu/resizable"; import { useParams } from "@solidjs/router"; -import { Show, createEffect, createResource, createSignal, useContext } from "solid-js"; +import { + Match, + Show, + Switch, + createEffect, + createResource, + createSignal, + useContext, +} from "solid-js"; import { Dynamic } from "solid-js/web"; import invariant from "tiny-invariant"; -import { RepoContext, RpcContext, getLiveDoc } from "../api"; +import { useApi } from "../api"; import { IconButton, ResizableHandle } from "../components"; -import { LiveModelContext, type ModelDocument, enlivenModelDocument } from "../model"; +import { DiagramPane } from "../diagram/diagram_editor"; import { ModelPane } from "../model/model_editor"; import { type CellConstructor, @@ -16,9 +24,15 @@ import { } from "../notebook"; import { BrandedToolbar, HelpButton } from "../page"; import { TheoryLibraryContext } from "../stdlib"; -import type { ModelAnalysisMeta } from "../theory"; -import type { AnalysisDocument, LiveAnalysisDocument } from "./document"; -import type { ModelAnalysis } from "./types"; +import type { AnalysisMeta } from "../theory"; +import { LiveAnalysisContext } from "./context"; +import { + type LiveAnalysisDocument, + type LiveDiagramAnalysisDocument, + type LiveModelAnalysisDocument, + getLiveAnalysis, +} from "./document"; +import type { Analysis } from "./types"; import PanelRight from "lucide-solid/icons/panel-right"; import PanelRightClose from "lucide-solid/icons/panel-right-close"; @@ -28,87 +42,13 @@ export default function AnalysisPage() { const refId = params.ref; invariant(refId, "Must provide document ref as parameter to analysis page"); - const rpc = useContext(RpcContext); - const repo = useContext(RepoContext); + const api = useApi(); const theories = useContext(TheoryLibraryContext); - invariant(rpc && repo && theories, "Missing context for analysis page"); - - const [liveAnalysis] = createResource(async () => { - const liveDoc = await getLiveDoc(rpc, repo, refId); - const { doc } = liveDoc; - invariant(doc.type === "analysis", () => `Expected analysis, got type: ${doc.type}`); + invariant(theories, "Must provide theory library as context to analysis page"); - const liveModelDoc = await getLiveDoc(rpc, repo, doc.modelRef.refId); - const liveModel = enlivenModelDocument(doc.modelRef.refId, liveModelDoc, theories); - - return { refId, liveDoc, liveModel }; - }); + const [liveAnalysis] = createResource(() => getLiveAnalysis(refId, api, theories)); - return ( - - {(liveAnalysis) => } - - ); -} - -/** Notebook editor for analyses of models of double theories. - */ -export function AnalysisPane(props: { - liveAnalysis: LiveAnalysisDocument; -}) { - const liveDoc = () => props.liveAnalysis.liveDoc; - return ( - - liveDoc().changeDoc((doc) => f(doc.notebook))} - formalCellEditor={ModelAnalysisCellEditor} - cellConstructors={modelAnalysisCellConstructors( - props.liveAnalysis.liveModel.theory()?.modelAnalyses ?? [], - )} - noShortcuts={true} - /> - - ); -} - -function ModelAnalysisCellEditor(props: FormalCellEditorProps) { - const liveModel = useContext(LiveModelContext); - invariant(liveModel, "Live model should be provided as context for analysis"); - - return ( - - {(analysis) => ( - void) => - props.changeContent((content) => f(content.content)) - } - /> - )} - - ); -} - -function modelAnalysisCellConstructors( - analyses: ModelAnalysisMeta[], -): CellConstructor[] { - return analyses.map((analysis) => { - const { id, name, description, initialContent } = analysis; - return { - name, - description, - construct: () => - newFormalCell({ - id, - content: initialContent(), - }), - }; - }); + return ; } /** Editor for a model of a double theory. @@ -117,11 +57,8 @@ The editor includes a notebook for the model itself plus another pane for performing analysis of the model. */ export function AnalysisDocumentEditor(props: { - liveAnalysis: LiveAnalysisDocument; + liveAnalysis?: LiveAnalysisDocument; }) { - const rpc = useContext(RpcContext); - invariant(rpc, "Must provide RPC context"); - const [resizableContext, setResizableContext] = createSignal(); const [isSidePanelOpen, setSidePanelOpen] = createSignal(true); @@ -170,7 +107,7 @@ export function AnalysisDocumentEditor(props: { - +