Skip to content

Conversation

@sid597
Copy link
Collaborator

@sid597 sid597 commented Feb 11, 2026

https://www.loom.com/share/92b399a36f4d4e3f8e49a95e5c65661b


Open with Devin

Summary by CodeRabbit

  • New Features
    • Added automatic query state synchronization to discourse nodes, preserving query configurations and selections.
    • Introduced a new "custom" field to query settings for extended configuration options.
    • Enhanced query builder to support discourse node type associations.

@linear
Copy link

linear bot commented Feb 11, 2026

@supabase
Copy link

supabase bot commented Feb 11, 2026

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@sid597 sid597 marked this pull request as ready for review February 11, 2026 08:06
@sid597 sid597 changed the title query builder port Port Discourse node: Query builder and editor component for block props Feb 11, 2026
@sid597 sid597 changed the title Port Discourse node: Query builder and editor component for block props ENG-1280: Port Discourse node: Query builder and editor component for block props Feb 11, 2026
@sid597
Copy link
Collaborator Author

sid597 commented Feb 11, 2026

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

✅ Actions performed

Full review triggered.

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

📝 Walkthrough

Walkthrough

The changes implement synchronization of query builder state to discourse node block properties. A new optional discourseNodeType prop is threaded through QueryBuilder and QueryEditor components. When provided, QueryEditor syncs the query state (conditions, selections, custom) to the discourse node using setDiscourseNodeSetting. The DiscourseNodeIndex initializes index settings on block creation and passes the node type to enable this synchronization behavior.

Changes

Cohort / File(s) Summary
Query Component Props & Synchronization
apps/roam/src/components/QueryBuilder.tsx, apps/roam/src/components/QueryEditor.tsx
Added optional discourseNodeType prop to both components. QueryEditor implements new effect that syncs query state (conditions, selections, custom) to discourse node via setDiscourseNodeSetting with validation and debouncing when discourseNodeType is provided.
Index Initialization
apps/roam/src/components/settings/DiscourseNodeIndex.tsx
Initializes index settings with default conditions and empty selections when creating a new block. Passes discourseNodeType to QueryBuilder to enable synchronization.
Schema Extensions
apps/roam/src/components/settings/utils/zodSchema.ts, apps/roam/src/components/settings/utils/zodSchema.example.ts
Extended IndexSchema to include new custom field with string type and empty string default.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant QueryEditor
    participant DebounceTimer
    participant IndexSchema
    participant DiscourseNode

    User->>QueryEditor: Update conditions/selections/custom
    QueryEditor->>DebounceTimer: Clear previous timeout
    DebounceTimer->>DebounceTimer: Start new 500ms timer
    
    DebounceTimer->>IndexSchema: Validate query state
    IndexSchema-->>IndexSchema: safeParse(data)
    
    alt Validation succeeds
        IndexSchema-->>QueryEditor: Valid data
        QueryEditor->>DiscourseNode: setDiscourseNodeSetting("index", validatedData)
        DiscourseNode-->>QueryEditor: Updated
    else Validation fails
        IndexSchema-->>QueryEditor: Parse error (silently ignored)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: porting a Discourse node query builder and editor component to support block props synchronization.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/roam/src/components/settings/DiscourseNodeIndex.tsx (1)

27-68: ⚠️ Potential issue | 🟠 Major

No error handling on the createBlock promise — spinner may hang indefinitely on failure.

If createBlock rejects, setShowQuery(true) is never called, leaving the user stuck on a <Spinner /> with no recovery path. Consider adding a .catch() to handle the failure gracefully.

Proposed fix
       void createBlock({
         parentUid: initialQueryArgs.conditionsNodesUid,
         node: {
           text: "clause",
           children: [
             {
               text: "source",
               children: [{ text: DEFAULT_RETURN_NODE }],
             },
             {
               text: "relation",
               children: [{ text: "is a" }],
             },
             {
               text: "target",
               children: [
                 {
                   text: node.text,
                 },
               ],
             },
           ],
         },
       }).then(() => {
         setDiscourseNodeSetting(node.type, ["index"], {
           conditions: [
             {
               type: "clause",
               source: DEFAULT_RETURN_NODE,
               relation: "is a",
               target: node.text,
             },
           ],
           selections: [],
         });
 
         setShowQuery(true);
-      });
+      }).catch((error) => {
+        console.error("Failed to create initial query block:", error);
+        setShowQuery(true);
+      });
🧹 Nitpick comments (1)
apps/roam/src/components/settings/DiscourseNodeIndex.tsx (1)

53-63: Minor inconsistency: initial index write omits custom field.

The IndexSchema now includes custom: z.string().default(""), and QueryEditor's sync logic serializes custom. This initial write to setDiscourseNodeSetting omits it. It works because Zod fills in the default on read, but adding custom: "" here would be consistent with the schema and the sync logic in QueryEditor.

Proposed fix
         setDiscourseNodeSetting(node.type, ["index"], {
           conditions: [
             {
               type: "clause",
               source: DEFAULT_RETURN_NODE,
               relation: "is a",
               target: node.text,
             },
           ],
           selections: [],
+          custom: "",
         });

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 10 additional findings in Devin Review.

Open in Devin Review

<ExtensionApiContextProvider {...onloadArgs}>
{showQuery ? <QueryBuilder pageUid={parentUid} /> : <Spinner />}
{showQuery ? (
<QueryBuilder pageUid={parentUid} discourseNodeType={node.type} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The pageUid/parentUid is the index block which is a child block of node.type. Seeing as we are passing the parentUid, we can just get the node.type uid based on that, so we don't need to pass it through 2 components.

EG: in Query Editor, where you want to use node.type, use the information that is there to get it (which we know is the ancestor with no parent (or the page uid it is in))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah never mind, we wouldn't want to make an extra query/check for every query instance

if (!discourseNodeType) return;

const stripped: unknown = JSON.parse(
JSON.stringify({ conditions, selections, custom }, (key, value: unknown) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format with prettier

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants