Skip to content

Commit 20de659

Browse files
committed
REFACTOR: Move document creation functions out of components.
1 parent 4490ba9 commit 20de659

File tree

7 files changed

+84
-85
lines changed

7 files changed

+84
-85
lines changed

packages/frontend/src/App.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import { Navigate, type RouteDefinition, type RouteSectionProps, Router } from "
1010
import { FirebaseProvider } from "solid-firebase";
1111
import { Show, createResource, lazy } from "solid-js";
1212

13-
import type { JsonValue } from "catcolab-api";
1413
import { RepoContext, RpcContext, createRpcClient, useApi } from "./api";
15-
import { newModelDocument } from "./model/document";
14+
import { createModel } from "./model/document";
1615
import { HelpContainer, lazyMdx } from "./page/help_page";
1716
import { TheoryLibraryContext, stdTheories } from "./stdlib";
1817

@@ -47,18 +46,8 @@ const Root = (props: RouteSectionProps<unknown>) => {
4746

4847
function CreateModel() {
4948
const api = useApi();
50-
const init = newModelDocument();
5149

52-
const [ref] = createResource<string>(async () => {
53-
const result = await api.rpc.new_ref.mutate({
54-
content: init as JsonValue,
55-
permissions: {
56-
anyone: "Read",
57-
},
58-
});
59-
invariant(result.tag === "Ok", "Failed to create model");
60-
return result.content;
61-
});
50+
const [ref] = createResource<string>(() => createModel(api));
6251

6352
return <Show when={ref()}>{(ref) => <Navigate href={`/model/${ref()}`} />}</Show>;
6453
}

packages/frontend/src/analysis/document.ts

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
import invariant from "tiny-invariant";
22

3+
import type { JsonValue } from "catcolab-api";
34
import { type Api, type ExternRef, type LiveDoc, getLiveDoc } from "../api";
45
import { type LiveDiagramDocument, getLiveDiagram } from "../diagram";
56
import { type LiveModelDocument, getLiveModel } from "../model";
67
import { type Notebook, newNotebook } from "../notebook";
78
import type { TheoryLibrary } from "../stdlib";
89
import type { Analysis } from "./types";
910

11+
type AnalysisType = "model" | "diagram";
12+
1013
/** Common base type for all analysis documents. */
11-
export type BaseAnalysisDocument = {
14+
export type BaseAnalysisDocument<T extends AnalysisType> = {
1215
type: "analysis";
1316

1417
/** User-defined name of analysis. */
1518
name: string;
1619

1720
/** Reference to the document that the analysis is of. */
18-
analysisOf: ExternRef;
21+
analysisOf: ExternRef<T>;
1922

2023
/** Content of the analysis.
2124
@@ -27,38 +30,25 @@ export type BaseAnalysisDocument = {
2730
};
2831

2932
/** A document defining an analysis of a model. */
30-
export type ModelAnalysisDocument = BaseAnalysisDocument & {
31-
analysisOf: { taxon: "model" };
32-
};
33+
export type ModelAnalysisDocument = BaseAnalysisDocument<"model">;
3334

3435
/** A document defining an analysis of a diagram. */
35-
export type DiagramAnalysisDocument = BaseAnalysisDocument & {
36-
analysisOf: { taxon: "diagram" };
37-
};
36+
export type DiagramAnalysisDocument = BaseAnalysisDocument<"diagram">;
3837

3938
/** A document defining an analysis. */
4039
export type AnalysisDocument = ModelAnalysisDocument | DiagramAnalysisDocument;
4140

42-
/** Create an empty model analysis. */
43-
export const newModelAnalysisDocument = (refId: string): ModelAnalysisDocument => ({
44-
name: "",
45-
type: "analysis",
46-
analysisOf: {
47-
tag: "extern-ref",
48-
refId,
49-
taxon: "model",
50-
},
51-
notebook: newNotebook(),
52-
});
53-
54-
/** Create an empty diagram analysis. */
55-
export const newDiagramAnalysisDocument = (refId: string): DiagramAnalysisDocument => ({
41+
/** Create an empty analysis. */
42+
export const newAnalysisDocument = (
43+
taxon: AnalysisType,
44+
refId: string,
45+
): BaseAnalysisDocument<typeof taxon> => ({
5646
name: "",
5747
type: "analysis",
5848
analysisOf: {
5949
tag: "extern-ref",
6050
refId,
61-
taxon: "diagram",
51+
taxon,
6252
},
6353
notebook: newNotebook(),
6454
});
@@ -94,6 +84,21 @@ export type LiveDiagramAnalysisDocument = {
9484
/** An analysis document "live" for editing. */
9585
export type LiveAnalysisDocument = LiveModelAnalysisDocument | LiveDiagramAnalysisDocument;
9686

87+
/** Create a new analysis in the backend. */
88+
export async function createAnalysis(type: AnalysisType, ofRefId: string, api: Api) {
89+
const init = newAnalysisDocument(type, ofRefId);
90+
91+
const result = await api.rpc.new_ref.mutate({
92+
content: init as JsonValue,
93+
permissions: {
94+
anyone: "Read",
95+
},
96+
});
97+
invariant(result.tag === "Ok", "Failed to create a new analysis");
98+
99+
return result.content;
100+
}
101+
97102
/** Retrieve an analysis and make it "live" for editing. */
98103
export async function getLiveAnalysis(
99104
refId: string,

packages/frontend/src/api/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ export type Api = {
99
};
1010

1111
/** A reference in a document to another document. */
12-
export type ExternRef = {
12+
export type ExternRef<T extends string> = {
1313
tag: "extern-ref";
1414
refId: string;
15-
taxon: string;
15+
taxon: T;
1616
};

packages/frontend/src/diagram/diagram_editor.tsx

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { A, useNavigate, useParams } from "@solidjs/router";
33
import { Match, Show, Switch, createResource, useContext } from "solid-js";
44
import invariant from "tiny-invariant";
55

6-
import type { JsonValue } from "catcolab-api";
6+
import { createAnalysis } from "../analysis/document";
77
import { useApi } from "../api";
88
import { IconButton, InlineInput } from "../components";
99
import { LiveModelContext } from "../model";
@@ -33,7 +33,6 @@ import {
3333
import "./diagram_editor.css";
3434

3535
import ChartSpline from "lucide-solid/icons/chart-spline";
36-
import { newDiagramAnalysisDocument } from "../analysis";
3736

3837
export default function DiagramPage() {
3938
const params = useParams();
@@ -55,18 +54,8 @@ export function DiagramDocumentEditor(props: {
5554
const api = useApi();
5655
const navigate = useNavigate();
5756

58-
const createAnalysis = async (diagramRefId: string) => {
59-
const init = newDiagramAnalysisDocument(diagramRefId);
60-
61-
const result = await api.rpc.new_ref.mutate({
62-
content: init as JsonValue,
63-
permissions: {
64-
anyone: "Read",
65-
},
66-
});
67-
invariant(result.tag === "Ok", "Failed to create a new analysis");
68-
const newRef = result.content;
69-
57+
const onCreateAnalysis = async (diagramRefId: string) => {
58+
const newRef = createAnalysis("diagram", diagramRefId, api);
7059
navigate(`/analysis/${newRef}`);
7160
};
7261

@@ -76,7 +65,7 @@ export function DiagramDocumentEditor(props: {
7665
<HelpButton />
7766
<MaybePermissionsButton permissions={props.liveDiagram?.liveDoc.permissions} />
7867
<IconButton
79-
onClick={() => props.liveDiagram && createAnalysis(props.liveDiagram.refId)}
68+
onClick={() => props.liveDiagram && onCreateAnalysis(props.liveDiagram.refId)}
8069
tooltip="Analyze this diagram"
8170
>
8271
<ChartSpline />

packages/frontend/src/diagram/document.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type Accessor, createMemo } from "solid-js";
22
import invariant from "tiny-invariant";
33

4+
import type { JsonValue } from "catcolab-api";
45
import type { DblModelDiagram, ModelDiagramValidationResult, Uuid } from "catlog-wasm";
56
import { type Api, type ExternRef, type LiveDoc, getLiveDoc } from "../api";
67
import { type LiveModelDocument, getLiveModel } from "../model";
@@ -17,7 +18,7 @@ export type DiagramDocument = {
1718
name: string;
1819

1920
/** Reference to the model that the diagram is in. */
20-
modelRef: ExternRef & { taxon: "model" };
21+
modelRef: ExternRef<"model">;
2122

2223
/** Content of the diagram. */
2324
notebook: Notebook<DiagramJudgment>;
@@ -105,7 +106,22 @@ function enlivenDiagramDocument(
105106
return { refId, liveDoc, liveModel, formalJudgments, objectIndex, validatedDiagram };
106107
}
107108

108-
/** Retrieve a diagram and make it "live" for editing. */
109+
/** Create a new diagram in the backend. */
110+
export async function createDiagram(modelRefId: string, api: Api): Promise<string> {
111+
const init = newDiagramDocument(modelRefId);
112+
113+
const result = await api.rpc.new_ref.mutate({
114+
content: init as JsonValue,
115+
permissions: {
116+
anyone: "Read",
117+
},
118+
});
119+
invariant(result.tag === "Ok", "Failed to create a new diagram");
120+
121+
return result.content;
122+
}
123+
124+
/** Retrieve a diagram from the backend and make it "live" for editing. */
109125
export async function getLiveDiagram(
110126
refId: string,
111127
api: Api,

packages/frontend/src/model/document.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type Accessor, createMemo } from "solid-js";
22
import invariant from "tiny-invariant";
33

4+
import type { JsonValue } from "catcolab-api";
45
import type { DblModel, ModelValidationResult, Uuid } from "catlog-wasm";
56
import { type Api, type LiveDoc, getLiveDoc } from "../api";
67
import { type Notebook, newNotebook } from "../notebook";
@@ -128,7 +129,27 @@ function enlivenModelDocument(
128129
};
129130
}
130131

131-
/** Retrieve a model and make it "live" for editing. */
132+
/** Create a new model in the backend.
133+
134+
Returns the ref ID of the created document.
135+
*/
136+
export async function createModel(api: Api, init?: ModelDocument): Promise<string> {
137+
if (init === undefined) {
138+
init = newModelDocument();
139+
}
140+
141+
const result = await api.rpc.new_ref.mutate({
142+
content: init as JsonValue,
143+
permissions: {
144+
anyone: "Read",
145+
},
146+
});
147+
invariant(result.tag === "Ok", "Failed to create model");
148+
149+
return result.content;
150+
}
151+
152+
/** Retrieve a model from the backend and make it "live" for editing. */
132153
export async function getLiveModel(
133154
refId: string,
134155
api: Api,

packages/frontend/src/model/model_editor.tsx

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import { useNavigate, useParams } from "@solidjs/router";
22
import { Match, Show, Switch, createResource, useContext } from "solid-js";
33
import invariant from "tiny-invariant";
44

5-
import type { JsonValue } from "catcolab-api";
6-
import { newModelAnalysisDocument } from "../analysis/document";
5+
import { createAnalysis } from "../analysis/document";
76
import { useApi } from "../api";
87
import { IconButton, InlineInput } from "../components";
9-
import { newDiagramDocument } from "../diagram";
8+
import { createDiagram } from "../diagram/document";
109
import {
1110
type CellConstructor,
1211
type FormalCellEditorProps,
@@ -56,33 +55,13 @@ export function ModelDocumentEditor(props: {
5655
const api = useApi();
5756
const navigate = useNavigate();
5857

59-
const createDiagram = async (modelRefId: string) => {
60-
const init = newDiagramDocument(modelRefId);
61-
62-
const result = await api.rpc.new_ref.mutate({
63-
content: init as JsonValue,
64-
permissions: {
65-
anyone: "Read",
66-
},
67-
});
68-
invariant(result.tag === "Ok", "Failed to create a new diagram");
69-
const newRef = result.content;
70-
58+
const onCreateDiagram = async (modelRefId: string) => {
59+
const newRef = await createDiagram(modelRefId, api);
7160
navigate(`/diagram/${newRef}`);
7261
};
7362

74-
const createAnalysis = async (modelRefId: string) => {
75-
const init = newModelAnalysisDocument(modelRefId);
76-
77-
const result = await api.rpc.new_ref.mutate({
78-
content: init as JsonValue,
79-
permissions: {
80-
anyone: "Read",
81-
},
82-
});
83-
invariant(result.tag === "Ok", "Failed to create a new analysis");
84-
const newRef = result.content;
85-
63+
const onCreateAnalysis = async (modelRefId: string) => {
64+
const newRef = await createAnalysis("model", modelRefId, api);
8665
navigate(`/analysis/${newRef}`);
8766
};
8867

@@ -93,14 +72,14 @@ export function ModelDocumentEditor(props: {
9372
<MaybePermissionsButton permissions={props.liveModel?.liveDoc.permissions} />
9473
<Show when={props.liveModel?.theory()?.supportsInstances}>
9574
<IconButton
96-
onClick={() => props.liveModel && createDiagram(props.liveModel.refId)}
75+
onClick={() => props.liveModel && onCreateDiagram(props.liveModel.refId)}
9776
tooltip="Create a diagram in this model"
9877
>
9978
<Network />
10079
</IconButton>
10180
</Show>
10281
<IconButton
103-
onClick={() => props.liveModel && createAnalysis(props.liveModel.refId)}
82+
onClick={() => props.liveModel && onCreateAnalysis(props.liveModel.refId)}
10483
tooltip="Analyze this model"
10584
>
10685
<ChartSpline />

0 commit comments

Comments
 (0)