Skip to content

Commit 622aba3

Browse files
hamidahoderinwaleepatters
authored andcommitted
Theory selection widget
1 parent 43e054a commit 622aba3

File tree

9 files changed

+203
-33
lines changed

9 files changed

+203
-33
lines changed

packages/frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@automerge/automerge-repo-network-websocket": "^1.2.1",
2323
"@automerge/automerge-repo-storage-indexeddb": "^1.2.1",
2424
"@automerge/prosemirror": "^0.0.13",
25+
"@corvu/dialog": "^0.2.3",
2526
"@corvu/disclosure": "^0.2.0",
2627
"@corvu/popover": "^0.2.0",
2728
"@corvu/resizable": "^0.2.2",

packages/frontend/pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/frontend/src/document/model_document_editor.tsx

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
import type { DocHandle } from "@automerge/automerge-repo";
2+
import Dialog from "@corvu/dialog";
23
import { MultiProvider } from "@solid-primitives/context";
34
import { useNavigate, useParams } from "@solidjs/router";
4-
import {
5-
type Accessor,
6-
For,
7-
Match,
8-
Switch,
9-
createMemo,
10-
createResource,
11-
useContext,
12-
} from "solid-js";
13-
import invariant from "tiny-invariant";
14-
155
import type { Uuid } from "catlog-wasm";
6+
import { type Accessor, Match, Switch, createMemo, createResource, useContext } from "solid-js";
7+
import invariant from "tiny-invariant";
168
import { RPCContext, RepoContext, retrieveDoc } from "../api";
179
import { IconButton, InlineInput } from "../components";
1810
import {
@@ -41,10 +33,11 @@ import { BrandedToolbar, HelpButton } from "../page";
4133
import { type TheoryLibrary, TheoryLibraryContext } from "../stdlib";
4234
import type { Theory } from "../theory";
4335
import { type IndexedMap, indexMap } from "../util/indexing";
36+
import TheorySelector from "./theory_selector";
4437
import { type ModelDocument, newAnalysisDocument } from "./types";
4538

4639
import "./model_document_editor.css";
47-
40+
import "./theory_selector.css";
4841
import ChartNetwork from "lucide-solid/icons/chart-network";
4942

5043
/** A model document "live" for editing.
@@ -225,26 +218,31 @@ export function ModelPane(props: {
225218
placeholder="Untitled"
226219
/>
227220
</div>
228-
<div class="model-theory">
229-
<select
230-
required
231-
disabled={doc().notebook.cells.some((cell) => cell.tag === "formal")}
232-
value={doc().theory ?? ""}
233-
onInput={(evt) => {
234-
const id = evt.target.value;
235-
docHandle().change((model) => {
236-
model.theory = id ? id : undefined;
237-
});
238-
}}
239-
>
240-
<option value="" disabled selected hidden>
241-
Choose a logic
242-
</option>
243-
<For each={Array.from(theories.metadata())}>
244-
{(meta) => <option value={meta.id}>{meta.name}</option>}
245-
</For>
246-
</select>
247-
</div>
221+
<Dialog
222+
initialOpen={false}
223+
modal={true}
224+
closeOnEscapeKeyDown={true}
225+
trapFocus={true}
226+
>
227+
<div>
228+
<Dialog.Trigger class="theory-selector">
229+
<span> {liveDoc().theory()?.name || "Theory"} </span>
230+
</Dialog.Trigger>
231+
</div>
232+
<Dialog.Portal>
233+
<div class="overlay">
234+
<Dialog.Content class="popup" id="theory-selector-popup">
235+
<span>
236+
<TheorySelector
237+
docHandle={docHandle}
238+
theories={theories}
239+
doc={doc()}
240+
/>
241+
</span>
242+
</Dialog.Content>
243+
</div>
244+
</Dialog.Portal>
245+
</Dialog>
248246
</div>
249247
<MultiProvider
250248
values={[
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
.theory-selector {
2+
text-transform: capitalize;
3+
border: none;
4+
font-size: 17px;
5+
padding: 16px;
6+
background-color: transparent;
7+
font-family: var(--main-font);
8+
cursor: pointer;
9+
font-weight: 600;
10+
opacity: 70%;
11+
}
12+
13+
.theory-selector:hover {
14+
color: var(--topos-color);
15+
}
16+
17+
.description {
18+
color: rgb(106, 106, 106);
19+
font-size: 11px;
20+
text-align: left;
21+
}
22+
23+
#input-selections input[type="radio"] {
24+
position: absolute;
25+
opacity: 0;
26+
}
27+
28+
#input-selections {
29+
display: flex;
30+
flex-direction: column;
31+
margin: 5px;
32+
background-color: transparent;
33+
text-align: left;
34+
border-top: transparent;
35+
border-left: transparent;
36+
min-height: 30vh;
37+
}
38+
39+
#selection-items:hover {
40+
color: var(--topos-color);
41+
cursor: pointer;
42+
}
43+
44+
ul {
45+
list-style-type: none;
46+
margin: 0;
47+
padding: 0;
48+
}
49+
50+
ul li {
51+
margin: 5px;
52+
padding: 6px;
53+
}
54+
55+
#division-category {
56+
font-weight: 600;
57+
padding-bottom: 1px;
58+
opacity: 35%;
59+
}
60+
61+
.overlay {
62+
position: absolute;
63+
top: 0;
64+
left: 0;
65+
right: 0;
66+
bottom: 0;
67+
background-color: rgba(0, 0, 0, 0.5);
68+
display: flex;
69+
justify-content: center;
70+
align-items: center;
71+
z-index: 1000;
72+
}
73+
74+
#theory-selector-popup {
75+
position: absolute;
76+
top: 50%;
77+
left: 50%;
78+
transform: translate(-50%, -50%);
79+
padding: 20px;
80+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { For, createMemo } from "solid-js";
2+
import type { TheoryLibrary } from "../stdlib/types";
3+
import type { ModelDocument } from "./types";
4+
import "./model_document_editor.css";
5+
import type { DocHandle } from "@automerge/automerge-repo";
6+
import type { TheoryMeta } from "../stdlib/types";
7+
import { Theory } from "../theory";
8+
9+
interface TheorySelectorProps {
10+
docHandle: DocHandle<TheorySelectorProps>;
11+
theories: TheoryLibrary;
12+
doc: ModelDocument;
13+
}
14+
15+
const TheorySelector = (props: TheorySelectorProps) => {
16+
const groupedTheories = createMemo(() => {
17+
const theories = Array.from(props.theories.metadata()).filter(
18+
(meta) => meta.divisionCategory,
19+
);
20+
const grouped = new Map<string, TheoryMeta[]>();
21+
22+
for (const theory of theories) {
23+
const category = theory.divisionCategory ?? "Other";
24+
grouped.set(category, [...(grouped.get(category) || []), theory]);
25+
}
26+
27+
return Array.from(grouped.entries()).sort((a, b) => a[0].localeCompare(b[0]));
28+
});
29+
30+
return (
31+
<div id="input-selections">
32+
<For each={groupedTheories()}>
33+
{([category, theories]) => (
34+
<div class="selection-items">
35+
<h4 id="division-category">{category}</h4>
36+
<For each={theories}>
37+
{(meta) => (
38+
<label>
39+
<input
40+
type="radio"
41+
name="theory"
42+
value={meta.id}
43+
onchange={(evt) => {
44+
const id = (evt.target as HTMLInputElement).value;
45+
props.docHandle().change(
46+
(model: {
47+
theory: string | undefined;
48+
}) => {
49+
model.theory = id ? id : undefined;
50+
},
51+
);
52+
}}
53+
/>
54+
<div>
55+
<ul>
56+
<li id="selection-items">
57+
{meta.name}{" "}
58+
<div>
59+
<span class="description">
60+
{meta.description}
61+
</span>
62+
</div>
63+
</li>
64+
</ul>
65+
</div>
66+
</label>
67+
)}
68+
</For>
69+
</div>
70+
)}
71+
</For>
72+
</div>
73+
);
74+
};
75+
export default TheorySelector;

packages/frontend/src/index.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
--mono-font: Roboto Mono, monospace;
44

55
--main-color: black;
6+
--topos-color: #53b6b2;
67

78
--h1-font-size: 3em;
89
--h2-font-size: 2em;
@@ -60,6 +61,7 @@ h3 {
6061
border-radius: 6px;
6162
box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px,
6263
rgba(15, 15, 15, 0.2) 0px 9px 24px;
64+
overflow-y: auto;
6365
}
6466

6567
.growable-container {

packages/frontend/src/notebook/notebook_cell.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export function NotebookCell(props: {
178178
</IconButton>
179179
</Popover.Anchor>
180180
<Popover.Portal>
181-
<Popover.Content class="popup">
181+
<Popover.Content class="selector-popup">
182182
<Completions completions={completions()} onComplete={closeMenu} />
183183
</Popover.Content>
184184
</Popover.Portal>

packages/frontend/src/stdlib/theories.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ stdTheories.add(
2020
id: "simple-olog",
2121
name: "Olog",
2222
description: "Ontology log, a simple conceptual model",
23+
divisionCategory: "Knowledge and Data",
2324
},
2425
(meta) => {
2526
const thCategory = new catlog.ThCategory();
@@ -63,6 +64,7 @@ stdTheories.add(
6364
id: "schema",
6465
name: "Schema",
6566
description: "Schema for a categorical database",
67+
divisionCategory: "Knowledge and Data",
6668
},
6769
(meta) => {
6870
const thSchema = new catlog.ThSchema();
@@ -132,6 +134,8 @@ stdTheories.add(
132134
{
133135
id: "reg-net",
134136
name: "Regulatory network",
137+
description: "Signed graphs to model networks",
138+
divisionCategory: "Life Sciences",
135139
},
136140
(meta) => {
137141
const thSignedCategory = new catlog.ThSignedCategory();
@@ -198,6 +202,8 @@ stdTheories.add(
198202
{
199203
id: "causal-loop",
200204
name: "Causal loop diagram",
205+
description: "Model cause-and-effect relationships",
206+
divisionCategory: "System Dynamics",
201207
},
202208
(meta) => {
203209
const thSignedCategory = new catlog.ThSignedCategory();
@@ -266,6 +272,8 @@ stdTheories.add(
266272
{
267273
id: "stock-flow",
268274
name: "Stock and flow",
275+
description: "Model accumulation (stocks) and change (flows)",
276+
divisionCategory: "System Dynamics",
269277
},
270278
(meta) => {
271279
const thCategoryLinks = new catlog.ThCategoryLinks();

packages/frontend/src/stdlib/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export type TheoryMeta = {
1414

1515
/** Short description of models of theory. */
1616
description?: string;
17+
18+
/** division Category */
19+
divisionCategory?: string;
1720
};
1821

1922
/** Library of double theories configured for the frontend.

0 commit comments

Comments
 (0)