ENG-1225: Discourse node migration simple settings#696
ENG-1225: Discourse node migration simple settings#696sid597 wants to merge 4 commits intographite-base/696from
Conversation
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
3ac2996 to
d549f8d
Compare
a82cfaf to
bc0de10
Compare
d549f8d to
78b7dbb
Compare
bc0de10 to
57abc42
Compare
78b7dbb to
d66fa03
Compare
57abc42 to
7ead54e
Compare
d66fa03 to
cb22590
Compare
490810f to
8dc5276
Compare
cb22590 to
78abef0
Compare
8dc5276 to
8286d6b
Compare
78abef0 to
3966245
Compare
8286d6b to
78e8311
Compare
3966245 to
7015148
Compare
7015148 to
ecdee21
Compare
78e8311 to
938f6aa
Compare
| uid={node.isFirstChild?.uid || ""} | ||
| parentUid={parentUid} | ||
| value={node.isFirstChild?.value || false} | ||
| settingKeys={["suggestiveRules", "isFirstChild", "value"]} |
There was a problem hiding this comment.
🔴 isFirstChild setting path creates invalid schema structure missing required uid field
The DiscourseNodeFlagPanel for "First Child" uses settingKeys={["suggestiveRules", "isFirstChild", "value"]} to set only the boolean value.
Click to expand
Problem
The schema in zodSchema.ts:20-26 defines isFirstChild as:
isFirstChild: z.object({
uid: z.string(),
value: z.boolean(),
}).optional()When the setter saves to path ["suggestiveRules", "isFirstChild", "value"], it creates:
{ "suggestiveRules": { "isFirstChild": { "value": true } } }This object is missing the required uid field.
Why validation passes on write but fails on read
The setDiscourseNodeSetting validation at accessors.ts:437-446 validates only the leaf value (true) against the leaf schema (z.boolean()), which passes.
However, when the full node settings are later read via getDiscourseNodeSettings, the entire object is parsed through DiscourseNodeSchema.safeParse() at accessors.ts:399. The isFirstChild: { value: true } object fails validation because uid: z.string() is required.
Impact
- User changes to the "First Child" toggle are saved in an invalid format
- Subsequent reads of the discourse node settings will fail schema validation
- This breaks suggestive mode functionality for affected nodes
Recommendation: Either change the setting path to set the entire isFirstChild object (e.g., settingKeys={["suggestiveRules", "isFirstChild"]} with value { uid: generateUID(), value: checked }), or update the schema to make uid optional or restructure isFirstChild to just be a boolean.
Was this helpful? React with 👍 or 👎 to provide feedback.
ecdee21 to
96f4575
Compare
| const validateTag = (tag: string): string | undefined => { | ||
| const cleanTag = getCleanTagText(tag); | ||
| if (!cleanTag) return undefined; | ||
| const format = getDiscourseNodeSetting<string>(node.type, ["format"])!; | ||
| const roamTagRegex = /#?\[\[(.*?)\]\]|#(\S+)/g; | ||
| const formatTags: string[] = []; | ||
| for (const match of format.matchAll(roamTagRegex)) { | ||
| const tagName = match[1] || match[2]; | ||
| if (tagName) formatTags.push(tagName.toUpperCase()); | ||
| } | ||
| if (formatTags.includes(cleanTag)) { | ||
| return `The tag "${tag}" is referenced in the format. Please use a different tag or format.`; | ||
| } | ||
| return undefined; | ||
| }; |
There was a problem hiding this comment.
Race condition in validation logic. The validateTag function reads format from settings via getDiscourseNodeSetting, but due to the 500ms debounce in BaseTextPanel (BlockPropSettingPanels.tsx:126-128), the format in settings may be stale. If a user types in the format field and immediately switches to edit the tag field, validateTag will validate against the old format value still in settings, not the current input value.
// Fix: Pass the current format value as a parameter
const validateTag = (tag: string, currentFormat: string): string | undefined => {
const cleanTag = getCleanTagText(tag);
if (!cleanTag) return undefined;
const roamTagRegex = /#?\[\[(.*?)\]\]|#(\S+)/g;
const formatTags: string[] = [];
for (const match of currentFormat.matchAll(roamTagRegex)) {
const tagName = match[1] || match[2];
if (tagName) formatTags.push(tagName.toUpperCase());
}
// ...
};Similarly, validateFormat needs to accept the current tag value as a parameter to avoid reading stale data from settings.
| const validateTag = (tag: string): string | undefined => { | |
| const cleanTag = getCleanTagText(tag); | |
| if (!cleanTag) return undefined; | |
| const format = getDiscourseNodeSetting<string>(node.type, ["format"])!; | |
| const roamTagRegex = /#?\[\[(.*?)\]\]|#(\S+)/g; | |
| const formatTags: string[] = []; | |
| for (const match of format.matchAll(roamTagRegex)) { | |
| const tagName = match[1] || match[2]; | |
| if (tagName) formatTags.push(tagName.toUpperCase()); | |
| } | |
| if (formatTags.includes(cleanTag)) { | |
| return `The tag "${tag}" is referenced in the format. Please use a different tag or format.`; | |
| } | |
| return undefined; | |
| }; | |
| const validateTag = (tag: string, currentFormat?: string): string | undefined => { | |
| const cleanTag = getCleanTagText(tag); | |
| if (!cleanTag) return undefined; | |
| const format = currentFormat || getDiscourseNodeSetting<string>(node.type, ["format"])!; | |
| const roamTagRegex = /#?\[\[(.*?)\]\]|#(\S+)/g; | |
| const formatTags: string[] = []; | |
| for (const match of format.matchAll(roamTagRegex)) { | |
| const tagName = match[1] || match[2]; | |
| if (tagName) formatTags.push(tagName.toUpperCase()); | |
| } | |
| if (formatTags.includes(cleanTag)) { | |
| return `The tag "${tag}" is referenced in the format. Please use a different tag or format.`; | |
| } | |
| return undefined; | |
| }; |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
| const nodeId = node.type; | ||
| tools[nodeId] = { | ||
| id: nodeId, | ||
| // TODO: port this when all node settings are done |
There was a problem hiding this comment.
remove already addressed or noted in the linear ticket
| ControlGroup, | ||
| Checkbox, | ||
| Radio, | ||
| RadioGroup, |
There was a problem hiding this comment.
changed the format of import why?
c09b869 to
67ecd97
Compare
mdroidian
left a comment
There was a problem hiding this comment.
Could you please record a loom video showing the working changed UI. Show the settings being updating in both the legacy as well as the new prop storage.
Please also format all files with prettier.
Also the CI is failing.
67ecd97 to
610365f
Compare
938f6aa to
0dee3d3
Compare
| <<<<<<< HEAD | ||
| import React, { useState, useCallback, useRef } from "react"; | ||
| ======= | ||
| import React, { useState, useRef, useEffect } from "react"; | ||
| >>>>>>> 67ecd97e (fix order) |
There was a problem hiding this comment.
Unresolved merge conflict markers will cause syntax error
The file contains Git merge conflict markers (<<<<<<< HEAD, =======, >>>>>>> 67ecd97e) that will prevent the code from compiling. This needs immediate resolution.
// Remove conflict markers and merge the changes properly:
import React, { useState, useRef, useEffect } from "react";| <<<<<<< HEAD | |
| import React, { useState, useCallback, useRef } from "react"; | |
| ======= | |
| import React, { useState, useRef, useEffect } from "react"; | |
| >>>>>>> 67ecd97e (fix order) | |
| import React, { useState, useRef, useEffect } from "react"; |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
apps/roam/src/components/settings/components/BlockPropSettingPanels.tsx
Outdated
Show resolved
Hide resolved
0dee3d3 to
d4ed8a1
Compare
610365f to
80bb0fb
Compare
80bb0fb to
dfe4388
Compare
d4ed8a1 to
88d4ff5
Compare
dfe4388 to
a449a73
Compare
| <DiscourseNodeTextPanel | ||
| nodeType={node.type} | ||
| title="Tag" | ||
| description={`Designate a hashtag for marking potential ${node.text}.`} | ||
| value={tagValue} | ||
| onChange={handleTagChange} | ||
| onBlur={handleTagBlur} | ||
| error={tagError} | ||
| settingKeys={["tag"]} | ||
| defaultValue={node.tag} | ||
| placeholder={generateTagPlaceholder(node)} | ||
| validate={validateTag} | ||
| onChange={setTagValue} | ||
| parentUid={node.type} | ||
| uid={tagUid} | ||
| /> |
There was a problem hiding this comment.
🟡 Tag validation error state becomes stale when format field changes
The tag validation error state is now managed internally within BaseTextPanel and only updates when the tag input changes. However, the validateTag function depends on formatValue to check for conflicts between tag and format.
Click to expand
Root Cause
In the previous implementation, validation ran via useEffect whenever either tagValue or formatValue changed:
useEffect(() => {
validate({ tag: tagValue, format: formatValue });
}, [tagValue, formatValue, validate]);In the new implementation (NodeConfig.tsx:241-243), only formatError is updated:
useEffect(() => {
validateFormat({ format: formatValue });
}, [tagValue, formatValue, validateFormat]);The tag error is now managed inside BaseTextPanel state (BlockPropSettingPanels.tsx:118-119) and is only set via handleChange (BlockPropSettingPanels.tsx:142-144).
Impact
- User enters a tag that conflicts with the format → tag error is shown
- User modifies the format to remove the conflict
- The tag error message persists until the user manually edits the tag field again
This is a regression in UX where stale error messages can confuse users.
Was this helpful? React with 👍 or 👎 to provide feedback.
a449a73 to
84aa5ac
Compare
| <DiscourseNodeTextPanel | ||
| nodeType={node.type} | ||
| title="Description" | ||
| description={`Describing what the ${node.text} node represents in your graph.`} | ||
| value={descriptionValue} | ||
| onChange={handleDescriptionChange} | ||
| onBlur={handleDescriptionBlur} | ||
| settingKeys={["description"]} | ||
| defaultValue={node.description} | ||
| parentUid={node.type} | ||
| uid={descriptionUid} |
There was a problem hiding this comment.
The DiscourseNodeTextPanel for Description is missing the required order prop. Without this prop, hasBlockSync will be false in BaseTextPanel (requires both parentUid and order to be defined), preventing changes from being synced to Roam blocks.
<DiscourseNodeTextPanel
nodeType={node.type}
title="Description"
description={`Describing what the ${node.text} node represents in your graph.`}
settingKeys={["description"]}
defaultValue={node.description}
order={1} // Add this line
parentUid={node.type}
uid={descriptionUid}
/>| <DiscourseNodeTextPanel | |
| nodeType={node.type} | |
| title="Description" | |
| description={`Describing what the ${node.text} node represents in your graph.`} | |
| value={descriptionValue} | |
| onChange={handleDescriptionChange} | |
| onBlur={handleDescriptionBlur} | |
| settingKeys={["description"]} | |
| defaultValue={node.description} | |
| parentUid={node.type} | |
| uid={descriptionUid} | |
| <DiscourseNodeTextPanel | |
| nodeType={node.type} | |
| title="Description" | |
| description={`Describing what the ${node.text} node represents in your graph.`} | |
| settingKeys={["description"]} | |
| defaultValue={node.description} | |
| order={1} | |
| parentUid={node.type} | |
| uid={descriptionUid} |
Spotted by Graphite Agent
Is this helpful? React 👍 or 👎 to let us know.
88d4ff5 to
f5d0a0a
Compare
84aa5ac to
8ad6b12
Compare
| <<<<<<< HEAD | ||
| ======= | ||
| settingKeys={["Export", "Remove Special Characters"]} | ||
| defaultValue={exportSettings.removeSpecialCharacters.value || false} | ||
| >>>>>>> 84aa5ac2 (restack and fix unnecessary changes) |
There was a problem hiding this comment.
🔴 Unresolved git merge conflicts in ExportSettings.tsx
The file contains unresolved git merge conflict markers (<<<<<<< HEAD, =======, >>>>>>> 84aa5ac2) at multiple locations throughout the file. This will cause syntax errors and prevent the application from compiling.
Click to expand
Impact
The file has 7 unresolved merge conflicts at lines 18-22, 32-36, 45-49, 59-63, 74-79, 92-96, and 105-109. Each conflict contains both HEAD and the other branch's changes, making the file invalid JavaScript/TypeScript.
Example of the conflict pattern:
<<<<<<< HEAD
=======
settingKeys={["Export", "Remove Special Characters"]}
defaultValue={exportSettings.removeSpecialCharacters.value || false}
>>>>>>> 84aa5ac2 (restack and fix unnecessary changes)Actual vs Expected
- Actual: File contains merge conflict markers that are invalid syntax
- Expected: File should have resolved conflicts with valid TypeScript code
Recommendation: Resolve the git merge conflicts by choosing the appropriate code from either HEAD or the other branch, then remove all conflict markers.
Was this helpful? React with 👍 or 👎 to provide feedback.

https://www.loom.com/share/4d58cd87bf7e40c9b6e1b644d53742d0
ENG-1225: Discourse node migration
Migrate personal settings text inputs
remove unnecessary checks zod takes care
migrate attributes overlay and suggestive rules
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.