Skip to content

Commit acce7e3

Browse files
committed
migrate discourseNodeIndex, create custom query editor, update zod
1 parent d549f8d commit acce7e3

File tree

7 files changed

+793
-156
lines changed

7 files changed

+793
-156
lines changed
Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,9 @@
1-
import React, { useEffect } from "react";
2-
import { Spinner } from "@blueprintjs/core";
3-
import ExtensionApiContextProvider from "roamjs-components/components/ExtensionApiContext";
4-
import type { OnloadArgs } from "roamjs-components/types/native";
1+
import React from "react";
52
import type { DiscourseNode } from "~/utils/getDiscourseNodes";
6-
import QueryBuilder from "~/components/QueryBuilder";
7-
import parseQuery, { DEFAULT_RETURN_NODE } from "~/utils/parseQuery";
8-
import createBlock from "roamjs-components/writes/createBlock";
3+
import DiscourseNodeQueryBuilder from "./components/DiscourseNodeQueryBuilder";
94

10-
const NodeIndex = ({
11-
parentUid,
12-
node,
13-
onloadArgs,
14-
}: {
15-
parentUid: string;
16-
node: DiscourseNode;
17-
onloadArgs: OnloadArgs;
18-
}) => {
19-
const initialQueryArgs = React.useMemo(
20-
() => parseQuery(parentUid),
21-
[parentUid],
22-
);
23-
const [showQuery, setShowQuery] = React.useState(
24-
!!initialQueryArgs.conditions.length,
25-
);
26-
useEffect(() => {
27-
if (!showQuery) {
28-
createBlock({
29-
parentUid: initialQueryArgs.conditionsNodesUid,
30-
node: {
31-
text: "clause",
32-
children: [
33-
{
34-
text: "source",
35-
children: [{ text: DEFAULT_RETURN_NODE }],
36-
},
37-
{
38-
text: "relation",
39-
children: [{ text: "is a" }],
40-
},
41-
{
42-
text: "target",
43-
children: [
44-
{
45-
text: node.text,
46-
},
47-
],
48-
},
49-
],
50-
},
51-
}).then(() => setShowQuery(true));
52-
}
53-
}, [parentUid, initialQueryArgs, showQuery]);
54-
return (
55-
<ExtensionApiContextProvider {...onloadArgs}>
56-
{showQuery ? <QueryBuilder pageUid={parentUid} /> : <Spinner />}
57-
</ExtensionApiContextProvider>
58-
);
5+
const NodeIndex = ({ node }: { node: DiscourseNode }) => {
6+
return <DiscourseNodeQueryBuilder nodeType={node.type} nodeText={node.text} />;
597
};
608

619
export default NodeIndex;

apps/roam/src/components/settings/DiscourseNodeSpecification.tsx

Lines changed: 59 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,85 @@
11
import React from "react";
2-
import getSubTree from "roamjs-components/util/getSubTree";
3-
import createBlock from "roamjs-components/writes/createBlock";
42
import { Checkbox } from "@blueprintjs/core";
5-
import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid";
6-
import deleteBlock from "roamjs-components/writes/deleteBlock";
73
import getDiscourseNodes from "~/utils/getDiscourseNodes";
84
import getDiscourseNodeFormatExpression from "~/utils/getDiscourseNodeFormatExpression";
9-
import QueryEditor from "~/components/QueryEditor";
5+
import DiscourseNodeQueryEditor from "./components/DiscourseNodeQueryEditor";
6+
import {
7+
getDiscourseNodeSetting,
8+
setDiscourseNodeSetting,
9+
} from "./utils/accessors";
10+
import type { Condition } from "~/utils/types";
11+
12+
const generateUID = (): string =>
13+
window.roamAlphaAPI?.util?.generateUID?.() ??
14+
Math.random().toString(36).substring(2, 11);
1015

1116
const NodeSpecification = ({
12-
parentUid,
1317
node,
1418
}: {
15-
parentUid: string;
1619
node: ReturnType<typeof getDiscourseNodes>[number];
1720
}) => {
18-
const [migrated, setMigrated] = React.useState(false);
19-
const [enabled, setEnabled] = React.useState(
20-
() =>
21-
getSubTree({ tree: getBasicTreeByParentUid(parentUid), key: "enabled" })
22-
?.uid,
23-
);
24-
React.useEffect(() => {
25-
if (enabled) {
26-
const scratchNode = getSubTree({ parentUid, key: "scratch" });
27-
if (
28-
!scratchNode.children.length ||
29-
!getSubTree({ tree: scratchNode.children, key: "conditions" }).children
30-
.length
31-
) {
32-
const conditionsUid = getSubTree({
33-
parentUid: scratchNode.uid,
34-
key: "conditions",
35-
}).uid;
36-
const returnUid = getSubTree({
37-
parentUid: scratchNode.uid,
38-
key: "return",
39-
}).uid;
40-
createBlock({
41-
parentUid: returnUid,
42-
node: {
43-
text: node.text,
44-
},
45-
})
46-
.then(() =>
47-
createBlock({
48-
parentUid: conditionsUid,
49-
node: {
50-
text: "clause",
51-
children: [
52-
{ text: "source", children: [{ text: node.text }] },
53-
{ text: "relation", children: [{ text: "has title" }] },
54-
{
55-
text: "target",
56-
children: [
57-
{
58-
text: `/${
59-
getDiscourseNodeFormatExpression(node.format).source
60-
}/`,
61-
},
62-
],
63-
},
64-
],
65-
},
66-
}),
67-
)
68-
.then(() => setMigrated(true));
21+
const nodeType = node.type;
22+
23+
const [enabled, setEnabled] = React.useState(() => {
24+
const spec = getDiscourseNodeSetting<Condition[]>(nodeType, [
25+
"specification",
26+
]);
27+
return spec !== null && spec !== undefined && spec.length > 0;
28+
});
29+
30+
const createInitialCondition = React.useCallback((): Condition => {
31+
return {
32+
uid: generateUID(),
33+
type: "clause",
34+
source: node.text,
35+
relation: "has title",
36+
target: `/${getDiscourseNodeFormatExpression(node.format).source}/`,
37+
};
38+
}, [node.text, node.format]);
39+
40+
const handleEnabledChange = React.useCallback(
41+
(e: React.FormEvent<HTMLInputElement>) => {
42+
const flag = (e.target as HTMLInputElement).checked;
43+
setEnabled(flag);
44+
45+
if (flag) {
46+
// Create initial condition when enabling
47+
const existingSpec = getDiscourseNodeSetting<Condition[]>(nodeType, [
48+
"specification",
49+
]);
50+
if (!existingSpec || existingSpec.length === 0) {
51+
const initialCondition = createInitialCondition();
52+
setDiscourseNodeSetting(nodeType, ["specification"], [
53+
initialCondition,
54+
]);
55+
}
56+
} else {
57+
// Clear specification when disabling
58+
setDiscourseNodeSetting(nodeType, ["specification"], []);
6959
}
70-
} else {
71-
const tree = getBasicTreeByParentUid(parentUid);
72-
const scratchNode = getSubTree({ tree, key: "scratch" });
73-
Promise.all(scratchNode.children.map((c) => deleteBlock(c.uid)));
74-
}
75-
}, [parentUid, setMigrated, enabled]);
60+
},
61+
[nodeType, createInitialCondition],
62+
);
63+
7664
return (
7765
<div className={"roamjs-node-specification"}>
7866
<style>
7967
{`.roamjs-node-specification .bp3-button.bp3-intent-primary { display: none; }`}
8068
</style>
8169
<p>
8270
<Checkbox
83-
checked={!!enabled}
71+
checked={enabled}
8472
className={"ml-8 inline-block"}
85-
onChange={(e) => {
86-
const flag = (e.target as HTMLInputElement).checked;
87-
if (flag) {
88-
createBlock({
89-
parentUid,
90-
order: 2,
91-
node: { text: "enabled" },
92-
}).then(setEnabled);
93-
} else {
94-
deleteBlock(enabled).then(() => setEnabled(""));
95-
}
96-
}}
73+
onChange={handleEnabledChange}
9774
/>
9875
</p>
9976
<div
100-
className={`${enabled ? "" : "bg-gray-200 opacity-75"} overflow-auto`}
77+
className={`${enabled ? "" : "bg-gray-200 opacity-75 pointer-events-none"} overflow-auto`}
10178
>
102-
<QueryEditor
103-
parentUid={parentUid}
104-
key={Number(migrated)}
105-
hideCustomSwitch
79+
<DiscourseNodeQueryEditor
80+
nodeType={nodeType}
81+
defaultConditions={enabled ? [createInitialCondition()] : []}
82+
key={String(enabled)}
10683
/>
10784
</div>
10885
</div>

apps/roam/src/components/settings/NodeConfig.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,13 @@ const NodeConfig = ({
164164
onloadArgs: OnloadArgs;
165165
}) => {
166166
const suggestiveModeEnabled = useFeatureFlag("Suggestive Mode Enabled");
167-
// UIDs still needed for deferred complex settings (template, specification, etc.)
167+
// UIDs still needed for deferred complex settings (template)
168168
const getUid = (key: string) =>
169169
getSubTree({
170170
parentUid: node.type,
171171
key: key,
172172
}).uid;
173173
const templateUid = getUid("Template");
174-
const specificationUid = getUid("Specification");
175-
const indexUid = getUid("Index");
176174

177175
const [selectedTabId, setSelectedTabId] = useState<TabId>("general");
178176
const [tagError, setTagError] = useState("");
@@ -301,11 +299,7 @@ const NodeConfig = ({
301299
title="Index"
302300
panel={
303301
<div className="flex flex-col gap-4 p-1">
304-
<DiscourseNodeIndex
305-
node={node}
306-
parentUid={indexUid}
307-
onloadArgs={onloadArgs}
308-
/>
302+
<DiscourseNodeIndex node={node} />
309303
</div>
310304
}
311305
/>
@@ -329,10 +323,7 @@ const NodeConfig = ({
329323
"The conditions specified to identify a ${nodeText} node."
330324
}
331325
/>
332-
<DiscourseNodeSpecification
333-
node={node}
334-
parentUid={specificationUid}
335-
/>
326+
<DiscourseNodeSpecification node={node} />
336327
</Label>
337328
</div>
338329
}

0 commit comments

Comments
 (0)