Skip to content

feat: Complete data cleaning workflow with bidirectional relationship management#46

Merged
patchmemory merged 11 commits intomainfrom
task/task-ui/labels/push-pull-instance-preview
Feb 8, 2026
Merged

feat: Complete data cleaning workflow with bidirectional relationship management#46
patchmemory merged 11 commits intomainfrom
task/task-ui/labels/push-pull-instance-preview

Conversation

@patchmemory
Copy link
Owner

Summary

Implements a complete data cleaning workflow for Neo4j knowledge graphs through a spreadsheet interface, plus bidirectional relationship management.

Features

Data Cleaning Workflow

  • Remove properties from label schema → instance table auto-updates (columns disappear)
  • Push with Overwrite Mode → removes properties from Neo4j nodes not in schema
  • Push with Merge Mode → only updates changed properties (preserves others)
  • CSV export/import for bulk editing in Excel/Sheets
  • Excel-like copy/paste (Ctrl+C/V) for multi-cell operations
  • Instance count preview before Pull/Push operations

Bidirectional Relationship Management

  • Manage relationships from source OR target perspective
  • Add/edit/delete incoming relationships (from other labels to this one)
  • Inline editing with editable rows (consistent UX with outgoing)
  • All changes commit atomically on Save
  • Editor closes after Save (returns to read-only mode)

Auto-Lock Session Security

  • Sessions auto-lock after inactivity (1-120 min configurable)
  • Lock screen overlay with password unlock
  • Settings UI for enable/disable and timeout

Documentation Cleanup

  • Updated testing.md to reflect Settings as landing page
  • Obsolete home page tests already archived

Technical Details

Backend:

  • Added PUT endpoint `/api/labels//instances/` for overwrite mode
  • Added `overwrite_label_instance()` in LabelService (uses Cypher `SET n = {props}`)
  • Incoming relationships computed dynamically from other labels
  • Session locking with database persistence

Frontend:

  • Inline editing for incoming relationships (like outgoing)
  • `applyIncomingRelationshipChanges()` updates source labels automatically
  • Property removal triggers instance table refresh
  • Push mode selection modal (Merge vs Overwrite)

Test Coverage

  • ✅ 53 tests passing (9 new tests added)
  • New file: `tests/test_property_removal_and_overwrite.py`
  • Tests validate overwrite mode, property removal, incoming relationships

Breaking Changes

None - all changes are additive

Migration Notes

None required

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

patchmemory and others added 11 commits February 8, 2026 17:48
Adds confirmation modal showing instance count before pulling schema:
- Uses existing /api/labels/<name>/instance-count endpoint
- Shows modal with preview of what will happen
- Displays Neo4j instance count (or error if not connected)
- User can confirm or cancel action
- Improves safety by showing impact before schema pull

Frontend changes:
- Add confirmation modal HTML component
- Add showConfirmModal() helper function
- Add getInstanceCount() async function
- Update pullFromNeo4j() to show modal with instance count
- Loading state while fetching count
- Error handling for Neo4j not connected

Testing:
- 3 unit tests for instance count endpoint
- Tests endpoint exists and handles errors gracefully
- All tests passing

Acceptance criteria met:
✅ Pull button shows instance count in modal
✅ User can confirm/cancel before action
✅ Clear feedback on what will happen
✅ Handles Neo4j not connected gracefully

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…ances

Extends instance editing with spreadsheet workflow:

CSV Export/Import:
- Download CSV button (appears after pulling instances)
- Upload CSV button (always visible)
- CSV format: neo4j_id, property1, property2, ...
- Proper CSV escaping (quotes, commas, newlines)
- Change detection (highlights modified cells)
- Merge uploaded data with existing instances

Push Confirmation Modal:
- Shows preview before pushing changes
- Displays count of updates vs creates
- User can confirm or cancel
- Reuses existing confirmation modal component

