Skip to content

Commit a9a2fd0

Browse files
committed
query builder port
1 parent f2c0787 commit a9a2fd0

5 files changed

Lines changed: 70 additions & 5 deletions

File tree

apps/roam/src/components/QueryBuilder.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@ type QueryPageComponent = (props: {
3131
pageUid: string;
3232
isEditBlock?: boolean;
3333
showAlias?: boolean;
34+
discourseNodeType?: string;
3435
}) => JSX.Element;
3536

3637
type Props = Parameters<QueryPageComponent>[0];
3738

38-
const QueryBuilder = ({ pageUid, isEditBlock, showAlias }: Props) => {
39+
const QueryBuilder = ({
40+
pageUid,
41+
isEditBlock,
42+
showAlias,
43+
discourseNodeType,
44+
}: Props) => {
3945
const extensionAPI = useExtensionAPI();
4046
const hideMetadata = useMemo(
4147
() =>
@@ -158,6 +164,7 @@ const QueryBuilder = ({ pageUid, isEditBlock, showAlias }: Props) => {
158164
<>
159165
<QueryEditor
160166
parentUid={pageUid}
167+
discourseNodeType={discourseNodeType}
161168
onQuery={() => {
162169
setHasResults(true);
163170
setIsEdit(false);

apps/roam/src/components/QueryEditor.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ import {
4444
import getShallowTreeByParentUid from "roamjs-components/queries/getShallowTreeByParentUid";
4545
import { ALL_SELECTION_SUGGESTIONS } from "~/utils/predefinedSelections";
4646
import { getAlias } from "~/utils/parseResultSettings";
47+
import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors";
48+
import { IndexSchema } from "~/components/settings/utils/zodSchema";
4749

4850
const getSourceCandidates = (cs: Condition[]): string[] =>
4951
cs.flatMap((c) =>
@@ -434,6 +436,7 @@ type QueryEditorComponent = (props: {
434436
setHasResults?: () => void;
435437
hideCustomSwitch?: boolean;
436438
showAlias?: boolean;
439+
discourseNodeType?: string;
437440
}) => JSX.Element;
438441

439442
const QueryEditor: QueryEditorComponent = ({
@@ -442,6 +445,7 @@ const QueryEditor: QueryEditorComponent = ({
442445
setHasResults,
443446
hideCustomSwitch,
444447
showAlias,
448+
discourseNodeType,
445449
}) => {
446450
useEffect(() => {
447451
const previewQuery = ((e: CustomEvent) => {
@@ -476,6 +480,39 @@ const QueryEditor: QueryEditorComponent = ({
476480
const [conditions, _setConditions] = useState(initialConditions);
477481
const [selections, setSelections] = useState(initialSelections);
478482
const [custom, setCustom] = useState(initialCustom);
483+
484+
const blockPropSyncTimeoutRef = useRef(0);
485+
const lastSyncedIndexRef = useRef("");
486+
useEffect(() => {
487+
return () => window.clearTimeout(blockPropSyncTimeoutRef.current);
488+
}, []);
489+
useEffect(() => {
490+
if (!discourseNodeType) return;
491+
492+
const stripped: unknown = JSON.parse(
493+
JSON.stringify({ conditions, selections, custom }, (key, value: unknown) =>
494+
key === "uid" ? undefined : value,
495+
),
496+
);
497+
498+
const serialized = JSON.stringify(stripped);
499+
if (serialized === lastSyncedIndexRef.current) return;
500+
501+
const result = IndexSchema.safeParse(stripped);
502+
if (!result.success) {
503+
console.error("Index blockprop sync failed validation:", result.error);
504+
return;
505+
}
506+
507+
window.clearTimeout(blockPropSyncTimeoutRef.current);
508+
blockPropSyncTimeoutRef.current = window.setTimeout(() => {
509+
setDiscourseNodeSetting(discourseNodeType, ["index"], result.data);
510+
lastSyncedIndexRef.current = serialized;
511+
}, 500);
512+
513+
return () => window.clearTimeout(blockPropSyncTimeoutRef.current);
514+
}, [conditions, selections, custom, discourseNodeType]);
515+
479516
const customNodeOnChange = (value: string) => {
480517
window.clearTimeout(debounceRef.current);
481518
setCustom(value);

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { DiscourseNode } from "~/utils/getDiscourseNodes";
66
import QueryBuilder from "~/components/QueryBuilder";
77
import parseQuery, { DEFAULT_RETURN_NODE } from "~/utils/parseQuery";
88
import createBlock from "roamjs-components/writes/createBlock";
9+
import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors";
910

1011
const NodeIndex = ({
1112
parentUid,
@@ -25,7 +26,7 @@ const NodeIndex = ({
2526
);
2627
useEffect(() => {
2728
if (!showQuery) {
28-
createBlock({
29+
void createBlock({
2930
parentUid: initialQueryArgs.conditionsNodesUid,
3031
node: {
3132
text: "clause",
@@ -48,12 +49,30 @@ const NodeIndex = ({
4849
},
4950
],
5051
},
51-
}).then(() => setShowQuery(true));
52+
}).then(() => {
53+
setDiscourseNodeSetting(node.type, ["index"], {
54+
conditions: [
55+
{
56+
type: "clause",
57+
source: DEFAULT_RETURN_NODE,
58+
relation: "is a",
59+
target: node.text,
60+
},
61+
],
62+
selections: [],
63+
});
64+
65+
setShowQuery(true);
66+
});
5267
}
53-
}, [parentUid, initialQueryArgs, showQuery]);
68+
}, [parentUid, initialQueryArgs, showQuery, node.text, node.type]);
5469
return (
5570
<ExtensionApiContextProvider {...onloadArgs}>
56-
{showQuery ? <QueryBuilder pageUid={parentUid} /> : <Spinner />}
71+
{showQuery ? (
72+
<QueryBuilder pageUid={parentUid} discourseNodeType={node.type} />
73+
) : (
74+
<Spinner />
75+
)}
5776
</ExtensionApiContextProvider>
5877
);
5978
};

apps/roam/src/components/settings/utils/zodSchema.example.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const discourseNodeSettings: DiscourseNodeSettings = {
7575
},
7676
],
7777
selections: [],
78+
custom: "",
7879
},
7980
suggestiveRules,
8081
backedBy: "user",

apps/roam/src/components/settings/utils/zodSchema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export const SelectionSchema = z.object({
5252
export const IndexSchema = z.object({
5353
conditions: z.array(ConditionSchema).default([]),
5454
selections: z.array(SelectionSchema).default([]),
55+
custom: z.string().default(""),
5556
});
5657

5758
type RoamNode = {

0 commit comments

Comments
 (0)