-
-
Notifications
You must be signed in to change notification settings - Fork 119
Enable relationships for span-based (text) annotations #866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Fix three categories of issues preventing relationship creation and
display for text documents:
1. File type detection: Multiple components only checked
startsWith("text/"), missing "application/txt" documents. Add
centralized isTextFileType()/isPdfFileType() utilities and update
all 12 call sites for consistency.
2. Label initialization race condition: Single initialized.current ref
in useAnnotationControls could be set true after span label init,
blocking relationship label auto-selection on subsequent effect
runs. Split into separate spanLabelInitialized and
relationLabelInitialized refs.
3. Type restrictions: RelationItem, RelationHighlightItem,
HighlightItem, and annotationSelectedViaRelationship() only
accepted ServerTokenAnnotation (PDF). Widen to accept
ServerTokenAnnotation | ServerSpanAnnotation union, enabling the
sidebar relationship display and creation flow for text documents.
Closes #281
https://claude.ai/code/session_01Q8XMB6GZZnDWaQP4prr6v2
Code Review - PR #866: Enable relationships for span-based (text) annotationsSummaryThis PR successfully addresses issue #281 by enabling relationship functionality for text documents. The changes are well-structured, focused, and follow good software engineering practices. The core approach of centralizing file type detection and separating initialization logic is solid. ✅ Strengths
🔍 Code Quality Observationsfiles.ts (frontend/src/utils/files.ts:8-15)export const isTextFileType = (fileType: string | null | undefined): boolean =>
fileType?.startsWith("text/") === true || fileType === "application/txt";
export const isPdfFileType = (fileType: string | null | undefined): boolean =>
fileType === "application/pdf";✅ Good: Handles null/undefined gracefully with optional chaining UISettingsAtom.tsx (lines 289-315)const spanLabelInitialized = useRef(false);
const relationLabelInitialized = useRef(false);
useEffect(() => {
if (\!selectedDocument) return;
const isTextFile = isTextFileType(selectedDocument.fileType);
const isPdfFile = isPdfFileType(selectedDocument.fileType);
if (\!spanLabelInitialized.current) {
// initialization logic
}
if (\!relationLabelInitialized.current) {
// initialization logic
}
}, [/* deps */]);✅ Good: Early return pattern for guard clause Type Union Updates (RelationItem.tsx, HighlightItem.tsx, etc.)target_annotations: (ServerTokenAnnotation | ServerSpanAnnotation)[];
source_annotations: (ServerTokenAnnotation | ServerSpanAnnotation)[];✅ Good: Union types are the correct approach here 🧪 Testing ConsiderationsMissing: Unit tests for the new utility functions in I recommend adding a test file import { describe, it, expect } from 'vitest';
import { isTextFileType, isPdfFileType } from '../files';
describe('File type utilities', () => {
describe('isTextFileType', () => {
it('should return true for text/plain', () => {
expect(isTextFileType('text/plain')).toBe(true);
});
it('should return true for text/* variants', () => {
expect(isTextFileType('text/html')).toBe(true);
expect(isTextFileType('text/csv')).toBe(true);
});
it('should return true for application/txt (legacy)', () => {
expect(isTextFileType('application/txt')).toBe(true);
});
it('should return false for PDF', () => {
expect(isTextFileType('application/pdf')).toBe(false);
});
it('should handle null/undefined gracefully', () => {
expect(isTextFileType(null)).toBe(false);
expect(isTextFileType(undefined)).toBe(false);
});
});
describe('isPdfFileType', () => {
it('should return true for application/pdf', () => {
expect(isPdfFileType('application/pdf')).toBe(true);
});
it('should return false for text types', () => {
expect(isPdfFileType('text/plain')).toBe(false);
});
it('should handle null/undefined gracefully', () => {
expect(isPdfFileType(null)).toBe(false);
expect(isPdfFileType(undefined)).toBe(false);
});
});
});Manual Testing Needed (per the PR description):
🔒 Security Considerations✅ No concerns: This PR is purely frontend type-safety and UI logic changes. No data validation, permissions, or backend changes that could introduce security issues. ⚡ Performance Considerations✅ No concerns: The utility functions are simple boolean checks with no performance impact. The initialization logic refactoring doesn't change the computational complexity. 📚 Adherence to Project Guidelines✅ CLAUDE.md compliance:
🎯 Recommendations
✅ VerdictAPPROVE with minor suggestions - This PR is well-implemented and ready to merge after adding the recommended unit tests. The changes are focused, solve the stated problem, and follow project conventions. The code quality is high, the approach is sound, and the risk is low. The centralization of file type detection will prevent future bugs and make the codebase more maintainable. Review generated for commit: Closes #281 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
- Add unit tests for isTextFileType/isPdfFileType (11 test cases covering text/*, application/txt, application/pdf, null, undefined, empty string, and other MIME types) - Extract LEGACY_TEXT_MIME_TYPE constant to constants.ts and reference it from files.ts instead of inlining the magic string - Remove activeSpanLabel/activeRelationLabel from useEffect deps in UISettingsAtom since the initialization refs already gate re-runs; drop the now-redundant !activeSpanLabel/!activeRelationLabel guards https://claude.ai/code/session_01Q8XMB6GZZnDWaQP4prr6v2
Code Review - PR #866: Enable relationships for span-based (text) annotationsSummaryThis PR successfully addresses issue #281 by enabling relationship creation and display for text documents (span-based annotations). The changes are well-structured, comprehensive, and include proper test coverage. ✅ Strengths1. Excellent Centralization PatternThe creation of
2. Critical Bug Fix - Race ConditionThe label initialization fix in
3. Type System EnhancementWidening types to
4. Comprehensive Test CoverageThe new test file
5. Excellent Changelog DocumentationThe CHANGELOG.md entry follows project conventions perfectly:
🔍 Code Quality ObservationsMinor Considerations (Not Blockers)
🔒 Security & Performance
📋 Adherence to Project ConventionsPer
🧪 Testing RecommendationsBefore merging, please verify:
🎯 Final VerdictLGTM - Approved ✅ This is high-quality work that:
The PR is ready to merge once tests confirm everything passes. AcknowledgmentGreat job on the centralization pattern and the thorough handling of the race condition. The separate initialization refs are a clean solution to a subtle timing issue. |
Summary
This PR fixes three critical issues preventing relationships from working with span-based annotations in text documents, enabling the full relationship creation and display workflow for text files.
Key Changes
1. Centralized File Type Detection
isTextFileType()andisPdfFileType()utility functions infrontend/src/utils/files.tsstartsWith("text/")checks and hardcoded MIME type comparisons across 11 componentsapplication/txtMIME type was missed by some checks2. Fixed Label Initialization Race Condition
UISettingsAtom.tsxinitialized.currentref with separatespanLabelInitializedandrelationLabelInitializedrefs3. Expanded Type Support for Relationship UI
RelationItem.tsx,RelationHighlightItem.tsx,HighlightItem.tsx,utils.tsServerTokenAnnotation | ServerSpanAnnotationunion typesannotationSelectedViaRelationship()function to handle both annotation typesFiles Modified
frontend/src/utils/files.ts(new utilities)frontend/src/components/annotator/context/UISettingsAtom.tsxfrontend/src/components/annotator/sidebar/RelationItem.tsxfrontend/src/components/annotator/sidebar/RelationHighlightItem.tsxfrontend/src/components/annotator/sidebar/HighlightItem.tsxfrontend/src/components/annotator/utils.tsfrontend/src/components/annotator/hooks/AnnotationHooks.tsxfrontend/src/components/annotator/labels/EnhancedLabelSelector.tsxfrontend/src/components/annotator/labels/UnifiedLabelSelector.tsxfrontend/src/components/annotator/labels/label_selector/LabelSelector.tsxfrontend/src/components/knowledge_base/document/DocumentKnowledgeBase.tsxfrontend/src/components/widgets/chat/ChatMessage.tsxTesting
Verify that:
text/plainandapplication/txtMIME types are handled consistentlyhttps://claude.ai/code/session_01Q8XMB6GZZnDWaQP4prr6v2