Skip to content

fix: strip demo graph prefix for display and fix schema table names#514

Open
galshubeli wants to merge 5 commits intostagingfrom
fix/demo-graph-prefix-and-schema-labels
Open

fix: strip demo graph prefix for display and fix schema table names#514
galshubeli wants to merge 5 commits intostagingfrom
fix/demo-graph-prefix-and-schema-labels

Conversation

@galshubeli
Copy link
Copy Markdown
Collaborator

@galshubeli galshubeli commented Mar 30, 2026

The list graphs endpoint now returns structured objects with id, name, and is_demo fields so the frontend can display demo graphs without the GENERAL_PREFIX while still using the full id for API calls. Hardcoded demo graph name checks are replaced with the is_demo flag. Also fixes table names not rendering in the schema viewer by using schemaNode.name instead of the undefined node.displayName[1].

Summary by CodeRabbit

  • Changes
    • Demo databases are now explicitly flagged via an is_demo property for consistent detection.
    • Database listing and selection now rely on the demo flag rather than name patterns.
    • Chat suggestions and delete controls follow the demo flag, improving UX consistency.
    • Mobile connected-database label now displays the actual database name directly.

The list graphs endpoint now returns structured objects with id, name,
and is_demo fields so the frontend can display demo graphs without the
GENERAL_PREFIX while still using the full id for API calls. Hardcoded
demo graph name checks are replaced with the is_demo flag. Also fixes
table names not rendering in the schema viewer by using schemaNode.name
instead of the undefined node.displayName[1].

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@galshubeli galshubeli requested a review from Copilot March 30, 2026 16:38
@overcut-ai
Copy link
Copy Markdown

overcut-ai bot commented Mar 30, 2026

Completed Working on "Code Review"

✅ Review publishing completed successfully. Posted comments from all chunks and submitted final review.

✅ Workflow completed successfully.


👉 View complete log

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 30, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA f7ac61e.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3aa588bd-daf7-4879-a6d3-315a9570b723

📥 Commits

Reviewing files that changed from the base of the PR and between 5e50530 and 26a3db3.

📒 Files selected for processing (1)
  • e2e/logic/api/apiCalls.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • e2e/logic/api/apiCalls.ts

📝 Walkthrough

Walkthrough

The pull request replaces string-/prefix-based demo detection with an explicit is_demo boolean across backend, types, frontend services, pages, and E2E utilities; backend now returns graph objects with is_demo, and frontend uses this flag for rendering and delete logic.

Changes

Cohort / File(s) Summary
API Type Definitions
app/src/types/api.ts, e2e/logic/api/apiResponses.ts
Added required is_demo: boolean to graph types; made created_at/updated_at optional; introduced GraphListItem for E2E.
Backend: graph listing
api/core/schema_loader.py
list_databases() now returns list of dicts (id, name, is_demo) instead of string list; user graphs marked is_demo: false, general/demo graphs marked is_demo: true with different id/name handling.
Frontend service
app/src/services/database.ts
DatabaseService.getGraphs() accepts object-array responses (expects is_demo) and maps legacy string arrays to objects with is_demo: false; removed previous created/updated timestamps on legacy conversion.
Frontend pages & UI
app/src/pages/Index.tsx, app/src/components/chat/ChatInterface.tsx, app/src/components/schema/SchemaViewer.tsx
Index: handleDeleteGraph now accepts isDemo param; mobile badge shows selectedGraph.name directly; dropdown/demo styling driven by graph.is_demo. ChatInterface: SuggestionCards rendering switched to selectedGraph?.is_demo. SchemaViewer: node title uses schemaNode.name instead of node.displayName[1].
E2E test utils
e2e/logic/api/apiCalls.ts
ApiCalls.getGraphs() parses /graphs response, maps object-array responses to id arrays using GraphListItem, preserves legacy shapes otherwise; added import for GraphListItem.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Frontend as Frontend (UI)
    participant DBService as DatabaseService
    participant Backend as Backend API
    participant DB as FalkorDB

    User->>Frontend: Request graphs / interact
    Frontend->>DBService: getGraphs()
    DBService->>Backend: GET /graphs
    Backend->>DB: Query graphs
    DB-->>Backend: return graph records
    Backend->>Backend: build list of {id, name, is_demo}
    Backend-->>DBService: [{id,name,is_demo}, ...]
    DBService->>DBService: parse response (handle legacy strings)
    DBService-->>Frontend: Graph[] with is_demo
    Frontend->>Frontend: use selectedGraph.is_demo for UI & delete logic
    Frontend->>User: render suggestions, badges, controls based on is_demo
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A little hop, a boolean cheer,
is_demo arrived — the path is clear.
From backend roots to frontend view,
demo flags guide what UI will do.
I nibble code and hum with glee — hooray for clarity! 🌿