Workflow:
1. Pull instances from Neo4j → Table displays
2. Edit inline OR Download CSV → Edit in Excel → Upload CSV
3. Changed cells highlight in yellow
4. Click 'Push Changes' → Confirmation modal shows preview
5. Confirm → Pushes to Neo4j

Features:
✅ Download instances as CSV with neo4j_id
✅ Upload CSV to populate/update instances
✅ Inline editing still works (existing feature)
✅ Push preview shows change count
✅ Handles CSV edge cases (quotes, commas, newlines)
✅ Change tracking and highlighting

This enables the 'spreadsheet editor for knowledge graph' use case!

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…rite mode

This commit implements a complete data cleaning workflow for Neo4j knowledge
graphs through the spreadsheet interface, enabling users to:
1. Remove properties from label schema
2. Automatically update instance table (columns disappear)
3. Push with Overwrite mode to clean Neo4j nodes

**Frontend Changes (labels.html):**
- Added handlePropertyRemoval() function to clean instanceChanges when properties deleted
- Modified createPropertyRow() to track property names via data-prop-name attribute
- Updated saveLabel() to refresh instance table after schema changes
- Added Push Mode selection modal with Merge/Overwrite radio buttons
- Modified pushInstances() to support both merge and overwrite modes
- Overwrite mode builds complete property sets from schema and sends PUT requests

**Backend Changes:**
- Added PUT endpoint /api/labels/<name>/instances/<instance_id> in api_labels.py
- Implemented overwrite_label_instance() in label_service.py
- Uses Cypher SET n = {properties} to replace all properties (removes extras)

**Data Cleaning Workflow:**
1. User pulls instances from Neo4j
2. User removes unwanted properties from label schema in editor
3. User saves label → table updates (columns for removed properties disappear)
4. User selects Overwrite mode in push confirmation modal
5. Push removes properties not in schema from Neo4j nodes

This enables complete dataset cleaning by removing unwanted properties
from the knowledge graph while maintaining data integrity for schema-defined
properties.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Added null checks for property and relationship fields
- Added console logging for save payload and response
- Added error logging for failures
- This helps debug save button issues when editing labels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed issue where saveLabel tried to gather data from incoming relationship
rows which are display-only and don't have data-field inputs. This caused
errors and prevented the editor from switching back to read-only mode after save.

Now only queries relationships-container (outgoing, editable) and ignores
incoming-relationships-container (display-only).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Allows users to delete incoming relationships (relationships from other labels
pointing to this label) directly from the edit view.

**Features:**
- Added delete (×) button to each incoming relationship row in edit view
- Confirmation modal shows relationship details before deletion
- Automatically updates source label by removing the relationship
- Refreshes current label to show updated incoming relationships
- Returns to read-only mode after successful deletion

**Implementation:**
- deleteIncomingRelationship() fetches source label, removes relationship, saves
- Uses existing API endpoints (GET /api/labels/{name}, POST /api/labels)
- Incoming relationships automatically recompute after source label update
- No backend changes needed (uses existing label save logic)

This completes the data cleaning workflow by allowing users to clean up
both unwanted properties and unwanted relationships in their knowledge graph.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…rget label

Allows users to add incoming relationships (from other labels to this one)
directly from the target label's edit view, completing bidirectional
relationship management.

**Features:**
- Added 'Add Incoming Relationship' button in edit view
- Modal with source label dropdown and relationship type input
- Validates that relationship doesn't already exist
- Updates source label definition automatically
- Refreshes current label to show new incoming relationship
- Returns to read-only mode after successful addition

**Workflow:**
1. User views target label (e.g., 'Sample')
2. Clicks 'Add Incoming Relationship'
3. Selects source label (e.g., 'Experiment') from dropdown
4. Enters relationship type (e.g., 'HAS_SAMPLE')
5. Confirms → Updates Experiment to add: Experiment → [HAS_SAMPLE] → Sample
6. Sample refreshes → shows new incoming relationship

**Implementation:**
- addIncomingRelationship() fetches source label, adds relationship, saves
- Uses existing API endpoints (GET /api/labels/{name}, POST /api/labels)
- Duplicate relationship checking prevents errors
- Incoming relationships automatically recompute after source update

