Spatial Dashboard Requirements (Detailed)
Spatial Dashboard Requirements (Detailed)
1. Core Philosophy: Relationship-Driven Layout
The spatial dashboard is a dynamic and interactive visualization of the Plings object graph. Its core principle is that the UI layout is a direct and editable reflection of the spatial relationships stored in the Neo4j database.
Key Principles
- Visualization: The dashboard is a faithful visual representation of relationships stored in the database
- Interaction (WYSIWYG): Direct manipulation (drag-and-drop, resize, arrange) ↔ immediate GraphQL mutations
- Responsiveness: Optimistic updates for fluid UX; instant visual feedback then server reconciliation
Visual Metaphor
Think of the dashboard as a digital version of organizing physical objects on a table or in containers. Every visual arrangement has meaning and is stored persistently.
2. Responsive & Mobile-First Design
The interface must adapt seamlessly from phones to desktops while maintaining spatial relationship accuracy.
Breakpoints
- Mobile (< 768px): Stack view, simplified spatial representation
- Tablet (768px - 1024px): Grid view with basic spatial arrangement
- Desktop (> 1024px): Full spatial canvas with detailed positioning
Mobile Constraints
- Touch-friendly drag targets (min 44px)
- Simplified relationship types for mobile (contain/adjacent only)
- Progressive disclosure of complex spatial features
3. Data & State Management
Current Spatial Data Model
Based on the enhanced GraphQL schema (Updated 2025-07-03 08:17:03):
interface ObjectInstance {
id: string;
name: string;
location: string; // Current location (human-readable text)
spatialParent?: SpatialRef; // Direct container object
spatialChildren: ObjectInstance[]; // Objects contained in this object
spatialHierarchy: SpatialRef[]; // Path from object to root container
currentPlacement?: Placement; // Current location (structured)
normalPlacement?: Placement; // Expected location (structured)
positionalRelationships: PositionalRelationship[]; // Relative positioning relationships
}
interface PositionalRelationship {
relationshipType: 'NORMAL_IN' | 'NORMAL_LEFT_OF' | 'NORMAL_RIGHT_OF' | 'NORMAL_ABOVE' | 'NORMAL_UNDER' | 'NORMAL_ON' | 'NORMAL_ATTACHED_TO' | 'NORMAL_NEXT_TO' |
'CURRENT_IN' | 'CURRENT_LEFT_OF' | 'CURRENT_RIGHT_OF' | 'CURRENT_ABOVE' | 'CURRENT_UNDER' | 'CURRENT_ON' | 'CURRENT_ATTACHED_TO' | 'CURRENT_NEXT_TO' |
'IN' | 'TO_LEFT' | 'TO_RIGHT' | 'ABOVE' | 'BELOW' | 'SHOULD_BE_IN' | 'NONE'; // Legacy predicates for backward compatibility
relatedObject: SpatialRef;
properties?: {
distance?: number;
unit?: string;
confidence?: number;
measuredAt?: string;
};
}
interface SpatialRef {
id: string;
name: string;
type: string;
}
interface Placement {
id: string;
name: string;
type: string;
}
Neo4j Relationships - Enhanced Dual Spatial Predicates System
NORMAL Predicates (Where Objects Should Be)
The NORMAL_ predicates represent the expected or designated location/arrangement of objects - where they “belong” in an ideal organized state.
NORMAL_IN: Object’s designated container location- Example:
(:Keys)-[:NORMAL_IN]->(:KeyHook) - Used for: Misplacement detection, inventory auditing, expected location tracking
- Example:
NORMAL_LEFT_OF: Object’s expected position to the left of another object- Example:
(:Lamp)-[:NORMAL_LEFT_OF]->(:Computer) - Used for: Spatial arrangement planning, designated positioning
- Example:
NORMAL_RIGHT_OF: Object’s expected position to the right of another object- Example:
(:Mouse)-[:NORMAL_RIGHT_OF]->(:Computer) - Used for: Spatial arrangement planning, designated positioning
- Example:
NORMAL_ABOVE: Object’s expected position above another object- Example:
(:Shelf)-[:NORMAL_ABOVE]->(:Desk) - Used for: Vertical positioning planning, multi-level arrangements
- Example:
NORMAL_UNDER: Object’s expected position below another object- Example:
(:Footrest)-[:NORMAL_UNDER]->(:Chair) - Used for: Vertical positioning planning, stacking arrangements
- Example:
NORMAL_ON: Object’s expected placement on another object’s surface- Example:
(:Laptop)-[:NORMAL_ON]->(:Desk) - Used for: Surface placement planning, designated work arrangements
- Example:
NORMAL_ATTACHED_TO: Object’s expected attachment to another object- Example:
(:MonitorMount)-[:NORMAL_ATTACHED_TO]->(:Monitor) - Used for: Physical attachment planning, accessory organization
- Example:
NORMAL_NEXT_TO: Object’s expected adjacent placement (direction-neutral)- Example:
(:Coaster)-[:NORMAL_NEXT_TO]->(:Chair) - Used for: General proximity planning, paired object arrangements
- Example:
CURRENT Predicates (Where Objects Currently Are) - Future Implementation
The CURRENT_ predicates will represent the real-time, observed location of objects - where they actually are right now. This enables misplacement detection and location tracking.
CURRENT_IN: Object’s actual current container (real-time location tracking)CURRENT_LEFT_OF: Object’s actual current position to the left (real-time positioning)CURRENT_RIGHT_OF: Object’s actual current position to the right (real-time positioning)CURRENT_ABOVE: Object’s actual current position above (real-time positioning)CURRENT_UNDER: Object’s actual current position below (real-time positioning)CURRENT_ON: Object’s actual current surface placement (real-time positioning)CURRENT_ATTACHED_TO: Object’s actual current attachment (real-time positioning)CURRENT_NEXT_TO: Object’s actual current adjacent placement (real-time positioning)
Legacy Predicates (Backward Compatibility)
Legacy predicates are maintained for backward compatibility during the migration period:
IN: Maps toNORMAL_IN(containment relationship)TO_LEFT: Maps toNORMAL_LEFT_OF(left positioning)TO_RIGHT: Maps toNORMAL_RIGHT_OF(right positioning)ABOVE: Maps toNORMAL_ABOVE(above positioning)BELOW: Maps toNORMAL_UNDER(below positioning)SHOULD_BE_IN: Maps toNORMAL_IN(expected containment)
Relationship Properties (Enhanced with Metadata)
// Enhanced relationships can include spatial metadata
(:Object)-[:NORMAL_LEFT_OF {distance: 30, unit: "cm", confidence: 0.9, designated_at: timestamp()}]->(:Reference)
(:Object)-[:CURRENT_ABOVE {height_difference: 120, unit: "cm", measured_at: timestamp(), sensor_id: "motion_001"}]->(:Reference)
Migration Benefits
This dual predicate system enables powerful inventory management features:
- Misplacement Detection: Compare NORMAL_ vs CURRENT_ predicates to identify displaced objects
- Location Auditing: Track when objects deviate from their designated locations
- Automated Organization: Guide users to return objects to their NORMAL_ positions
- Inventory Intelligence: Analyze patterns in object displacement and usage
- Real-time Tracking: Monitor object movements and current positions
- Smart Notifications: Alert when important objects are not in their designated locations
State Management Strategy
- Primary State: Apollo cache with normalized relationships
- UI State: React state for canvas zoom, selection, drag operations
- Optimistic Updates: Immediate UI updates with server reconciliation
Data-loading Strategy (runtime)
The spatial dashboard follows a two-tier fetch model to balance fast initial rendering with rich, on-demand detail:
-
Initial list query —
GET_SPATIAL_DASHBOARD_DATA
Fired once whenSpatialDashboardmounts viauseSpatialHierarchy. It returns just enough data to build the hierarchy:id,name,mainImageUrl,spatialParent,spatialChildrensummaries,positionalRelationships, andstatuses.
This lightweight payload keeps the first paint fast (≈ N × a few hundred bytes). -
Lazy detail query —
GET_OBJECT_DETAILS_COMPLETE($objectId)
Triggered when a user opens an object’s detail modal. It supplies heavier fields—full image metadata,functionalRelationships,collections, property map, tags, etc. Apollo caches the response, so repeated openings are instant. -
Mutations & auto-refresh
The drag-and-drop actions callMOVE_OBJECT(forINmoves) orCREATE_SPATIAL_RELATIONSHIP(TO_LEFT,ABOVE, etc.). On success each mutation invokesrefetch(), re-executing the list query so the hierarchy stays authoritative.
Road-map: switch to aspatialRelationshipChangedsubscription to eliminate manual refetches. -
Future optimisation ideas
• Windowed queries that fetch only the visible subtree
• GraphQL@defer/@streamonce supported
• Fine-grained Apollo cache updates instead of full refetches
Note Early prototypes executed
GET_OBJECT_DETAILS_COMPLETEfor every object on page load, inflating payloads and slowing first paint. The current strategy adheres to the principle: fetch just enough to draw the list; fetch the rest only when requested.
Root Containers & Top-Level Navigation
A root container is any ObjectInstance that has no IN parent – in other words, it sits at the top of its own containment chain. When the Spatial Dashboard first loads, it queries all objects the signed-in user can read and filters for those without a spatialParent. These become the top-level cards you see (e.g. “My House”, “Summerhouse”, “Office Building”).
Key points for the UI:
- The person (user) is not modelled as a spatial node, so the view starts one level below “me”.
- Ownership is irrelevant here – the list shows every root container you have permission to read, even if it belongs to a different organisation (work vs personal).
- Clicking a root container drills down by following its
spatialChildren, building breadcrumbs from thespatialHierarchyarray.
For the formal definition of spatialParent, spatialHierarchy, and the Cypher query that finds roots, see the Spatial Relationships System (backend docs). The dashboard relies on those same fields exposed via GraphQL.
GraphQL Integration
# Queries (Current Implementation)
query GetObjectDetailsComplete($objectId: ID!) {
getObjectDetailsComplete(id: $objectId) {
id
name
location
spatialParent { id name type }
spatialChildren { id name type hasChildren }
spatialHierarchy { id name type }
currentPlacement { id name type }
normalPlacement { id name type }
}
}
query GetSpatialChildren($parentId: ID!, $limit: Int = 100) {
getSpatialChildren(parentId: $parentId, limit: $limit) {
id
name
type
mainImageUrl
hasChildren
}
}
# Mutations (Current Implementation)
mutation MoveObject($objectId: ID!, $newContainerId: ID!) {
moveObject(objectId: $objectId, newContainerId: $newContainerId) {
id
spatialParent { id name type }
spatialHierarchy { id name type }
}
}
# Mutations (Enhanced with Dropzone Support)
mutation CreateSpatialRelationship($objectId: ID!, $targetId: ID!, $relationship: SpatialRelationshipType!) {
createSpatialRelationship(objectId: $objectId, targetId: $targetId, relationship: $relationship) {
id
spatialParent { id name type }
spatialHierarchy { id name type }
positionalRelationships {
relationshipType
relatedObject { id name type }
}
}
}
mutation RemoveSpatialRelationship($objectId: ID!, $targetId: ID!, $relationship: SpatialRelationshipType!) {
removeSpatialRelationship(objectId: $objectId, targetId: $targetId, relationship: $relationship) {
success
}
}
enum SpatialRelationshipType {
# NORMAL predicates (where objects should be) - Primary system
NORMAL_IN
NORMAL_LEFT_OF
NORMAL_RIGHT_OF
NORMAL_ABOVE
NORMAL_UNDER
NORMAL_ON
NORMAL_ATTACHED_TO
NORMAL_NEXT_TO
# CURRENT predicates (where objects currently are) - Future implementation
CURRENT_IN
CURRENT_LEFT_OF
CURRENT_RIGHT_OF
CURRENT_ABOVE
CURRENT_UNDER
CURRENT_ON
CURRENT_ATTACHED_TO
CURRENT_NEXT_TO
# Legacy predicates (backward compatibility)
IN
TO_LEFT
TO_RIGHT
ABOVE
BELOW
SHOULD_BE_IN
}
# Future Subscriptions
subscription SpatialChanges($containerId: ID!) {
spatialRelationshipChanged(containerId: $containerId) {
objectId
newParentId
changeType # MOVED, ADDED, REMOVED
}
}
4. Dashboard Implementation Strategy
Technology Stack (Simplified)
- Layout: CSS Grid/Flexbox for responsive container layouts
- Drag & Drop: React DnD or native HTML5 drag API
- Animation: CSS transitions with optional Framer Motion for complex animations
- Canvas: Standard React components, no external canvas libraries needed
Component Architecture
interface DashboardLayer {
containerGrid: ContainerGrid;
objectCards: ObjectCard[];
breadcrumbNav: SpatialBreadcrumb;
dragPreview: DragPreview;
}
Layout Strategy
- Container-First Layout: Display containers as the primary organizational structure
- Object Grid Within Containers: Objects arranged in responsive grids within their containers
- Drag-and-Drop Movement: Objects can be dragged between containers
- Breadcrumb Navigation: Show spatial hierarchy for navigation
Object Card Design
- Desktop: 200px × 120px with image, name, status
- Mobile: 140px × 80px with essential info only
- Visual Hierarchy: Image, title, location, status indicator
Detailed Card Anatomy & Drag UX (v1.1)
-
Thumbnail sizing
• Root-level cards are now 220 × 180 px. Main image sits in a 180 × 112 px wrapper withobject-containso the whole photo is always visible (no cropping).
• All cards keep a fixed outer width so the grid remains predictable. -
Minimal overlay text
• Show name in a single line under the thumbnail (truncate with ellipsis).
• Remove the multiline description from the card; instead expose it as a tooltip (titleattribute or custom tooltip component) when hovering/tapping the card. -
Click behaviour
• Single click anywhere on the card (image or padding) opens the Object Details modal (already backed byGET_OBJECT_DETAILS_COMPLETE). -
Drag-and-drop visuals
• Main Cards: When dragging starts, the source card renders a ghost thumbnail pinned directly beneath the pointer:
– Size: 48 px × 48 px square.
– 70 % opacity.
– Small drop-shadow so it stands out on any background.
• Child Icons: Individual child preview icons (32×32px) are draggable with custom ghost: – Manual ghost tracking system (bypasses browser limitations) – Shows object image in 64×64px bordered container, or blue circle with first letter – Ghost follows mouse cursor precisely during drag operation – Multi-level event handling prevents premature drag termination • The original card remains in place with 20 % opacity until drop completes (standard ghost behaviour).
• This solves the mismatch where large thumbnails made it hard to tell exactly where the pointer (hit-test) is. -
Accessibility
•aria-labelon the draggable ghost = object name.
• Tooltip content is exposed viaaria-describedbyfor keyboard users. -
Status badges (optional)
• If the card shows status chips (e.g., “for_sale”, “broken”) they stack horizontally under the name, truncated if >2. -
Size guidelines & responsive grid | Breakpoint | Card outer size | Thumbnail wrapper | Notes | |————|—————–|——————-|——-| | ≥ 1280 px | 220 × 180 px | 180 × 112 px | Updated root card spec | | 768–1279 px| 180 × 148 px | 140 × 88 px | Tablet scale | | < 768 px | 140 × 116 px | 104 × 64 px | Mobile touch target ≥ 44 px |
-
Two-line title clamp
• Object names wrap to max two lines using CSSline-clamp-2; overflowing text is ellipsised.
• Font sizes:text-smfor root cards,text-xsfor children. -
Default-collapsed containers
• Containers render collapsed on first paint to reduce vertical scroll; users expand via chevron. -
Cross-browser drag ghost
• Custom 48 × 48 ghost set viadataTransfer.setDragImage.
• Safari workaround: create a temporary<img>element because Safari ignores non-image elements.
Styling & Interaction
Visual Design
- Containers: Rounded cards with subtle borders using design tokens
- Objects: Compact cards with hover states and drag indicators
- Drag Feedback: Visual feedback for valid/invalid drop targets
- Brand Integration: Use Plings design system consistently
Interaction Patterns
Drag & Drop with Dropzones (Primary Interaction)
Each object card displays multiple drop zones when another object is being dragged over it. The layout has been optimized to prevent conflicts between dropzones and child icons:
┌─────────────────────────────┐
│ ABOVE/TOP │
├─────────────────────────────┤
│ │ ┌─────────────┐ │ │
│LEFT│ │ IMAGE │ │RIGHT│
│ │ │ CENTER │ │ │
│ │ └─────────────┘ │ │
├─────────────────────────────┤
│ BELOW/BOTTOM BAR │ ← Distinct bar below image
├─────────────────────────────┤
│ Child Object Icons │ ← Clear space below
└─────────────────────────────┘
Dropzone Behaviors:
- CENTER: Creates
NORMAL_INrelationship (object goes inside this container)- Visual: Highlight main image area only (168×112px), show “Place inside” tooltip
- Position: Overlays only the main object image, not the entire card
- Result:
(:DraggedObject)-[:NORMAL_IN]->(DropTarget)
- LEFT: Creates
NORMAL_LEFT_OFspatial relationship- Visual: Highlight left zone, show “Place to the left” tooltip
- Result:
(:DraggedObject)-[:NORMAL_LEFT_OF]->(DropTarget)
- RIGHT: Creates
NORMAL_RIGHT_OFspatial relationship- Visual: Highlight right zone, show “Place to the right” tooltip
- Result:
(:DraggedObject)-[:NORMAL_RIGHT_OF]->(DropTarget)
- TOP: Creates
NORMAL_ABOVEspatial relationship- Visual: Highlight top zone, show “Place above” tooltip
- Result:
(:DraggedObject)-[:NORMAL_ABOVE]->(DropTarget)
- BOTTOM: Creates
NORMAL_UNDERspatial relationship- Visual: Highlight bottom bar (4px high) positioned between image and child icons
- Position: Distinct bar spanning card width, located immediately below main image
- Result:
(:DraggedObject)-[:NORMAL_UNDER]->(DropTarget)
Dropzone Visual Design:
- Inactive: Dropzones invisible until drag operation starts
- Active: Semi-transparent overlays (different colors per zone)
- Hover: Solid highlight with relationship type label
- Invalid: Red highlight with “Cannot place here” message
- Layout Optimization: CENTER zone limited to image area, BOTTOM zone as separate bar to prevent overlap with child icons
Additional Interactions
- Click Navigation: Click objects to open detail modal
- Container Drill-Down: Click containers to navigate into them
- Breadcrumb Navigation: Click breadcrumb levels to navigate up
- Context Menu: Right-click for additional relationship options
Hierarchical Navigation & Canvas Layout
This section formalises how the Spatial Dashboard behaves when the user navigates up/down the containment tree and how objects are visually arranged on the current level.
1. View scope & breadcrumbs
- Current container = any object whose
spatialChildrenare being rendered. - The breadcrumb at the top shows the full path (
spatialHierarchy) starting with the root container(s). Example:Me → My House → Living-room → Drawer 3.- Clicking a breadcrumb segment jumps directly to that container level.
- Dragging an object onto a breadcrumb segment moves it into that ancestor (updates
IN).
2. Root container display
- When the dashboard first loads it lists all root containers side-by-side (those without
spatialParent). Typical roots might be “My House”, “Summerhouse”, “Office Building”. - Each root is rendered using the same inner-canvas rules as any other container, so users can drag objects between root containers if permissions allow.
3. Inner canvas ordering rules (LEFT/RIGHT/ABOVE/BELOW)
- Objects whose positional predicates reference each other are placed on a shared inner canvas.
- X-axis order:
TO_LEFT/TO_RIGHTchain. If A isTO_LEFTof B we render A ▯ B. - Y-axis order:
ABOVE/BELOWchain. If C isABOVED we render C centred above D.
- X-axis order:
- Stand-alone objects (no predicates at this level) are rendered left-to-right in incoming order with extra horizontal spacing (
gap-x-8) to convey lack of relation.
4. Removing positional relationships
- Dropping an object onto empty space outside any inner canvas clears the positional predicate on that axis by calling
createOrMoveSpatialRelationshipwithrelationship: NONE(upsert behaviour). The backend resolver deletes any existingNORMAL_LEFT_OF/NORMAL_RIGHT_OF(X-axis) orNORMAL_ABOVE/NORMAL_UNDER(Y-axis) edge for that object. - Dropping onto the special centre zone of another object still invokes
moveObject(container change) as described earlier.
5. Moving up one level
- Dragging an object to empty space above the canvas (or onto a breadcrumb segment) removes its
INlink to the current container, effectively moving it up one level.
These rules complement the drag-and-drop behaviours already specified and ensure consistent navigation through the spatial hierarchy while keeping the layout intuitive.
Optimistic Movement & Roll-Back
Real-time UX demands that objects snap to their new position the instant the user drops them—long before the network round-trip finishes.
-
Local state update
•SpatialHierarchyViewmaintains a pendingOps map keyed by object-id → target relationship.
• OnonDrop, we mutate the localhierarchicalObjectstree immediately (or update Apollo cache viacache.modify) so the UI reflects the move instantly. -
GraphQL mutation with
optimisticResponse
•MOVE_OBJECT/CREATE_OR_MOVE_SPATIAL_RELATIONSHIP(upsert) are fired with anoptimisticResponsemirroring the expected server payload so Apollo’s cache aligns with the local change. -
Visual feedback while pending
• Card displays a subtle spinner or 50 % opacity state.
• Tooltip: “Saving…”
• Dropzones are disabled for that card until confirmation. -
Success path
• Server responds → pending flag cleared → spinner removed.
• Any additional server-side canonical data (e.g., updatedspatialHierarchy) overwrites optimistic cache. -
Error path / rollback
• If mutation returns an error or times out (30 s), UI shows toast “Move failed – reverting”.
• The cached change is reversed by either:
– Callingcache.evicton the object andrefetch(); or
– Manually restoring its previous parent/position stored inpendingOps. -
Concurrency rule
• Only one pending spatial operation per object. Additional drags on a pending object are disabled until server confirmation or rollback. -
Edge cases
• If rollback would place the object into a container that no longer exists (deleted in another tab), we refetch root containers and surface an error toast.
Implementation detail: Apollo’s built-in
optimisticResponsekeeps the local cache consistent, but standalone React state is acceptable if we later migrate away from Apollo.
Relationship Management
Primary Spatial Relationships (via Dropzones)
- Containment:
IN- Object is physically inside another - Positional:
TO_LEFT,TO_RIGHT,ABOVE,BELOW- Object is positioned relative to another - Expected Location:
SHOULD_BE_IN- Object’s designated home location
Advanced Relationship Options
- Set Expected Location: UI to set
SHOULD_BE_INrelationships - Misplacement Detection: Visual indicators when current ≠ expected location
- Relationship History: Track and display recent spatial changes
5. Performance Optimization
Rendering Optimization
- Virtualization: Only render visible containers and objects
- Lazy Loading: Load container contents on demand
- Pagination: Limit objects per container view
Data Optimization
- Incremental Loading: Load spatial data as needed
- Apollo Cache: Efficient caching and normalization
- Optimistic Updates: Immediate visual feedback
6. Accessibility
Keyboard Navigation
- Tab through objects and containers in logical order
- Arrow keys for navigation within containers
- Space to select, Enter to open details
Screen Reader Support
- Semantic markup for spatial relationships
- ARIA labels for container contents
- Alternative list view for screen readers
Implementation Phases
Phase 1: Core Spatial Dashboard with Dropzones (Current Priority)
- ✅ Display objects in their current containers
- ✅ Object detail modals with spatial information
- ✅ Dropzone System: Multi-zone drag-and-drop interface
- ✅ CENTER zone for
INrelationships - ✅ LEFT/RIGHT zones for
TO_LEFT/TO_RIGHTrelationships - ✅ TOP/BOTTOM zones for
ABOVE/BELOWrelationships - ✅ Visual feedback and tooltips for each dropzone
- ✅ Child Object Drag Support: Individual child icons can be dragged
- Custom ghost tracking with image or letter representation
- Smart dropzone visibility (excludes source card)
- Robust event handling to prevent premature drag termination
- Global cleanup mechanisms for stuck ghosts
- Child icons can be drop targets for NORMAL_IN relationships only
- ✅ Optimized Dropzone Layout: Refined positioning to eliminate conflicts
- CENTER zone limited to main image area only (168×112px)
- BOTTOM zone positioned as distinct bar between image and child icons
- Child icons placed below BOTTOM zone with clear visual hierarchy
- LEFT/RIGHT/TOP zones remain on card edges for positioning relationships
- ✅ CENTER zone for
- 🚧 Container navigation and breadcrumbs
- 🚧 Basic positional relationship display
Phase 2: Enhanced Spatial Features
- 🚧 Expected vs actual location comparison (
SHOULD_BE_IN) - 🚧 Misplacement detection and correction workflows
- ❌ Enhanced Dropzone Features:
- Relationship properties (distance, confidence)
- Context menu for relationship management
- Undo/redo for spatial changes
- ❌ Bulk move operations
- ❌ Search and filter within spatial view
Phase 3: Advanced Spatial Intelligence
- ❌ Real-time collaboration with subscriptions
- ❌ Smart Spatial Suggestions:
- Auto-suggest relationships based on proximity
- Pattern recognition for common arrangements
- Spatial conflict detection and resolution
- ❌ Advanced visualization options (different layout algorithms)
- ❌ Batch operations and spatial workflows
Implementation Notes
- Dropzone Priority: The 5-zone dropzone system is the core interaction model
- Progressive Enhancement: Start with basic dropzones, add properties and metadata in Phase 2
- Mobile Adaptation: Simplify to 3 zones (center, left, right) on mobile devices
- Accessibility: Ensure keyboard navigation and screen reader support for all dropzones
Appendix A: Technical Safeguards
Relationship Validation Rules
- Circular Containment Prevention: Object A cannot contain B if B contains A (direct or indirect)
- Single Location Enforcement: Object can only be
INone container at a time - Self-Containment Prevention: Object cannot contain itself
Error Handling
- Client-side Validation: Check constraints before mutation
- Server-side Validation: Final authority on relationship validity
- Rollback Strategy: Optimistic updates with automatic rollback on conflict
- User Feedback: Clear error messages with suggested corrections
Appendix B: Spatial Relationships (Enhanced Implementation)
Primary Relationships - NORMAL Predicates (Current Implementation)
NORMAL_IN: Expected containment relationship(:Object)-[:NORMAL_IN]->(:Container)- Used for designated location tracking and misplacement detection
NORMAL_LEFT_OF: Expected left positioning(:Object)-[:NORMAL_LEFT_OF]->(:Reference)- Used for designated spatial arrangement
NORMAL_RIGHT_OF: Expected right positioning(:Object)-[:NORMAL_RIGHT_OF]->(:Reference)- Used for designated spatial arrangement
NORMAL_ABOVE: Expected above positioning(:Object)-[:NORMAL_ABOVE]->(:Reference)- Used for designated vertical arrangement
NORMAL_UNDER: Expected below positioning(:Object)-[:NORMAL_UNDER]->(:Reference)- Used for designated vertical arrangement
Future Relationships - CURRENT Predicates (Planned Implementation)
CURRENT_IN: Actual current containment relationship(:Object)-[:CURRENT_IN]->(:Container)- Used for real-time location tracking
CURRENT_LEFT_OF: Actual current left positioningCURRENT_RIGHT_OF: Actual current right positioningCURRENT_ABOVE: Actual current above positioningCURRENT_UNDER: Actual current below positioning
Legacy Relationships (Backward Compatibility)
IN: Maps toNORMAL_IN(legacy containment)TO_LEFT: Maps toNORMAL_LEFT_OF(legacy left positioning)TO_RIGHT: Maps toNORMAL_RIGHT_OF(legacy right positioning)ABOVE: Maps toNORMAL_ABOVE(legacy above positioning)BELOW: Maps toNORMAL_UNDER(legacy below positioning)SHOULD_BE_IN: Maps toNORMAL_IN(legacy expected containment)
Additional Spatial Predicates (Future Consideration)
NORMAL_NEXT_TO: Adjacent positioningNORMAL_ON: Surface placementNORMAL_ATTACHED_TO: Physical attachment
Note: Implementation prioritizes NORMAL_ predicates for designated location tracking, with CURRENT_ predicates planned for real-time position monitoring.