Secondary Manager Relationships
Overview
Secondary manager relationships represent non-primary reporting lines between people in an org chart. These include dotted-line managers, advisory roles, committee memberships, project-based reporting, and mentorship connections.
Unlike primary manager relationships (stored as managerId on each person), secondary relationships are stored in a separate org_chart_relationships table and rendered visually as dashed lines or text sections depending on the template.
Database Schema
org_chart_relationships table
| Column | Type | Description |
|---|---|---|
id | UUID | Primary key |
org_chart_id | UUID | FK to org_charts |
person_id | UUID | FK to org_chart_people (from) |
related_person_id | UUID | FK to org_chart_people (to) |
relationship_type | TEXT | One of: dotted_line, advisory, committee, project, mentor |
label | TEXT | Optional human-readable label (e.g., βBudget Oversightβ) |
created_at | TIMESTAMPTZ | Auto-set |
API Endpoints
Relationships are fetched and passed to templates automatically when generating org charts:
- GET
/api/orgcharts/:id/people- Returns people and relationships - POST
/api/orgcharts/:id/relationships- Create a relationship - DELETE
/api/orgcharts/:id/relationships/:relId- Remove a relationship
The API transforms snake_case DB fields to camelCase at the boundary:
person_id->personIdrelated_person_id->relatedPersonIdrelationship_type->relationshipType
Template Support Matrix
| Template | Rendering Strategy | supportsDottedLines |
|---|---|---|
| top-down-tree | SVG overlay | true |
| horizontal-tree | SVG overlay | true |
| photo-cards | SVG overlay | true |
| detailed-cards | SVG overlay | true |
| indented-list | Text section | true |
| interactive-collapsible | Text section | true |
| compact-cards | Text section | true |
| condensed-text | Text section | true |
| executive-profile | Text section | true |
| department-grouped | Text section (existing) | true |
| civic-accessible | N/A (redirect) | false |
| radial | N/A (redirect) | false |
Rendering Approaches
SVG Overlay (Tree/Visual Templates)
Used by templates that render nodes in a visual hierarchy layout.
How it works:
- Each person node in the HTML gets a
data-person-idattribute - After page load, client-side JavaScript finds matching nodes and draws dashed SVG paths between them
- Paths are quadratic bezier curves with arrow markers at the endpoints
- A visual legend shows which line colors map to which relationship types
- A visually-hidden (
sr-only) summary provides the same data for screen readers
Components:
RELATIONSHIP_OVERLAY_CSS- Styles for the SVG overlay, legend, and screen-reader summarybuildRelationshipOverlayJs()- Client JS that draws the dashed linesbuildRelationshipLegendHtml()- Color-coded legendbuildScreenReaderRelationshipSummary()- Accessible text alternative
Behavior:
- Lines redraw on window resize
- Lines redraw on
toggleevents (for collapsible templates) - Hidden nodes (collapsed sections) are skipped
- Lines have 70% opacity to avoid obscuring content
Text Section (Card/Grid/Text Templates)
Used by templates where nodes arenβt positioned in a spatial hierarchy.
How it works:
- A βSecondary Relationshipsβ
<section>is appended to the main content - Each relationship is listed with names, direction arrows, and a colored type badge
- Fully accessible without JavaScript
Components:
buildRelationshipTextSection()- Generates the HTML section
Relationship Types and Colors
| Type | Color | Hex | Use Case |
|---|---|---|---|
| dotted_line | Violet | #7c3aed | Secondary reporting line |
| advisory | Blue | #2563eb | Advisory/consulting role |
| committee | Orange | #ea580c | Committee membership |
| project | Pink | #db2777 | Project-based reporting |
| mentor | Amber | #d97706 | Mentorship relationship |
Controlling Visibility
Relationships are only rendered when both conditions are met:
options.showDottedLinesistrue(set by user in chart options)relationships.length > 0(there are actual relationships to show)
When showDottedLines is false, no relationship rendering occurs regardless of data.
Shared Utilities
All relationship rendering utilities live in workers/api/src/utils/html.ts:
RELATIONSHIP_OVERLAY_CSS- CSS constantserializeRelationshipsJson()- Converts relationships to JSON for client JSbuildRelationshipOverlayJs()- SVG overlay JavaScriptbuildRelationshipTextSection()- Text section HTMLbuildRelationshipLegendHtml()- Visual legend HTMLbuildScreenReaderRelationshipSummary()- Screen reader HTMLbuildPersonById()- Helper to create person lookup map
Known Limitations
- SVG overlay positioning - Lines connect to node centers and use edge detection, but complex overlapping layouts may produce crossing lines
- Zoom interaction - SVG overlay redraws on resize but may briefly misalign during zoom animation
- Print - SVG overlay is hidden in print mode (
@media print); only screen reader summary persists - Performance - For charts with many relationships (50+), SVG rendering may cause brief layout shifts on load
Troubleshooting
Lines not appearing
- Verify
showDottedLinesistruein the chart options - Check that relationships exist in the database for this org chart
- Confirm both
personIdandrelatedPersonIdreference valid people in the chart - Check browser console for JavaScript errors
Lines pointing to wrong positions
- Ensure
data-person-idattributes are present on node elements - Check for duplicate person IDs in the data
Screen reader not announcing relationships
- The
sr-onlysection should contain relationship data - Verify
role="complementary"is present on the hidden section