From 9046f4a9d3df5f3fc2dce2ecf6697f8dae21c369 Mon Sep 17 00:00:00 2001 From: sid597 Date: Sat, 21 Feb 2026 02:40:25 +0530 Subject: [PATCH 1/9] ENG-1328: Port small blueprint based misc settings into props based --- .../src/components/settings/AdminPanel.tsx | 4 ++ .../settings/DiscourseNodeCanvasSettings.tsx | 47 ++++++++++--------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/apps/roam/src/components/settings/AdminPanel.tsx b/apps/roam/src/components/settings/AdminPanel.tsx index 6606cf20e..85ba13269 100644 --- a/apps/roam/src/components/settings/AdminPanel.tsx +++ b/apps/roam/src/components/settings/AdminPanel.tsx @@ -38,6 +38,7 @@ import createBlock from "roamjs-components/writes/createBlock"; import deleteBlock from "roamjs-components/writes/deleteBlock"; import { USE_REIFIED_RELATIONS } from "~/data/userSettings"; import posthog from "posthog-js"; +import { setFeatureFlag } from "~/components/settings/utils/accessors"; const NodeRow = ({ node }: { node: PConceptFull }) => { return ( @@ -377,6 +378,7 @@ const FeatureFlagsTab = (): React.ReactElement => { setSuggestiveModeUid(undefined); } setSuggestiveModeEnabled(false); + setFeatureFlag("Suggestive mode enabled", false); } }} labelElement={ @@ -399,6 +401,7 @@ const FeatureFlagsTab = (): React.ReactElement => { }).then((uid) => { setSuggestiveModeUid(uid); setSuggestiveModeEnabled(true); + setFeatureFlag("Suggestive mode enabled", true); setIsAlertOpen(false); setIsInstructionOpen(true); }); @@ -447,6 +450,7 @@ const FeatureFlagsTab = (): React.ReactElement => { void setSetting(USE_REIFIED_RELATIONS, target.checked).catch( () => undefined, ); + setFeatureFlag("Reified relation triples", target.checked); posthog.capture("Reified Relations: Toggled", { enabled: target.checked, }); diff --git a/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx b/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx index ebc47d1ad..371429ef9 100644 --- a/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx @@ -11,7 +11,8 @@ import React, { useState, useMemo } from "react"; import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; import getSettingValueFromTree from "roamjs-components/util/getSettingValueFromTree"; import setInputSetting from "roamjs-components/util/setInputSetting"; -import { DiscourseNodeFlagPanel } from "./components/BlockPropSettingPanels"; +import { DiscourseNodeFlagPanel, DiscourseNodeTextPanel } from "./components/BlockPropSettingPanels"; +import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors"; export const formatHexColor = (color: string) => { if (!color) return ""; @@ -37,9 +38,7 @@ const DiscourseNodeCanvasSettings = ({ const color = getSettingValueFromTree({ tree, key: "color" }); return formatHexColor(color); }); - const [alias, setAlias] = useState(() => - getSettingValueFromTree({ tree, key: "alias" }), - ); + const alias = getSettingValueFromTree({ tree, key: "alias" }); const [queryBuilderAlias, setQueryBuilderAlias] = useState(() => getSettingValueFromTree({ tree, key: "query-builder-alias" }), ); @@ -60,12 +59,14 @@ const DiscourseNodeCanvasSettings = ({ type={"color"} value={color} onChange={(e) => { + const colorValue = e.target.value.replace("#", ""); // remove hash to not create roam link setColor(e.target.value); void setInputSetting({ blockUid: uid, key: "color", - value: e.target.value.replace("#", ""), // remove hash to not create roam link + value: colorValue, }); + setDiscourseNodeSetting(nodeType, ["canvasSettings", "color"], colorValue); }} /> @@ -79,25 +80,26 @@ const DiscourseNodeCanvasSettings = ({ key: "color", value: "", }); + setDiscourseNodeSetting(nodeType, ["canvasSettings", "color"], ""); }} /> - + { + void setInputSetting({ + blockUid: uid, + key: "alias", + value: val, + }); + }} + /> @@ -145,12 +148,14 @@ const DiscourseNodeCanvasSettings = ({ disabled={keyImageOption !== "query-builder" || !isKeyImage} value={queryBuilderAlias} onChange={(e) => { - setQueryBuilderAlias(e.target.value); + const val = e.target.value; + setQueryBuilderAlias(val); void setInputSetting({ blockUid: uid, key: "query-builder-alias", - value: e.target.value, + value: val, }); + setDiscourseNodeSetting(nodeType, ["canvasSettings", "query-builder-alias"], val); }} /> From fb51d4afd33039c09f584a2bd59302b7bfda8d9d Mon Sep 17 00:00:00 2001 From: sid597 Date: Sat, 21 Feb 2026 02:44:05 +0530 Subject: [PATCH 2/9] attributes -> overlay --- apps/roam/src/components/settings/NodeConfig.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/roam/src/components/settings/NodeConfig.tsx b/apps/roam/src/components/settings/NodeConfig.tsx index 0c0e5ff7d..dea52eb60 100644 --- a/apps/roam/src/components/settings/NodeConfig.tsx +++ b/apps/roam/src/components/settings/NodeConfig.tsx @@ -25,6 +25,7 @@ import refreshConfigTree from "~/utils/refreshConfigTree"; import { DiscourseNodeTextPanel, DiscourseNodeFlagPanel, + DiscourseNodeSelectPanel, } from "./components/BlockPropSettingPanels"; const TEMPLATE_SETTING_KEYS = ["template"]; @@ -360,15 +361,16 @@ const NodeConfig = ({ panel={
- c.text)} + initialValue={getBasicTreeByParentUid(overlayUid)[0]?.text} order={0} parentUid={node.type} uid={overlayUid} - options={{ - items: () => attributeNode.children.map((c) => c.text), - }} />
} From 1c6b6aa7af67032e8b6187693d12d98b87a72fc8 Mon Sep 17 00:00:00 2001 From: sid597 Date: Sat, 21 Feb 2026 02:46:54 +0530 Subject: [PATCH 3/9] attributes label --- .../settings/DiscourseNodeAttributes.tsx | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx index a1d6f2fb5..a20c16d2a 100644 --- a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx @@ -5,6 +5,7 @@ import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByPar import getFirstChildUidByBlockUid from "roamjs-components/queries/getFirstChildUidByBlockUid"; import updateBlock from "roamjs-components/writes/updateBlock"; import deleteBlock from "roamjs-components/writes/deleteBlock"; +import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors"; type Attribute = { uid: string; @@ -18,7 +19,12 @@ const NodeAttribute = ({ value, onChange, onDelete, -}: Attribute & { onChange: (v: string) => void; onDelete: () => void }) => { + onSync, +}: Attribute & { + onChange: (v: string) => void; + onDelete: () => void; + onSync?: () => void; +}) => { const timeoutRef = useRef(0); return (
@@ -53,7 +60,10 @@ const NodeAttribute = ({ ); }; -const NodeAttributes = ({ uid }: { uid: string }) => { +const toRecord = (attrs: Attribute[]): Record => + Object.fromEntries(attrs.map((a) => [a.label, a.value])); + +const NodeAttributes = ({ uid, nodeType }: { uid: string; nodeType: string }) => { const [attributes, setAttributes] = useState(() => getBasicTreeByParentUid(uid).map((t) => ({ uid: t.uid, @@ -61,6 +71,10 @@ const NodeAttributes = ({ uid }: { uid: string }) => { value: t.children[0]?.text, })), ); + const attributesRef = useRef(attributes); + attributesRef.current = attributes; + const syncToBlockProps = () => + setDiscourseNodeSetting(nodeType, ["attributes"], toRecord(attributesRef.current)); const [newAttribute, setNewAttribute] = useState(""); return (
@@ -77,10 +91,13 @@ const NodeAttributes = ({ uid }: { uid: string }) => { ) } onDelete={() => - deleteBlock(a.uid).then(() => - setAttributes(attributes.filter((aa) => a.uid !== aa.uid)), - ) + deleteBlock(a.uid).then(() => { + const updated = attributes.filter((aa) => a.uid !== aa.uid); + setAttributes(updated); + setDiscourseNodeSetting(nodeType, ["attributes"], toRecord(updated)); + }) } + onSync={syncToBlockProps} /> ))}
@@ -105,11 +122,13 @@ const NodeAttributes = ({ uid }: { uid: string }) => { parentUid: uid, order: attributes.length, }).then((uid) => { - setAttributes([ + const updated = [ ...attributes, { uid, label: newAttribute, value: DEFAULT }, - ]); + ]; + setAttributes(updated); setNewAttribute(""); + setDiscourseNodeSetting(nodeType, ["attributes"], toRecord(updated)); }); }} /> From 9a513d0f24d1da114df3813609bd131d1ef3fad6 Mon Sep 17 00:00:00 2001 From: sid597 Date: Sat, 21 Feb 2026 02:50:05 +0530 Subject: [PATCH 4/9] default filters --- .../components/settings/DefaultFilters.tsx | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/apps/roam/src/components/settings/DefaultFilters.tsx b/apps/roam/src/components/settings/DefaultFilters.tsx index f9daeb85f..693e98f74 100644 --- a/apps/roam/src/components/settings/DefaultFilters.tsx +++ b/apps/roam/src/components/settings/DefaultFilters.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react"; import type { OnloadArgs } from "roamjs-components/types"; import type { Filters } from "roamjs-components/components/Filter"; import posthog from "posthog-js"; +import { setPersonalSetting } from "~/components/settings/utils/accessors"; // // TODO - REWORK THIS COMPONENT @@ -124,28 +125,27 @@ const DefaultFilters = ({ ); useEffect(() => { - extensionAPI.settings.set( - "default-filters", - Object.fromEntries( - Object.entries(filters).map(([k, v]) => [ - k, - { - includes: Object.fromEntries( - Object.entries(v.includes || {}).map(([k, v]) => [ - k, - Array.from(v), - ]), - ), - excludes: Object.fromEntries( - Object.entries(v.excludes || {}).map(([k, v]) => [ - k, - Array.from(v), - ]), - ), - }, - ]), - ), + const serialized = Object.fromEntries( + Object.entries(filters).map(([k, v]) => [ + k, + { + includes: Object.fromEntries( + Object.entries(v.includes || {}).map(([k, v]) => [ + k, + Array.from(v), + ]), + ), + excludes: Object.fromEntries( + Object.entries(v.excludes || {}).map(([k, v]) => [ + k, + Array.from(v), + ]), + ), + }, + ]), ); + void extensionAPI.settings.set("default-filters", serialized); + setPersonalSetting(["Query", "Default filters"], serialized); }, [filters]); return (
Date: Sat, 21 Feb 2026 03:09:06 +0530 Subject: [PATCH 5/9] node config --- .../settings/DiscourseNodeConfigPanel.tsx | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx index ea5db06cc..3c9cab16b 100644 --- a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx @@ -16,6 +16,9 @@ import posthog from "posthog-js"; import getDiscourseRelations from "~/utils/getDiscourseRelations"; import { deleteBlock } from "roamjs-components/writes"; import { formatHexColor } from "./DiscourseNodeCanvasSettings"; +import setBlockProps from "~/utils/setBlockProps"; +import { DiscourseNodeSchema } from "./utils/zodSchema"; +import { getGlobalSettings, setGlobalSetting } from "./utils/accessors"; type DiscourseNodeConfigPanelProps = React.ComponentProps< CustomField["options"]["component"] @@ -72,13 +75,15 @@ const DiscourseNodeConfigPanel: React.FC = ({ className="select-none" disabled={!label} onClick={() => { + const shortcut = label.slice(0, 1).toUpperCase(); + const format = `[[${label.slice(0, 3).toUpperCase()}]] - {content}`; posthog.capture("Discourse Node: Type Created", { label: label }); - createPage({ + void createPage({ title: `discourse-graph/nodes/${label}`, tree: [ { text: "Shortcut", - children: [{ text: label.slice(0, 1).toUpperCase() }], + children: [{ text: shortcut }], }, { text: "Tag", @@ -86,14 +91,17 @@ const DiscourseNodeConfigPanel: React.FC = ({ }, { text: "Format", - children: [ - { - text: `[[${label.slice(0, 3).toUpperCase()}]] - {content}`, - }, - ], + children: [{ text: format }], }, ], }).then((valueUid) => { + setBlockProps(valueUid, DiscourseNodeSchema.parse({ + text: label, + type: valueUid, + shortcut, + format, + backedBy: "user", + })); setNodes([ ...nodes, { @@ -222,6 +230,9 @@ const DiscourseNodeConfigPanel: React.FC = ({ throw error; }); } + const relations = { ...getGlobalSettings().Relations }; + for (const rel of affectedRelations) delete relations[rel.id]; + setGlobalSetting(["Relations"], relations); deleteNodeType(nodeTypeIdToDelete); } catch (error) { console.error( From 26999de5406c3b4c2263eea767435c0df851ef95 Mon Sep 17 00:00:00 2001 From: sid597 Date: Sat, 21 Feb 2026 03:13:04 +0530 Subject: [PATCH 6/9] fix lint --- .../src/components/settings/DiscourseNodeConfigPanel.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx index 3c9cab16b..1ca5ac534 100644 --- a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx @@ -13,7 +13,9 @@ import refreshConfigTree from "~/utils/refreshConfigTree"; import createPage from "roamjs-components/writes/createPage"; import type { CustomField } from "roamjs-components/components/ConfigPanels/types"; import posthog from "posthog-js"; -import getDiscourseRelations from "~/utils/getDiscourseRelations"; +import getDiscourseRelations, { + type DiscourseRelation, +} from "~/utils/getDiscourseRelations"; import { deleteBlock } from "roamjs-components/writes"; import { formatHexColor } from "./DiscourseNodeCanvasSettings"; import setBlockProps from "~/utils/setBlockProps"; @@ -41,7 +43,7 @@ const DiscourseNodeConfigPanel: React.FC = ({ const [isAlertOpen, setIsAlertOpen] = useState(false); const [alertMessage, setAlertMessage] = useState(""); - const [affectedRelations, setAffectedRelations] = useState([]); + const [affectedRelations, setAffectedRelations] = useState([]); const [nodeTypeIdToDelete, setNodeTypeIdToDelete] = useState(""); const navigateToNode = (uid: string) => { if (isPopup) { From c1f0a1c987e88102f74168d4cb12a7d7cf7e086e Mon Sep 17 00:00:00 2001 From: sid597 Date: Mon, 23 Feb 2026 20:05:11 +0530 Subject: [PATCH 7/9] prettier --- .../settings/DiscourseNodeAttributes.tsx | 26 ++++++++++++++--- .../settings/DiscourseNodeCanvasSettings.tsx | 29 +++++++++++++++---- .../settings/DiscourseNodeConfigPanel.tsx | 21 +++++++++----- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx index a20c16d2a..d437aea97 100644 --- a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx @@ -63,7 +63,13 @@ const NodeAttribute = ({ const toRecord = (attrs: Attribute[]): Record => Object.fromEntries(attrs.map((a) => [a.label, a.value])); -const NodeAttributes = ({ uid, nodeType }: { uid: string; nodeType: string }) => { +const NodeAttributes = ({ + uid, + nodeType, +}: { + uid: string; + nodeType: string; +}) => { const [attributes, setAttributes] = useState(() => getBasicTreeByParentUid(uid).map((t) => ({ uid: t.uid, @@ -74,7 +80,11 @@ const NodeAttributes = ({ uid, nodeType }: { uid: string; nodeType: string }) => const attributesRef = useRef(attributes); attributesRef.current = attributes; const syncToBlockProps = () => - setDiscourseNodeSetting(nodeType, ["attributes"], toRecord(attributesRef.current)); + setDiscourseNodeSetting( + nodeType, + ["attributes"], + toRecord(attributesRef.current), + ); const [newAttribute, setNewAttribute] = useState(""); return (
@@ -94,7 +104,11 @@ const NodeAttributes = ({ uid, nodeType }: { uid: string; nodeType: string }) => deleteBlock(a.uid).then(() => { const updated = attributes.filter((aa) => a.uid !== aa.uid); setAttributes(updated); - setDiscourseNodeSetting(nodeType, ["attributes"], toRecord(updated)); + setDiscourseNodeSetting( + nodeType, + ["attributes"], + toRecord(updated), + ); }) } onSync={syncToBlockProps} @@ -128,7 +142,11 @@ const NodeAttributes = ({ uid, nodeType }: { uid: string; nodeType: string }) => ]; setAttributes(updated); setNewAttribute(""); - setDiscourseNodeSetting(nodeType, ["attributes"], toRecord(updated)); + setDiscourseNodeSetting( + nodeType, + ["attributes"], + toRecord(updated), + ); }); }} /> diff --git a/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx b/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx index 371429ef9..287f4194b 100644 --- a/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeCanvasSettings.tsx @@ -11,7 +11,10 @@ import React, { useState, useMemo } from "react"; import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; import getSettingValueFromTree from "roamjs-components/util/getSettingValueFromTree"; import setInputSetting from "roamjs-components/util/setInputSetting"; -import { DiscourseNodeFlagPanel, DiscourseNodeTextPanel } from "./components/BlockPropSettingPanels"; +import { + DiscourseNodeFlagPanel, + DiscourseNodeTextPanel, +} from "./components/BlockPropSettingPanels"; import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors"; export const formatHexColor = (color: string) => { @@ -66,7 +69,11 @@ const DiscourseNodeCanvasSettings = ({ key: "color", value: colorValue, }); - setDiscourseNodeSetting(nodeType, ["canvasSettings", "color"], colorValue); + setDiscourseNodeSetting( + nodeType, + ["canvasSettings", "color"], + colorValue, + ); }} /> @@ -80,7 +87,11 @@ const DiscourseNodeCanvasSettings = ({ key: "color", value: "", }); - setDiscourseNodeSetting(nodeType, ["canvasSettings", "color"], ""); + setDiscourseNodeSetting( + nodeType, + ["canvasSettings", "color"], + "", + ); }} /> @@ -128,7 +139,11 @@ const DiscourseNodeCanvasSettings = ({ key: "key-image-option", value, }); - setDiscourseNodeSetting(nodeType, ["canvasSettings", "key-image-option"], value); + setDiscourseNodeSetting( + nodeType, + ["canvasSettings", "key-image-option"], + value, + ); }} > @@ -155,7 +170,11 @@ const DiscourseNodeCanvasSettings = ({ key: "query-builder-alias", value: val, }); - setDiscourseNodeSetting(nodeType, ["canvasSettings", "query-builder-alias"], val); + setDiscourseNodeSetting( + nodeType, + ["canvasSettings", "query-builder-alias"], + val, + ); }} />
diff --git a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx index 1ca5ac534..8d388189e 100644 --- a/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeConfigPanel.tsx @@ -43,7 +43,9 @@ const DiscourseNodeConfigPanel: React.FC = ({ const [isAlertOpen, setIsAlertOpen] = useState(false); const [alertMessage, setAlertMessage] = useState(""); - const [affectedRelations, setAffectedRelations] = useState([]); + const [affectedRelations, setAffectedRelations] = useState< + DiscourseRelation[] + >([]); const [nodeTypeIdToDelete, setNodeTypeIdToDelete] = useState(""); const navigateToNode = (uid: string) => { if (isPopup) { @@ -97,13 +99,16 @@ const DiscourseNodeConfigPanel: React.FC = ({ }, ], }).then((valueUid) => { - setBlockProps(valueUid, DiscourseNodeSchema.parse({ - text: label, - type: valueUid, - shortcut, - format, - backedBy: "user", - })); + setBlockProps( + valueUid, + DiscourseNodeSchema.parse({ + text: label, + type: valueUid, + shortcut, + format, + backedBy: "user", + }), + ); setNodes([ ...nodes, { From d29036a43cd368a71a9fff19037473f10bbe17a3 Mon Sep 17 00:00:00 2001 From: sid597 Date: Mon, 23 Feb 2026 20:57:44 +0530 Subject: [PATCH 8/9] port format panel --- .../settings/DiscourseNodeAttributes.tsx | 3 +- .../src/components/settings/NodeConfig.tsx | 123 ++---------------- 2 files changed, 14 insertions(+), 112 deletions(-) diff --git a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx index d437aea97..39a420ae3 100644 --- a/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx +++ b/apps/roam/src/components/settings/DiscourseNodeAttributes.tsx @@ -79,12 +79,13 @@ const NodeAttributes = ({ ); const attributesRef = useRef(attributes); attributesRef.current = attributes; - const syncToBlockProps = () => + const syncToBlockProps = () => { setDiscourseNodeSetting( nodeType, ["attributes"], toRecord(attributesRef.current), ); + }; const [newAttribute, setNewAttribute] = useState(""); return (
diff --git a/apps/roam/src/components/settings/NodeConfig.tsx b/apps/roam/src/components/settings/NodeConfig.tsx index dea52eb60..2bd08868a 100644 --- a/apps/roam/src/components/settings/NodeConfig.tsx +++ b/apps/roam/src/components/settings/NodeConfig.tsx @@ -1,24 +1,20 @@ import React, { useState, useCallback, - useRef, useEffect, useMemo, } from "react"; import { DiscourseNode } from "~/utils/getDiscourseNodes"; -import SelectPanel from "roamjs-components/components/ConfigPanels/SelectPanel"; import DualWriteBlocksPanel from "./components/EphemeralBlocksPanel"; import { getSubTree } from "roamjs-components/util"; import Description from "roamjs-components/components/Description"; -import { Label, Tabs, Tab, TabId, InputGroup } from "@blueprintjs/core"; +import { Label, Tabs, Tab, TabId } from "@blueprintjs/core"; import DiscourseNodeSpecification from "./DiscourseNodeSpecification"; import DiscourseNodeAttributes from "./DiscourseNodeAttributes"; import DiscourseNodeCanvasSettings from "./DiscourseNodeCanvasSettings"; import DiscourseNodeIndex from "./DiscourseNodeIndex"; import { OnloadArgs } from "roamjs-components/types"; import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; -import createBlock from "roamjs-components/writes/createBlock"; -import updateBlock from "roamjs-components/writes/updateBlock"; import DiscourseNodeSuggestiveRules from "./DiscourseNodeSuggestiveRules"; import { getFormattedConfigTree } from "~/utils/discourseConfigRef"; import refreshConfigTree from "~/utils/refreshConfigTree"; @@ -34,91 +30,6 @@ export const getCleanTagText = (tag: string): string => { return tag.replace(/^#+/, "").trim().toUpperCase(); }; -const ValidatedInputPanel = ({ - label, - description, - value, - onChange, - onBlur, - error, - placeholder, -}: { - label: string; - description: string; - value: string; - onChange: (e: React.ChangeEvent) => void; - onBlur: () => void; - error: string; - placeholder?: string; -}) => ( -
- - {error && ( -
{error}
- )} -
-); - -const useDebouncedRoamUpdater = < - T extends HTMLInputElement | HTMLTextAreaElement, ->( - uid: string, - initialValue: string, - isValid: boolean, -) => { - const [value, setValue] = useState(initialValue); - const debounceRef = useRef(0); - const isValidRef = useRef(isValid); - isValidRef.current = isValid; - - const saveToRoam = useCallback( - (text: string, timeout: boolean) => { - window.clearTimeout(debounceRef.current); - debounceRef.current = window.setTimeout( - () => { - if (!isValidRef.current) { - return; - } - const existingBlock = getBasicTreeByParentUid(uid)[0]; - if (existingBlock) { - if (existingBlock.text !== text) { - void updateBlock({ uid: existingBlock.uid, text }); - } - } else if (text) { - void createBlock({ parentUid: uid, node: { text } }); - } - }, - timeout ? 500 : 0, - ); - }, - [uid], - ); - - const handleChange = useCallback( - (e: React.ChangeEvent) => { - const newValue = e.target.value; - setValue(newValue); - saveToRoam(newValue, true); - }, - [saveToRoam], - ); - - const handleBlur = useCallback(() => { - saveToRoam(value, false); - }, [value, saveToRoam]); - - return { value, handleChange, handleBlur }; -}; - const generateTagPlaceholder = (node: DiscourseNode): string => { // Extract first reference from format like [[CLM]], [[QUE]], [[EVD]] const referenceMatch = node.format.match(/\[\[([A-Z]+)\]\]/); @@ -167,18 +78,9 @@ const NodeConfig = ({ const [selectedTabId, setSelectedTabId] = useState("general"); const [tagError, setTagError] = useState(""); const [formatError, setFormatError] = useState(""); - const isConfigurationValid = !tagError && !formatError; const [tagValue, setTagValue] = useState(node.tag || ""); - const { - value: formatValue, - handleChange: handleFormatChange, - handleBlur: handleFormatBlurFromHook, - } = useDebouncedRoamUpdater( - formatUid, - node.format, - isConfigurationValid, - ); + const [formatValue, setFormatValue] = useState(node.format || ""); const validate = useCallback( ({ tag, @@ -238,11 +140,6 @@ const NodeConfig = ({ validate({ tag: tagValue, format: formatValue }); }, [tagValue, formatValue, validate]); - const handleFormatBlur = useCallback(() => { - handleFormatBlurFromHook(); - validate({ tag: tagValue, format: formatValue }); - }, [handleFormatBlurFromHook, tagValue, formatValue, validate]); - return ( <> -