🚥 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 pull request title accurately and concisely describes the two main changes: demo graph prefix stripping for display and schema table name fixes using the correct source property.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/demo-graph-prefix-and-schema-labels

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.

@railway-app
Copy link
Copy Markdown

railway-app bot commented Mar 30, 2026

🚅 Deployed to the QueryWeaver-pr-514 environment in queryweaver

Service Status Web Updated (UTC)
QueryWeaver ✅ Success (View Logs) Web Apr 5, 2026 at 12:01 pm

@railway-app railway-app bot temporarily deployed to queryweaver / QueryWeaver-pr-514 March 30, 2026 16:39 Destroyed
Copy link
Copy Markdown

@overcut-ai overcut-ai bot left a comment

Choose a reason for hiding this comment

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

Review Summary

Found 2 MAJOR issues across 2 files.

Key themes

  • Backward compatibility risk in demo-graph behavior after switching to is_demo-only checks.
  • Type contract drift between frontend types and backend API guarantees (is_demo treated as optional where behavior depends on it).

Recommended next steps

  1. Add a temporary fallback predicate for demo detection (e.g., id/name-based) to avoid regressions for legacy/persisted graph objects.
  2. Make Graph.is_demo required in frontend types and ensure list-graphs responses always include it.
  3. Add/adjust tests for demo suggestion-card visibility and demo-protection behavior with both legacy and current graph payload shapes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the graphs listing contract to return structured graph objects (including a demo flag) so the UI can display demo graphs without the internal prefix while continuing to use full graph IDs for API operations. It also fixes schema table labels in the schema viewer by using the correct field.

Changes:

  • Update /graphs to return { id, name, is_demo } objects instead of plain string IDs.
  • Update frontend demo-graph handling to rely on is_demo instead of hardcoded name/prefix checks.
  • Fix schema viewer table name rendering by using schemaNode.name.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/src/types/api.ts Extends Graph typing to include is_demo and makes timestamps optional to accommodate list response shape.
app/src/pages/Index.tsx Uses is_demo for demo detection and removes special-casing of demo display names.
app/src/components/schema/SchemaViewer.tsx Fixes displayed table name source for canvas labels.
app/src/components/chat/ChatInterface.tsx Shows suggestion cards based on selectedGraph.is_demo rather than hardcoded demo IDs/names.
api/routes/graphs.py Changes list-graphs endpoint to return structured items with id/name/is_demo and strips prefix for display name.

Copy link
Copy Markdown
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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/src/pages/Index.tsx (1)

184-185: Pass isDemo into the handler instead of re-querying graphs.

At Line 184, recomputing with graphs.find(...) is unnecessary and can drift from the clicked row state. Prefer passing the already-known isDemo from the row click site directly to handleDeleteGraph.