This completes bidirectional relationship management - users can now define
relationships from either the source or target label perspective.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…outgoing)

Refactored incoming relationship management to use inline editing with
editable rows (like outgoing relationships), instead of modal-based approach.
Now all changes are made in the editor and committed together with Save.

**Changes:**
- Incoming relationships now render as editable rows with dropdowns and inputs
- Added 'Add Incoming Relationship' button that adds an empty editable row
- Created createIncomingRelationshipRow() for editable incoming relationship UI
- Made saveLabel() async to handle incoming relationship changes
- Added applyIncomingRelationshipChanges() to compare and sync changes:
  - Finds added/removed incoming relationships
  - Updates source label definitions automatically
  - Removes old relationships from source labels
  - Adds new relationships to source labels
- Refreshes current label after save to show updated incoming relationships
- Editor closes after save (returns to read-only mode) as requested

**UX Improvements:**
- Consistent editing experience for both outgoing and incoming relationships
- All edits happen in-place with visual feedback
- Single Save button commits all changes at once
- No modals interrupting the editing flow
- Editor only closes when Save is clicked

**Workflow:**
1. Click Edit on a label
2. Add/remove/modify incoming relationships using dropdowns
3. Add/remove/modify outgoing relationships
4. Add/remove/modify properties
5. Click Save → All changes committed atomically
6. Editor closes, returns to read-only view

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Added 9 new tests covering all the new data cleaning workflow features:

**Overwrite Mode Tests:**
- test_overwrite_instance_removes_extra_properties - Validates PUT endpoint exists
- test_overwrite_endpoint_requires_properties - Validates required parameters
- test_overwrite_endpoint_validates_label_exists - Validates label existence check
- test_patch_endpoint_still_works_for_merge_mode - Ensures PATCH still works

**Property Removal Tests:**
- test_property_removal_from_schema - Validates property can be removed from schema
- test_property_removal_cascades_to_instances - Validates workflow pattern

**Incoming Relationships Tests:**
- test_incoming_relationships_computed_correctly - Validates dynamic computation
- test_incoming_relationships_updates_when_source_changes - Validates auto-updates
- test_multiple_incoming_relationships_from_different_sources - Validates multiple sources

**Test Results:**
- All 53 tests pass (29 existing + 9 new + 12 auto-lock + 3 instance count)
- Tests validate both API endpoints and business logic
- Tests use unique label names to avoid cross-test pollution
- Tests expect appropriate error codes when Neo4j not configured

**Coverage:**
✅ PUT /api/labels/<name>/instances/<id> endpoint (overwrite mode)
✅ PATCH /api/labels/<name>/instances/<id> endpoint (merge mode)
✅ Property removal from label schema
✅ Incoming relationship computation
✅ Incoming relationship updates when sources change
✅ Multiple incoming relationships from different sources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated references from 'Home page' to 'Settings page (landing page)' in
testing documentation to accurately reflect current application structure.

Changes:
- Updated UI selector documentation (line 210-211)
- Updated E2E test description for scan.spec.ts (line 275)
- Clarified that index.html now renders Settings page
- Updated nav-home description to indicate it's the Settings/landing page

Note: Old home page content was already migrated to Settings in previous work.
Obsolete tests already archived with _archive_ prefix.

Closes task:ui/refactor/remove-old-home-page-content

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@patchmemory patchmemory force-pushed the task/task-ui/labels/push-pull-instance-preview branch from 7eb0f21 to 85ec3cf Compare February 8, 2026 22:48
@patchmemory patchmemory merged commit 60c738d into main Feb 8, 2026
1 check passed
@patchmemory patchmemory deleted the task/task-ui/labels/push-pull-instance-preview branch February 8, 2026 22:52
@patchmemory patchmemory restored the task/task-ui/labels/push-pull-instance-preview branch February 8, 2026 23:04
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.

1 participant