Notetaking-1(Introduced notes-taking,highlights,comments,canvas,AI-chat,translate in saperate Notes Section)#23
Conversation
There was a problem hiding this comment.
19 issues found across 28 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="types.ts">
<violation number="1" location="types.ts:49">
P0: `result.tags || []` breaks when tags is an object — truthy non-null object skips the `[]` fallback, then spread `...result.tags` throws `object is not iterable` at runtime.</violation>
</file>
<file name="src/components/notes/NoteEditor.tsx">
<violation number="1" location="src/components/notes/NoteEditor.tsx:87">
P2: Escape handler on parent div cancels editor when pressing Escape inside the tag input. NoteTagInput captures Enter but does not stopPropagation, so Escape bubbles up and triggers onCancel, unexpectedly closing the entire editor.</violation>
<violation number="2" location="src/components/notes/NoteEditor.tsx:206">
P3: Keyboard shortcut hint only mentions 'Ctrl+Enter' but handler also supports Cmd+Enter (e.metaKey) for Mac users. Hint should reference both modifiers.</violation>
</file>
<file name="src/components/notes/TranscriptNotes.tsx">
<violation number="1" location="src/components/notes/TranscriptNotes.tsx:64">
P1: Component performs state updates and parent callback inside render. Move this pending-text consumption logic to `useEffect` to avoid render-phase side effects and re-render loops.</violation>
</file>
<file name="src/components/HighlightToolbar.tsx">
<violation number="1" location="src/components/HighlightToolbar.tsx:232">
P2: Icon-only buttons are missing `aria-label`, reducing accessibility for assistive tech users.</violation>
</file>
<file name="src/components/notes/NoteTagInput.tsx">
<violation number="1" location="src/components/notes/NoteTagInput.tsx:44">
P2: Remove button for each tag has no `aria-label`, making it inaccessible to screen reader users.</violation>
<violation number="2" location="src/components/notes/NoteTagInput.tsx:54">
P2: The `<input>` element lacks an accessible label, which can cause issues for screen reader users navigating the form.</violation>
</file>
<file name="src/components/notes/NoteCard.tsx">
<violation number="1" location="src/components/notes/NoteCard.tsx:86">
P2: Action buttons are hidden by default on mobile, making note actions hard to discover/use on touch devices. Set default opacity visible and only hide on `sm+` until hover/focus.</violation>
</file>
<file name="NEW_DB_SCRIPTS/add_indexes.py">
<violation number="1" location="NEW_DB_SCRIPTS/add_indexes.py:4">
P3: Unused import `create_engine` adds dead code and reduces clarity.</violation>
<violation number="2" location="NEW_DB_SCRIPTS/add_indexes.py:73">
P2: Mandatory pg_trgm creation can fail and block all index creation. Make extension creation best-effort or remove it unless trigram operators are actually used.</violation>
</file>
<file name="backend/src/utils/dataProcessor.js">
<violation number="1" location="backend/src/utils/dataProcessor.js:189">
P2: Falsy check on `row.duration_seconds` treats `0` as missing. A 0-second duration should display as `0:00`, not `N/A`.</violation>
</file>
<file name="src/pages/Library.tsx">
<violation number="1" location="src/pages/Library.tsx:69">
P2: Notes tab sort ignores `pinned` state, so pinned notes are not reliably kept at the top.</violation>
<violation number="2" location="src/pages/Library.tsx:433">
P2: `onEdit` uses `window.location.href`, forcing full-page reload instead of SPA navigation.</violation>
</file>
<file name="src/hooks/useWhiteboard.ts">
<violation number="1" location="src/hooks/useWhiteboard.ts:12">
P1: State is not reset when `transcriptId` changes, so previous transcript graph can leak into a new transcript and be saved under the wrong key. Reset loading/data before reading localStorage for the new transcript.</violation>
<violation number="2" location="src/hooks/useWhiteboard.ts:17">
P2: Parsed localStorage data is not shape-validated before setting React Flow state. Non-array `nodes`/`edges` can cause runtime errors in downstream graph operations.</violation>
</file>
<file name="src/components/whiteboard/TranscriptWhiteboard.tsx">
<violation number="1" location="src/components/whiteboard/TranscriptWhiteboard.tsx:26">
P2: Notes list is recomputed every render, forcing avoidable concept-sync work. Memoize allNotes by transcript/function deps to prevent unnecessary node reconciliation.</violation>
<violation number="2" location="src/components/whiteboard/TranscriptWhiteboard.tsx:73">
P2: Delete action applies note deletion to every selected node id, including non-concept nodes. This can trigger incorrect deletions/false success toasts and leaves selected non-concept nodes undeleted.</violation>
<violation number="3" location="src/components/whiteboard/TranscriptWhiteboard.tsx:138">
P3: Timeout in FitViewOnLoad is not cleaned up. This leaves stale delayed callbacks and can run fitView after unmount/update.</violation>
</file>
<file name="backend/supabase/migrations/001_full_text_search.sql">
<violation number="1" location="backend/supabase/migrations/001_full_text_search.sql:51">
P3: `speakers` array order is nondeterministic because `array_agg` has no `ORDER BY`. This causes unstable API payloads and noisy cache diffs.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
| summary: string | null; | ||
| tags: string[]; | ||
| categories: string[]; | ||
| tags: string[] | object; |
There was a problem hiding this comment.
P0: result.tags || [] breaks when tags is an object — truthy non-null object skips the [] fallback, then spread ...result.tags throws object is not iterable at runtime.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At types.ts, line 49:
<comment>`result.tags || []` breaks when tags is an object — truthy non-null object skips the `[]` fallback, then spread `...result.tags` throws `object is not iterable` at runtime.</comment>
<file context>
@@ -46,10 +46,10 @@ export interface RawTranscript {
summary: string | null;
- tags: string[];
- categories: string[];
+ tags: string[] | object;
+ categories: string[] | object;
+ topics?: string[] | object;
</file context>
|
|
||
| // Auto-open editor when pendingSelectedText arrives | ||
| const [consumedText, setConsumedText] = useState<string | undefined>(undefined) | ||
| if (pendingSelectedText && pendingSelectedText !== consumedText) { |
There was a problem hiding this comment.
P1: Component performs state updates and parent callback inside render. Move this pending-text consumption logic to useEffect to avoid render-phase side effects and re-render loops.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/notes/TranscriptNotes.tsx, line 64:
<comment>Component performs state updates and parent callback inside render. Move this pending-text consumption logic to `useEffect` to avoid render-phase side effects and re-render loops.</comment>
<file context>
@@ -0,0 +1,350 @@
+
+ // Auto-open editor when pendingSelectedText arrives
+ const [consumedText, setConsumedText] = useState<string | undefined>(undefined)
+ if (pendingSelectedText && pendingSelectedText !== consumedText) {
+ setConsumedText(pendingSelectedText)
+ setActiveTab('notes')
</file context>
| useEffect(() => { | ||
| try { | ||
| const stored = localStorage.getItem(`${STORAGE_KEY}-${transcriptId}`); | ||
| if (stored) { | ||
| const parsed = JSON.parse(stored); | ||
| if (parsed.nodes) setNodes(parsed.nodes); | ||
| if (parsed.edges) setEdges(parsed.edges); | ||
| } | ||
| } catch (e) { | ||
| console.error("Failed to load whiteboard state:", e); | ||
| } | ||
| setIsLoaded(true); | ||
| }, [transcriptId]); | ||
|
|
||
| // Save to local storage |
There was a problem hiding this comment.
P1: State is not reset when transcriptId changes, so previous transcript graph can leak into a new transcript and be saved under the wrong key. Reset loading/data before reading localStorage for the new transcript.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/hooks/useWhiteboard.ts, line 12:
<comment>State is not reset when `transcriptId` changes, so previous transcript graph can leak into a new transcript and be saved under the wrong key. Reset loading/data before reading localStorage for the new transcript.</comment>
<file context>
@@ -0,0 +1,51 @@
+ const [isLoaded, setIsLoaded] = useState(false);
+
+ // Load from local storage
+ useEffect(() => {
+ try {
+ const stored = localStorage.getItem(`${STORAGE_KEY}-${transcriptId}`);
</file context>
| useEffect(() => { | |
| try { | |
| const stored = localStorage.getItem(`${STORAGE_KEY}-${transcriptId}`); | |
| if (stored) { | |
| const parsed = JSON.parse(stored); | |
| if (parsed.nodes) setNodes(parsed.nodes); | |
| if (parsed.edges) setEdges(parsed.edges); | |
| } | |
| } catch (e) { | |
| console.error("Failed to load whiteboard state:", e); | |
| } | |
| setIsLoaded(true); | |
| }, [transcriptId]); | |
| // Save to local storage | |
| useEffect(() => { | |
| setIsLoaded(false); | |
| setNodes([]); | |
| setEdges([]); | |
| try { | |
| const stored = localStorage.getItem(`${STORAGE_KEY}-${transcriptId}`); | |
| if (stored) { | |
| const parsed = JSON.parse(stored); | |
| if (Array.isArray(parsed.nodes)) setNodes(parsed.nodes); | |
| if (Array.isArray(parsed.edges)) setEdges(parsed.edges); | |
| } | |
| } catch (e) { | |
| console.error("Failed to load whiteboard state:", e); | |
| } | |
| setIsLoaded(true); | |
| }, [transcriptId]); |
| e.preventDefault() | ||
| handleSave() | ||
| } | ||
| if (e.key === 'Escape') { |
There was a problem hiding this comment.
P2: Escape handler on parent div cancels editor when pressing Escape inside the tag input. NoteTagInput captures Enter but does not stopPropagation, so Escape bubbles up and triggers onCancel, unexpectedly closing the entire editor.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/notes/NoteEditor.tsx, line 87:
<comment>Escape handler on parent div cancels editor when pressing Escape inside the tag input. NoteTagInput captures Enter but does not stopPropagation, so Escape bubbles up and triggers onCancel, unexpectedly closing the entire editor.</comment>
<file context>
@@ -0,0 +1,240 @@
+ e.preventDefault()
+ handleSave()
+ }
+ if (e.key === 'Escape') {
+ e.preventDefault()
+ onCancel()
</file context>
| </div> | ||
| <div className="flex items-center justify-between gap-1 px-1"> | ||
| <div className="flex items-center gap-1"> | ||
| <button onClick={handleCopySelectedText} className="p-1.5 rounded hover:bg-secondary text-muted-foreground hover:text-foreground transition-colors" title="Copy"><Copy className="w-4 h-4" /></button> |
There was a problem hiding this comment.
P2: Icon-only buttons are missing aria-label, reducing accessibility for assistive tech users.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/HighlightToolbar.tsx, line 232:
<comment>Icon-only buttons are missing `aria-label`, reducing accessibility for assistive tech users.</comment>
<file context>
@@ -174,90 +188,57 @@ export function HighlightToolbar({
- </div>
+ <div className="flex items-center justify-between gap-1 px-1">
+ <div className="flex items-center gap-1">
+ <button onClick={handleCopySelectedText} className="p-1.5 rounded hover:bg-secondary text-muted-foreground hover:text-foreground transition-colors" title="Copy"><Copy className="w-4 h-4" /></button>
+ {onAddNote && <button onClick={() => { onAddNote(selectedText); setToolbarVisible(false); }} className="p-1.5 rounded hover:bg-secondary text-muted-foreground hover:text-foreground transition-colors" title="Add Note"><StickyNote className="w-4 h-4" /></button>}
+ {onExtractConcept && <button onClick={() => { onExtractConcept(selectedText); setToolbarVisible(false); }} className="p-1.5 rounded hover:bg-secondary text-amber-500 hover:text-amber-600 transition-colors" title="Extract Concept"><Sparkles className="w-4 h-4" /></button>}
</file context>
| }, [conceptNotes, setNodes, isLoaded]); | ||
|
|
||
| const handleDeleteSelected = () => { | ||
| selectedNodeIds.forEach(id => { |
There was a problem hiding this comment.
P2: Delete action applies note deletion to every selected node id, including non-concept nodes. This can trigger incorrect deletions/false success toasts and leaves selected non-concept nodes undeleted.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/whiteboard/TranscriptWhiteboard.tsx, line 73:
<comment>Delete action applies note deletion to every selected node id, including non-concept nodes. This can trigger incorrect deletions/false success toasts and leaves selected non-concept nodes undeleted.</comment>
<file context>
@@ -0,0 +1,145 @@
+ }, [conceptNotes, setNodes, isLoaded]);
+
+ const handleDeleteSelected = () => {
+ selectedNodeIds.forEach(id => {
+ deleteNote(id);
+ });
</file context>
|
|
||
| <div className="flex items-center gap-3"> | ||
| <span className="hidden sm:inline text-xs text-muted-foreground font-mono"> | ||
| Ctrl+Enter to save |
There was a problem hiding this comment.
P3: Keyboard shortcut hint only mentions 'Ctrl+Enter' but handler also supports Cmd+Enter (e.metaKey) for Mac users. Hint should reference both modifiers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/notes/NoteEditor.tsx, line 206:
<comment>Keyboard shortcut hint only mentions 'Ctrl+Enter' but handler also supports Cmd+Enter (e.metaKey) for Mac users. Hint should reference both modifiers.</comment>
<file context>
@@ -0,0 +1,240 @@
+
+ <div className="flex items-center gap-3">
+ <span className="hidden sm:inline text-xs text-muted-foreground font-mono">
+ Ctrl+Enter to save
+ </span>
+ <div className="flex items-center gap-2">
</file context>
| import os | ||
| import sys | ||
| import logging | ||
| from sqlalchemy import create_engine, text |
There was a problem hiding this comment.
P3: Unused import create_engine adds dead code and reduces clarity.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At NEW_DB_SCRIPTS/add_indexes.py, line 4:
<comment>Unused import `create_engine` adds dead code and reduces clarity.</comment>
<file context>
@@ -0,0 +1,88 @@
+import os
+import sys
+import logging
+from sqlalchemy import create_engine, text
+from dotenv import load_dotenv
+
</file context>
| setTimeout(() => { | ||
| fitView({ padding: 0.2, duration: 800 }); | ||
| }, 200); |
There was a problem hiding this comment.
P3: Timeout in FitViewOnLoad is not cleaned up. This leaves stale delayed callbacks and can run fitView after unmount/update.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/components/whiteboard/TranscriptWhiteboard.tsx, line 138:
<comment>Timeout in FitViewOnLoad is not cleaned up. This leaves stale delayed callbacks and can run fitView after unmount/update.</comment>
<file context>
@@ -0,0 +1,145 @@
+
+ useEffect(() => {
+ if (nodesCount > 0) {
+ setTimeout(() => {
+ fitView({ padding: 0.2, duration: 800 });
+ }, 200);
</file context>
| setTimeout(() => { | |
| fitView({ padding: 0.2, duration: 800 }); | |
| }, 200); | |
| const timer = setTimeout(() => { | |
| fitView({ padding: 0.2, duration: 800 }); | |
| }, 200); | |
| return () => clearTimeout(timer); |
| t.summary, | ||
| ts_rank(t.fts, tsquery_val) AS rank, | ||
| c.title, | ||
| COALESCE(array_agg(DISTINCT s.name) FILTER (WHERE s.name IS NOT NULL), '{}') AS speakers, |
There was a problem hiding this comment.
P3: speakers array order is nondeterministic because array_agg has no ORDER BY. This causes unstable API payloads and noisy cache diffs.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/supabase/migrations/001_full_text_search.sql, line 51:
<comment>`speakers` array order is nondeterministic because `array_agg` has no `ORDER BY`. This causes unstable API payloads and noisy cache diffs.</comment>
<file context>
@@ -41,29 +38,35 @@ AS $$
- t.summary,
- ts_rank(t.fts, tsquery_val) AS rank,
+ c.title,
+ COALESCE(array_agg(DISTINCT s.name) FILTER (WHERE s.name IS NOT NULL), '{}') AS speakers,
+ c.event_date,
+ tx.name AS conference,
</file context>
| COALESCE(array_agg(DISTINCT s.name) FILTER (WHERE s.name IS NOT NULL), '{}') AS speakers, | |
| COALESCE(array_agg(DISTINCT s.name ORDER BY s.name) FILTER (WHERE s.name IS NOT NULL), '{}') AS speakers, |
|
@parthdude07 change the title of PR to specifics of the changes in the PR . |
Summary by cubic
Adds Phase 1 note-taking and a transcript whiteboard, and migrates the backend to the new multi‑source DB schema with improved full‑text search.
New Features
@xyflow/react.Migration
@xyflow/reactif not auto‑installedWritten for commit 64921f4. Summary will update on new commits.