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
  • 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
  • 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
  • NORMAL_ABOVE: Object’s expected position above another object
    • Example: (:Shelf)-[:NORMAL_ABOVE]->(:Desk)
    • Used for: Vertical positioning planning, multi-level arrangements
  • NORMAL_UNDER: Object’s expected position below another object
    • Example: (:Footrest)-[:NORMAL_UNDER]->(:Chair)
    • Used for: Vertical positioning planning, stacking arrangements
  • NORMAL_ON: Object’s expected placement on another object’s surface
    • Example: (:Laptop)-[:NORMAL_ON]->(:Desk)
    • Used for: Surface placement planning, designated work arrangements
  • NORMAL_ATTACHED_TO: Object’s expected attachment to another object
    • Example: (:MonitorMount)-[:NORMAL_ATTACHED_TO]->(:Monitor)
    • Used for: Physical attachment planning, accessory organization
  • NORMAL_NEXT_TO: Object’s expected adjacent placement (direction-neutral)
    • Example: (:Coaster)-[:NORMAL_NEXT_TO]->(:Chair)
    • Used for: General proximity planning, paired object arrangements

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 to NORMAL_IN (containment relationship)
  • TO_LEFT: Maps to NORMAL_LEFT_OF (left positioning)
  • TO_RIGHT: Maps to NORMAL_RIGHT_OF (right positioning)
  • ABOVE: Maps to NORMAL_ABOVE (above positioning)
  • BELOW: Maps to NORMAL_UNDER (below positioning)
  • SHOULD_BE_IN: Maps to NORMAL_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:

  1. Misplacement Detection: Compare NORMAL_ vs CURRENT_ predicates to identify displaced objects
  2. Location Auditing: Track when objects deviate from their designated locations
  3. Automated Organization: Guide users to return objects to their NORMAL_ positions
  4. Inventory Intelligence: Analyze patterns in object displacement and usage
  5. Real-time Tracking: Monitor object movements and current positions
  6. 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:

  1. Initial list query — GET_SPATIAL_DASHBOARD_DATA
    Fired once when SpatialDashboard mounts via useSpatialHierarchy. It returns just enough data to build the hierarchy: id, name, mainImageUrl, spatialParent, spatialChildren summaries, positionalRelationships, and statuses.
    This lightweight payload keeps the first paint fast (≈ N × a few hundred bytes).

  2. 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.

  3. Mutations & auto-refresh
    The drag-and-drop actions call MOVE_OBJECT (for IN moves) or CREATE_SPATIAL_RELATIONSHIP (TO_LEFT, ABOVE, etc.). On success each mutation invokes refetch(), re-executing the list query so the hierarchy stays authoritative.
    Road-map: switch to a spatialRelationshipChanged subscription to eliminate manual refetches.

  4. Future optimisation ideas
    • Windowed queries that fetch only the visible subtree
    • GraphQL @defer/@stream once supported
    • Fine-grained Apollo cache updates instead of full refetches

