diff --git a/apps/roam/src/components/QueryBuilder.tsx b/apps/roam/src/components/QueryBuilder.tsx index 20b5cbf47..ac7fd1897 100644 --- a/apps/roam/src/components/QueryBuilder.tsx +++ b/apps/roam/src/components/QueryBuilder.tsx @@ -32,6 +32,8 @@ type QueryPageComponent = (props: { isEditBlock?: boolean; showAlias?: boolean; discourseNodeType?: string; + settingKey?: "index" | "specification"; + returnNode?: string; }) => JSX.Element; type Props = Parameters[0]; @@ -41,6 +43,8 @@ const QueryBuilder = ({ isEditBlock, showAlias, discourseNodeType, + settingKey, + returnNode, }: Props) => { const extensionAPI = useExtensionAPI(); const hideMetadata = useMemo( @@ -165,6 +169,8 @@ const QueryBuilder = ({ { setHasResults(true); setIsEdit(false); diff --git a/apps/roam/src/components/QueryEditor.tsx b/apps/roam/src/components/QueryEditor.tsx index a47a3198d..b739af92a 100644 --- a/apps/roam/src/components/QueryEditor.tsx +++ b/apps/roam/src/components/QueryEditor.tsx @@ -437,6 +437,8 @@ type QueryEditorComponent = (props: { hideCustomSwitch?: boolean; showAlias?: boolean; discourseNodeType?: string; + settingKey?: "index" | "specification"; + returnNode?: string; }) => JSX.Element; const QueryEditor: QueryEditorComponent = ({ @@ -446,6 +448,8 @@ const QueryEditor: QueryEditorComponent = ({ hideCustomSwitch, showAlias, discourseNodeType, + settingKey, + returnNode, }) => { useEffect(() => { const previewQuery = ((e: CustomEvent) => { @@ -487,11 +491,12 @@ const QueryEditor: QueryEditorComponent = ({ return () => window.clearTimeout(blockPropSyncTimeoutRef.current); }, []); useEffect(() => { - if (!discourseNodeType) return; + if (!discourseNodeType || !settingKey) return; const stripped: unknown = JSON.parse( - JSON.stringify({ conditions, selections, custom }, (key, value: unknown) => - key === "uid" ? undefined : value, + JSON.stringify( + { conditions, selections, custom, returnNode }, + (key, value: unknown) => (key === "uid" ? undefined : value), ), ); @@ -500,18 +505,28 @@ const QueryEditor: QueryEditorComponent = ({ const result = IndexSchema.safeParse(stripped); if (!result.success) { - console.error("Index blockprop sync failed validation:", result.error); + console.error(`${settingKey} blockprop sync failed validation:`, result.error); return; } + const path = + settingKey === "index" ? ["index"] : ["specification", "query"]; + window.clearTimeout(blockPropSyncTimeoutRef.current); blockPropSyncTimeoutRef.current = window.setTimeout(() => { - setDiscourseNodeSetting(discourseNodeType, ["index"], result.data); + setDiscourseNodeSetting(discourseNodeType, path, result.data); lastSyncedIndexRef.current = serialized; }, 250); return () => window.clearTimeout(blockPropSyncTimeoutRef.current); - }, [conditions, selections, custom, discourseNodeType]); + }, [ + conditions, + selections, + custom, + discourseNodeType, + settingKey, + returnNode, + ]); const customNodeOnChange = (value: string) => { window.clearTimeout(debounceRef.current); diff --git a/apps/roam/src/components/settings/DiscourseNodeIndex.tsx b/apps/roam/src/components/settings/DiscourseNodeIndex.tsx index ad1b0a40e..38717ade2 100644 --- a/apps/roam/src/components/settings/DiscourseNodeIndex.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeIndex.tsx @@ -60,6 +60,8 @@ const NodeIndex = ({ }, ], selections: [], + custom: "", + returnNode: DEFAULT_RETURN_NODE, }); setShowQuery(true); @@ -69,7 +71,12 @@ const NodeIndex = ({ return ( {showQuery ? ( - + ) : ( )} diff --git a/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx b/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx index 5f2c7332f..8bfac4954 100644 --- a/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeSpecification.tsx @@ -1,7 +1,6 @@ import React from "react"; import getSubTree from "roamjs-components/util/getSubTree"; import createBlock from "roamjs-components/writes/createBlock"; -import { Checkbox } from "@blueprintjs/core"; import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; import deleteBlock from "roamjs-components/writes/deleteBlock"; import refreshConfigTree from "~/utils/refreshConfigTree"; @@ -9,6 +8,8 @@ import getDiscourseNodes from "~/utils/getDiscourseNodes"; import getDiscourseNodeFormatExpression from "~/utils/getDiscourseNodeFormatExpression"; import QueryEditor from "~/components/QueryEditor"; import internalError from "~/utils/internalError"; +import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors"; +import { DiscourseNodeFlagPanel } from "~/components/settings/components/BlockPropSettingPanels"; const NodeSpecification = ({ parentUid, @@ -20,11 +21,14 @@ const NodeSpecification = ({ parentSetEnabled?: (enabled: boolean) => void; }) => { const [migrated, setMigrated] = React.useState(false); - const [enabled, setEnabled] = React.useState( + const enabledBlockUid = React.useMemo( () => getSubTree({ tree: getBasicTreeByParentUid(parentUid), key: "enabled" }) ?.uid, + [parentUid], ); + const [enabled, setEnabled] = React.useState(!!enabledBlockUid); + React.useEffect(() => { if (enabled) { const scratchNode = getSubTree({ parentUid, key: "scratch" }); @@ -69,7 +73,22 @@ const NodeSpecification = ({ }, }), ) - .then(() => setMigrated(true)) + .then(() => { + setDiscourseNodeSetting(node.type, ["specification", "query"], { + conditions: [ + { + type: "clause" as const, + source: node.text, + relation: "has title", + target: `/${getDiscourseNodeFormatExpression(node.format).source}/`, + }, + ], + selections: [], + custom: "", + returnNode: node.text, + }); + setMigrated(true); + }) .catch((error) => { internalError({ error }); }); @@ -77,11 +96,18 @@ const NodeSpecification = ({ } else { const tree = getBasicTreeByParentUid(parentUid); const scratchNode = getSubTree({ tree, key: "scratch" }); - Promise.all(scratchNode.children.map((c) => deleteBlock(c.uid))).catch( - (error) => { + Promise.all(scratchNode.children.map((c) => deleteBlock(c.uid))) + .then(() => { + setDiscourseNodeSetting(node.type, ["specification", "query"], { + conditions: [], + selections: [], + custom: "", + returnNode: "", + }); + }) + .catch((error) => { internalError({ error }); - }, - ); + }); } return () => { refreshConfigTree(); @@ -90,40 +116,24 @@ const NodeSpecification = ({ return (
-

- { - const flag = (e.target as HTMLInputElement).checked; - if (flag) { - createBlock({ - parentUid, - order: 2, - node: { text: "enabled" }, - }) - .then((uid: string) => { - setEnabled(uid); - if (parentSetEnabled) parentSetEnabled(true); - }) - .catch((error) => { - internalError({ error }); - }); - } else { - deleteBlock(enabled) - .then(() => { - setEnabled(""); - if (parentSetEnabled) parentSetEnabled(false); - }) - .catch((error) => { - internalError({ error }); - }); - } - }} - /> -

+ { + setEnabled(checked); + parentSetEnabled?.(checked); + }} + />
@@ -131,6 +141,9 @@ const NodeSpecification = ({ parentUid={parentUid} key={Number(migrated)} hideCustomSwitch + discourseNodeType={node.type} + settingKey="specification" + returnNode={node.text} />
diff --git a/apps/roam/src/components/settings/utils/zodSchema.example.ts b/apps/roam/src/components/settings/utils/zodSchema.example.ts index d72b6b7c0..b8c2d04f6 100644 --- a/apps/roam/src/components/settings/utils/zodSchema.example.ts +++ b/apps/roam/src/components/settings/utils/zodSchema.example.ts @@ -45,14 +45,22 @@ const discourseNodeSettings: DiscourseNodeSettings = { shortcut: "C", tag: "#claim", description: "A statement or assertion that can be supported or refuted", - specification: [ - { - type: "clause", - source: "Claim", - relation: "has title", - target: "/^\\[\\[CLM\\]\\]/", + specification: { + enabled: true, + query: { + conditions: [ + { + type: "clause", + source: "Claim", + relation: "has title", + target: "/^\\[\\[CLM\\]\\]/", + }, + ], + selections: [], + custom: "", + returnNode: "Claim", }, - ], + }, template: [ { text: "Summary::", heading: 2 }, { text: "Evidence::", heading: 2, children: [{ text: "" }] }, @@ -76,6 +84,7 @@ const discourseNodeSettings: DiscourseNodeSettings = { ], selections: [], custom: "", + returnNode: "node", }, suggestiveRules, backedBy: "user", diff --git a/apps/roam/src/components/settings/utils/zodSchema.ts b/apps/roam/src/components/settings/utils/zodSchema.ts index 5e49a1bc3..50ced8e18 100644 --- a/apps/roam/src/components/settings/utils/zodSchema.ts +++ b/apps/roam/src/components/settings/utils/zodSchema.ts @@ -53,6 +53,7 @@ export const IndexSchema = z.object({ conditions: z.array(ConditionSchema).default([]), selections: z.array(SelectionSchema).default([]), custom: z.string().default(""), + returnNode: z.string().default("node"), }); type RoamNode = { @@ -103,10 +104,13 @@ export const DiscourseNodeSchema = z.object({ tag: stringWithDefault(""), description: stringWithDefault(""), specification: z - .array(ConditionSchema) + .object({ + enabled: z.boolean().default(false), + query: IndexSchema.default({}), + }) .nullable() .optional() - .transform((val) => val ?? []), + .transform((val) => val ?? { enabled: false, query: { conditions: [], selections: [], custom: "", returnNode: "" } }), template: z .array(RoamNodeSchema) .nullable()