♻️ Suggested simplification
- const handleDeleteGraph = async (graphId: string, graphName: string, event: React.MouseEvent) => {
+ const handleDeleteGraph = async (
+   graphId: string,
+   graphName: string,
+   isDemo: boolean,
+   event: React.MouseEvent
+ ) => {
   event.stopPropagation(); // Prevent dropdown from closing/selecting
-  const isDemo = graphs.find(g => g.id === graphId)?.is_demo || false;

   if (isRefreshingSchema) return;
   setDatabaseToDelete({ id: graphId, name: graphName, isDemo });
   setShowDeleteModal(true);
 };
// call site (outside this hunk)
onClick={(e) => {
  if (isDemo || isRefreshingSchema || isChatProcessing) return;
  handleDeleteGraph(graph.id, graph.name, isDemo, e);
}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/pages/Index.tsx` around lines 184 - 185, The code recomputes isDemo
via graphs.find(...) causing possible state drift; update handleDeleteGraph to
accept an isDemo boolean parameter (e.g., handleDeleteGraph(graphId, graphName,
isDemo, event)) and use that passed value instead of querying graphs inside
handleDeleteGraph, then update the call site(s) (the onClick handler that
currently checks isDemo/isRefreshingSchema/isChatProcessing) to pass the row's
isDemo (graph.is_demo) through to handleDeleteGraph; ensure all references to
the old signature are updated to the new signature.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/routes/graphs.py`:
- Around line 56-59: The current demo detection in graphs.py uses is_demo =
bool(GENERAL_PREFIX and graph_id.startswith(GENERAL_PREFIX)) and then truncates
display_name, which misclassifies user graphs whose visible name starts with
GENERAL_PREFIX; instead, use the demo flag that should be provided by the data
source (e.g., the list_databases response or DB record) rather than recomputing
from the stripped graph_id—lookup the originating field (e.g., the database
record's is_demo/isShared/isPublic flag returned by list_databases) and use that
to set is_demo and compute display_name, or if the data source cannot provide
it, enforce and validate at creation time that user graph names cannot begin
with GENERAL_PREFIX (reject/create-time validation) so the current startswith
logic remains safe; update occurrences of is_demo, graph_id and display_name
handling accordingly.

---

Nitpick comments:
In `@app/src/pages/Index.tsx`:
- Around line 184-185: The code recomputes isDemo via graphs.find(...) causing
possible state drift; update handleDeleteGraph to accept an isDemo boolean
parameter (e.g., handleDeleteGraph(graphId, graphName, isDemo, event)) and use
that passed value instead of querying graphs inside handleDeleteGraph, then
update the call site(s) (the onClick handler that currently checks
isDemo/isRefreshingSchema/isChatProcessing) to pass the row's isDemo
(graph.is_demo) through to handleDeleteGraph; ensure all references to the old
signature are updated to the new signature.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4d8c34c4-a1a9-4617-8072-9b42d1e20479

📥 Commits

Reviewing files that changed from the base of the PR and between 9d986cd and 6a178b6.

📒 Files selected for processing (5)
  • api/routes/graphs.py
  • app/src/components/chat/ChatInterface.tsx
  • app/src/components/schema/SchemaViewer.tsx
  • app/src/pages/Index.tsx
  • app/src/types/api.ts

Move is_demo classification into list_databases so it comes from the
data source rather than re-inferring via startsWith in the route. This
prevents user graphs whose name happens to start with GENERAL_PREFIX
from being misclassified as demo graphs. Also makes is_demo required
on the Graph type and passes isDemo directly to handleDeleteGraph.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to queryweaver / QueryWeaver-pr-514 March 30, 2026 16:50 Destroyed
The getGraphs helper now extracts id strings from the object response
so existing E2E tests that call string methods like endsWith continue
to work with the new {id, name, is_demo} response format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to queryweaver / QueryWeaver-pr-514 March 30, 2026 17:09 Destroyed
Copy link
Copy Markdown
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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
api/core/schema_loader.py (1)

147-157: Tighten the return type for list_databases.

list[dict]/list[dict] = [] is too loose for this now-stable response shape (id, name, is_demo). Please use a typed structure (e.g., TypedDict) so static checks catch contract drift.

♻️ Proposed refactor
-from typing import AsyncGenerator, Optional
+from typing import AsyncGenerator, Optional, TypedDict
+
+class GraphListItem(TypedDict):
+    id: str
+    name: str
+    is_demo: bool
@@
 async def list_databases(
     user_id: str, general_prefix: Optional[str] = None
-) -> list[dict]:
+) -> list[GraphListItem]:
@@
-    result: list[dict] = []
+    result: list[GraphListItem] = []

As per coding guidelines, "Use type hints throughout Python code."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/core/schema_loader.py` around lines 147 - 157, The return type and local
`result` list in `list_databases` are too permissive; define a TypedDict (e.g.,
`DatabaseInfo` or `GraphInfo` with keys `id: str`, `name: str`, `is_demo:
bool`), import TypedDict from typing, change the function return annotation from
`list[dict]` to `list[DatabaseInfo]`, and initialize `result: list[DatabaseInfo]
= []`; update any places that construct dicts to produce `DatabaseInfo`-shaped
dicts so static type checkers can validate the response shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/core/schema_loader.py`:
- Around line 151-153: The docstring says the returned dict key "id" should be
the full FalkorDB graph name for API calls, but the implementation at the
user-graph construction (lines around 163-170) sets "id" to the stripped display
name; change the runtime so the returned dict uses the original full graph name
for the "id" field while keeping the stripped value in "name" and preserving
"is_demo", i.e., when building each graph dict assign "id" from the
full/original graph name variable (not the stripped display name) so runtime
matches the docstring.

In `@app/src/services/database.ts`:
- Around line 41-53: getGraphs may return a non-array when payload is
unexpected; ensure the function always returns a Graph[] by validating
graphNames before returning. In getGraphs, after computing const graphNames =
data.graphs || data || [], validate that graphNames is an array of either
strings or objects: if Array.isArray(graphNames) && graphNames.length > 0 &&
typeof graphNames[0] === 'string' keep the existing string->Graph mapping, else
if Array.isArray(graphNames) && graphNames.every(item => item && typeof item ===
'object') cast/map each item to Graph (ensuring id/name/is_demo fields exist
with safe defaults), otherwise return an empty array; use the existing
graphNames identifier and the getGraphs function name to locate and update the
code.

In `@e2e/logic/api/apiCalls.ts`:
- Around line 160-165: getGraphs must always return an array shape; instead of
returning data as-is, coerce/normalize the parsed response into an array of ids.
After parsing response.json() in getGraphs, handle these cases: if Array -> map
GraphListItem to id; else if object with an "id" property -> return [data.id];
else if object with an "items" array -> map items to ids; otherwise return an
empty array. Update the branch around the GraphListItem check to normalize all
non-array payloads into a safe array return so GraphsListResponse contract is
preserved.

---

Nitpick comments:
In `@api/core/schema_loader.py`:
- Around line 147-157: The return type and local `result` list in
`list_databases` are too permissive; define a TypedDict (e.g., `DatabaseInfo` or
`GraphInfo` with keys `id: str`, `name: str`, `is_demo: bool`), import TypedDict
from typing, change the function return annotation from `list[dict]` to
`list[DatabaseInfo]`, and initialize `result: list[DatabaseInfo] = []`; update
any places that construct dicts to produce `DatabaseInfo`-shaped dicts so static
type checkers can validate the response shape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1825fba6-ed92-49d3-9dc2-9216ad2af98e

📥 Commits

Reviewing files that changed from the base of the PR and between 6a178b6 and 5e50530.

📒 Files selected for processing (6)
  • api/core/schema_loader.py
  • app/src/pages/Index.tsx
  • app/src/services/database.ts
  • app/src/types/api.ts
  • e2e/logic/api/apiCalls.ts
  • e2e/logic/api/apiResponses.ts
✅ Files skipped from review due to trivial changes (1)
  • e2e/logic/api/apiResponses.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/pages/Index.tsx

Comment on lines +151 to +153
Returns a list of dicts with keys ``id`` (the full FalkorDB graph name
used for API calls), ``name`` (the display name with namespace prefix
stripped) and ``is_demo`` (whether the graph is a shared demo graph).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Docstring for id does not match runtime behavior.

Line 151-153 says id is the full FalkorDB graph name for API calls, but Line 163 sets user graph id to the stripped display name. This can mislead callers and future maintainers.

Also applies to: 163-170

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/core/schema_loader.py` around lines 151 - 153, The docstring says the
returned dict key "id" should be the full FalkorDB graph name for API calls, but
the implementation at the user-graph construction (lines around 163-170) sets
"id" to the stripped display name; change the runtime so the returned dict uses
the original full graph name for the "id" field while keeping the stripped value
in "name" and preserving "is_demo", i.e., when building each graph dict assign
"id" from the full/original graph name variable (not the stripped display name)
so runtime matches the docstring.

Comment on lines +160 to +165
const data = await response.json();
// Backend now returns objects with {id, name, is_demo}; extract ids for backward compat
if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'object') {
return (data as GraphListItem[]).map((g) => g.id);
}
return data;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Ensure getGraphs() always returns an array shape.

Line 165 returns data as-is; if payload shape drifts (object wrapper, error body, etc.), this breaks the GraphsListResponse contract and can destabilize tests expecting array methods.

💡 Safer shape-guard
-      const data = await response.json();
-      // Backend now returns objects with {id, name, is_demo}; extract ids for backward compat
-      if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'object') {
-        return (data as GraphListItem[]).map((g) => g.id);
-      }
-      return data;
+      const data: unknown = await response.json();
+      if (!Array.isArray(data)) {
+        throw new Error('Unexpected /graphs response shape');
+      }
+      if (data.length === 0) return [];
+      if (typeof data[0] === 'string') return data as GraphsListResponse;
+      if (typeof data[0] === 'object' && data[0] !== null) {
+        return (data as GraphListItem[]).map((g) => g.id);
+      }
+      throw new Error('Unexpected /graphs item type');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const data = await response.json();
// Backend now returns objects with {id, name, is_demo}; extract ids for backward compat
if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'object') {
return (data as GraphListItem[]).map((g) => g.id);
}
return data;
const data: unknown = await response.json();
if (!Array.isArray(data)) {
throw new Error('Unexpected /graphs response shape');
}
if (data.length === 0) return [];
if (typeof data[0] === 'string') return data as GraphsListResponse;
if (typeof data[0] === 'object' && data[0] !== null) {
return (data as GraphListItem[]).map((g) => g.id);
}
throw new Error('Unexpected /graphs item type');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/logic/api/apiCalls.ts` around lines 160 - 165, getGraphs must always
return an array shape; instead of returning data as-is, coerce/normalize the
parsed response into an array of ids. After parsing response.json() in
getGraphs, handle these cases: if Array -> map GraphListItem to id; else if
object with an "id" property -> return [data.id]; else if object with an "items"
array -> map items to ids; otherwise return an empty array. Update the branch
around the GraphListItem check to normalize all non-array payloads into a safe
array return so GraphsListResponse contract is preserved.

@railway-app railway-app bot temporarily deployed to queryweaver / QueryWeaver-pr-514 April 1, 2026 06:35 Destroyed
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