Note Early prototypes executed GET_OBJECT_DETAILS_COMPLETE for 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:

  1. The person (user) is not modelled as a spatial node, so the view starts one level below “me”.
  2. 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).
  3. Clicking a root container drills down by following its spatialChildren, building breadcrumbs from the spatialHierarchy array.

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

  1. Container-First Layout: Display containers as the primary organizational structure
  2. Object Grid Within Containers: Objects arranged in responsive grids within their containers
  3. Drag-and-Drop Movement: Objects can be dragged between containers
  4. 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)

  1. Thumbnail sizing
    • Root-level cards are now 220 × 180 px. Main image sits in a 180 × 112 px wrapper with object-contain so the whole photo is always visible (no cropping).
    • All cards keep a fixed outer width so the grid remains predictable.

  2. 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 (title attribute or custom tooltip component) when hovering/tapping the card.

  3. Click behaviour
    • Single click anywhere on the card (image or padding) opens the Object Details modal (already backed by GET_OBJECT_DETAILS_COMPLETE).

  4. 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.

  5. Accessibility
    aria-label on the draggable ghost = object name.
    • Tooltip content is exposed via aria-describedby for keyboard users.

  6. Status badges (optional)
    • If the card shows status chips (e.g., “for_sale”, “broken”) they stack horizontally under the name, truncated if >2.

  7. 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 |

  8. Two-line title clamp
    • Object names wrap to max two lines using CSS line-clamp-2; overflowing text is ellipsised.
    • Font sizes: text-sm for root cards, text-xs for children.

  9. Default-collapsed containers
    • Containers render collapsed on first paint to reduce vertical scroll; users expand via chevron.

  10. Cross-browser drag ghost
    • Custom 48 × 48 ghost set via dataTransfer.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_IN relationship (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_OF spatial relationship
    • Visual: Highlight left zone, show “Place to the left” tooltip
    • Result: (:DraggedObject)-[:NORMAL_LEFT_OF]->(DropTarget)
  • RIGHT: Creates NORMAL_RIGHT_OF spatial relationship
    • Visual: Highlight right zone, show “Place to the right” tooltip
    • Result: (:DraggedObject)-[:NORMAL_RIGHT_OF]->(DropTarget)
  • TOP: Creates NORMAL_ABOVE spatial relationship
    • Visual: Highlight top zone, show “Place above” tooltip
    • Result: (:DraggedObject)-[:NORMAL_ABOVE]->(DropTarget)
  • BOTTOM: Creates NORMAL_UNDER spatial 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 spatialChildren are 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_RIGHT chain. If A is TO_LEFT of B we render A ▯ B.
    • Y-axis order: ABOVE/BELOW chain. If C is ABOVE D we render C centred above D.
  • 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 createOrMoveSpatialRelationship with relationship: NONE (upsert behaviour). The backend resolver deletes any existing NORMAL_LEFT_OF / NORMAL_RIGHT_OF (X-axis) or NORMAL_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 IN link 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.

  1. Local state update
    SpatialHierarchyView maintains a pendingOps map keyed by object-id → target relationship.
    • On onDrop, we mutate the local hierarchicalObjects tree immediately (or update Apollo cache via cache.modify) so the UI reflects the move instantly.

  2. GraphQL mutation with optimisticResponse
    MOVE_OBJECT / CREATE_OR_MOVE_SPATIAL_RELATIONSHIP (upsert) are fired with an optimisticResponse mirroring the expected server payload so Apollo’s cache aligns with the local change.

  3. Visual feedback while pending
    • Card displays a subtle spinner or 50 % opacity state.
    • Tooltip: “Saving…”
    • Dropzones are disabled for that card until confirmation.

  4. Success path
    • Server responds → pending flag cleared → spinner removed.
    • Any additional server-side canonical data (e.g., updated spatialHierarchy) overwrites optimistic cache.

  5. 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:
    – Calling cache.evict on the object and refetch(); or
    – Manually restoring its previous parent/position stored in pendingOps.

  6. Concurrency rule
    • Only one pending spatial operation per object. Additional drags on a pending object are disabled until server confirmation or rollback.

  7. 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 optimisticResponse keeps 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_IN relationships
  • 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 IN relationships
    • ✅ LEFT/RIGHT zones for TO_LEFT/TO_RIGHT relationships
    • ✅ TOP/BOTTOM zones for ABOVE/BELOW relationships
    • ✅ 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
  • 🚧 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

  1. Circular Containment Prevention: Object A cannot contain B if B contains A (direct or indirect)
  2. Single Location Enforcement: Object can only be IN one container at a time
  3. 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 positioning
  • CURRENT_RIGHT_OF: Actual current right positioning
  • CURRENT_ABOVE: Actual current above positioning
  • CURRENT_UNDER: Actual current below positioning

Legacy Relationships (Backward Compatibility)

  • IN: Maps to NORMAL_IN (legacy containment)
  • TO_LEFT: Maps to NORMAL_LEFT_OF (legacy left positioning)
  • TO_RIGHT: Maps to NORMAL_RIGHT_OF (legacy right positioning)
  • ABOVE: Maps to NORMAL_ABOVE (legacy above positioning)
  • BELOW: Maps to NORMAL_UNDER (legacy below positioning)
  • SHOULD_BE_IN: Maps to NORMAL_IN (legacy expected containment)

Additional Spatial Predicates (Future Consideration)

  • NORMAL_NEXT_TO: Adjacent positioning
  • NORMAL_ON: Surface placement
  • NORMAL_ATTACHED_TO: Physical attachment

Note: Implementation prioritizes NORMAL_ predicates for designated location tracking, with CURRENT_ predicates planned for real-time position monitoring.