diff --git a/dev b/dev index ad6f67f..fa3e22d 160000 --- a/dev +++ b/dev @@ -1 +1 @@ -Subproject commit ad6f67fbedb7d04036c5a19ce8cbad949bab692e +Subproject commit fa3e22d6a59b334aa36ff5596161bf0a87fe6f69 diff --git a/docs/testing.md b/docs/testing.md index 6d763f7..a81e9dd 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -201,14 +201,14 @@ Stable hooks are provided via `data-testid` attributes on key elements: - Header/nav/main in `scidk/ui/templates/base.html`: - `data-testid="header"` - Main header element - `data-testid="nav"` - Navigation container - - `data-testid="nav-home"` - Home link + - `data-testid="nav-home"` - Home/Settings link (landing page) - `data-testid="nav-files"` - Files link - `data-testid="nav-maps"` - Maps link - `data-testid="nav-chats"` - Chats link - `data-testid="nav-settings"` - Settings link - `data-testid="main"` - Main content area -- Home page in `scidk/ui/templates/index.html`: - - `data-testid="home-recent-scans"` - Recent scans section +- Settings page (landing page) in `scidk/ui/templates/index.html`: + - Settings sections with various configuration options - Files page in `scidk/ui/templates/datasets.html`: - `data-testid="files-root"` - Root container - `data-testid="files-title"` - Page title @@ -272,7 +272,7 @@ New API contracts added under `tests/contracts/test_api_contracts.py`: New Playwright specs: - `e2e/browse.spec.ts`: navigates to Files and verifies stable hooks, no console errors -- `e2e/scan.spec.ts`: posts `/api/scan` for a temp directory and verifies the Home page lists it +- `e2e/scan.spec.ts`: posts `/api/scan` for a temp directory and verifies scan completion ### How to Run New Tests diff --git a/scidk/services/label_service.py b/scidk/services/label_service.py index 221ba0a..abce1e8 100644 --- a/scidk/services/label_service.py +++ b/scidk/services/label_service.py @@ -713,3 +713,59 @@ def update_label_instance(self, name: str, instance_id: str, property_name: str, 'status': 'error', 'error': str(e) } + + def overwrite_label_instance(self, name: str, instance_id: str, properties: Dict[str, Any]) -> Dict[str, Any]: + """ + Overwrite all properties of a label instance in Neo4j. + This removes any properties not in the provided dictionary. + + Args: + name: Label name + instance_id: Neo4j element ID + properties: Complete set of properties to set (removes all others) + + Returns: + Dict with status and updated instance + """ + label_def = self.get_label(name) + if not label_def: + raise ValueError(f"Label '{name}' not found") + + try: + from .neo4j_client import get_neo4j_client + neo4j_client = get_neo4j_client() + + if not neo4j_client: + raise Exception("Neo4j client not configured") + + # Use SET n = {properties} to overwrite all properties + # This removes any properties not in the provided dict + query = f""" + MATCH (n:{name}) + WHERE elementId(n) = $instance_id + SET n = $properties + RETURN elementId(n) as id, properties(n) as properties + """ + + results = neo4j_client.execute_write(query, { + 'instance_id': instance_id, + 'properties': properties + }) + + if not results: + raise Exception(f"Instance with ID '{instance_id}' not found") + + instance = { + 'id': results[0].get('id'), + 'properties': results[0].get('properties', {}) + } + + return { + 'status': 'success', + 'instance': instance + } + except Exception as e: + return { + 'status': 'error', + 'error': str(e) + } diff --git a/scidk/ui/templates/labels.html b/scidk/ui/templates/labels.html index c5eef2a..19789b6 100644 --- a/scidk/ui/templates/labels.html +++ b/scidk/ui/templates/labels.html @@ -451,6 +451,7 @@

Incoming Relationships

No incoming relationships
+
@@ -466,10 +467,14 @@

Instances

+ +
+ +
Click "Pull from Neo4j" to load instances
@@ -560,6 +565,46 @@
Import Schema
+ + +