|
| 1 | +# Session/Activity Visual Indicators |
| 2 | + |
| 3 | +**Feature:** Colored dots to visually identify CustomerSession and ActivitySession groupings in webhook events |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +Events in the webhook inspector now display two colored dots that help identify which events belong to the same session and activity. This makes it easy to visually group related events without reading session IDs. |
| 8 | + |
| 9 | +## Visual Design |
| 10 | + |
| 11 | +Each event shows up to two colored dots: |
| 12 | + |
| 13 | +``` |
| 14 | +┌─────────────────────────────────────────┐ |
| 15 | +│ TPS.SessionInfo │ |
| 16 | +│ Oct 2, 2025, 3:45:12 PM │ |
| 17 | +│ ● ● ← Session indicators │ |
| 18 | +│ ↑ ↑ │ |
| 19 | +│ │ └─ Activity Session (green) │ |
| 20 | +│ └─── Customer Session (blue) │ |
| 21 | +└─────────────────────────────────────────┘ |
| 22 | +``` |
| 23 | + |
| 24 | +### Dot Meanings |
| 25 | + |
| 26 | +- **First dot (left):** CustomerSession |
| 27 | + - All events with the same CustomerSession.Id have the same color |
| 28 | + - A customer session can contain 0 or more activities |
| 29 | + |
| 30 | +- **Second dot (right):** ActivitySession |
| 31 | + - All events with the same ActivitySession.Id have the same color |
| 32 | + - An activity is a subset of a customer session |
| 33 | + |
| 34 | +### Color Assignment |
| 35 | + |
| 36 | +Colors are automatically assigned from a palette of 10 distinct colors: |
| 37 | +1. Blue (#3b82f6) |
| 38 | +2. Green (#10b981) |
| 39 | +3. Amber (#f59e0b) |
| 40 | +4. Red (#ef4444) |
| 41 | +5. Violet (#8b5cf6) |
| 42 | +6. Pink (#ec4899) |
| 43 | +7. Cyan (#06b6d4) |
| 44 | +8. Orange (#f97316) |
| 45 | +9. Lime (#84cc16) |
| 46 | +10. Indigo (#6366f1) |
| 47 | + |
| 48 | +Colors are assigned in order as new session IDs are encountered. If more than 10 sessions exist, colors cycle through the palette. |
| 49 | + |
| 50 | +## Implementation |
| 51 | + |
| 52 | +### Session ID Extraction |
| 53 | + |
| 54 | +**File:** `src/components/WebhookInspector.tsx` (lines 5-32) |
| 55 | + |
| 56 | +```typescript |
| 57 | +const getSessionIds = (e: EventItem): { customerSessionId?: string; activitySessionId?: string } => { |
| 58 | + const raw = e.raw as any; |
| 59 | + const data = raw?.data || raw; |
| 60 | + |
| 61 | + // Extract CustomerSession.Id from various possible locations |
| 62 | + const customerSessionId = |
| 63 | + data?.CustomerSession?.Id || |
| 64 | + data?.common?.CustomerSession?.Id || |
| 65 | + raw?.common?.CustomerSession?.Id; |
| 66 | + |
| 67 | + // Extract ActivitySession.Id from various possible locations |
| 68 | + const activitySessionId = |
| 69 | + data?.ActivitySession?.Id || |
| 70 | + data?.common?.ActivitySession?.Id || |
| 71 | + raw?.common?.ActivitySession?.Id; |
| 72 | + |
| 73 | + return { customerSessionId, activitySessionId }; |
| 74 | +}; |
| 75 | +``` |
| 76 | + |
| 77 | +### Color Assignment Logic |
| 78 | + |
| 79 | +**File:** `src/components/WebhookInspector.tsx` (lines 34-44) |
| 80 | + |
| 81 | +```typescript |
| 82 | +const getColorForId = (id: string | undefined, colorMap: Map<string, string>): string | null => { |
| 83 | + if (!id) return null; |
| 84 | + |
| 85 | + if (!colorMap.has(id)) { |
| 86 | + // Assign a color based on the current size of the map |
| 87 | + const colorIndex = colorMap.size % SESSION_COLORS.length; |
| 88 | + colorMap.set(id, SESSION_COLORS[colorIndex]); |
| 89 | + } |
| 90 | + |
| 91 | + return colorMap.get(id) || null; |
| 92 | +}; |
| 93 | +``` |
| 94 | + |
| 95 | +### State Management |
| 96 | + |
| 97 | +Color maps are stored in React refs to persist across renders: |
| 98 | + |
| 99 | +```typescript |
| 100 | +const customerSessionColors = React.useRef(new Map<string, string>()).current; |
| 101 | +const activitySessionColors = React.useRef(new Map<string, string>()).current; |
| 102 | +``` |
| 103 | + |
| 104 | +### Rendering |
| 105 | + |
| 106 | +**File:** `src/components/WebhookInspector.tsx` (lines 291-320) |
| 107 | + |
| 108 | +Each event extracts session IDs, gets colors, and renders dots: |
| 109 | + |
| 110 | +```tsx |
| 111 | +{filtered.map((e, idx) => { |
| 112 | + const { customerSessionId, activitySessionId } = getSessionIds(e); |
| 113 | + const customerColor = getColorForId(customerSessionId, customerSessionColors); |
| 114 | + const activityColor = getColorForId(activitySessionId, activitySessionColors); |
| 115 | + |
| 116 | + return ( |
| 117 | + <li className="webhook-event-item"> |
| 118 | + <div className="event-type">{e.eventType}</div> |
| 119 | + <div className="event-meta">{new Date(e.timestamp).toLocaleString()}</div> |
| 120 | + <div className="event-session-indicators"> |
| 121 | + {customerColor && <div className="session-dot" style={{ backgroundColor: customerColor }} />} |
| 122 | + {activityColor && <div className="session-dot" style={{ backgroundColor: activityColor }} />} |
| 123 | + </div> |
| 124 | + </li> |
| 125 | + ); |
| 126 | +})} |
| 127 | +``` |
| 128 | + |
| 129 | +### CSS Styling |
| 130 | + |
| 131 | +**File:** `src/components/WebhookInspector.css` |
| 132 | + |
| 133 | +```css |
| 134 | +.event-session-indicators{ |
| 135 | + display:flex; |
| 136 | + gap:6px; |
| 137 | + margin-top:6px; |
| 138 | + align-items:center |
| 139 | +} |
| 140 | + |
| 141 | +.session-dot{ |
| 142 | + width:10px; |
| 143 | + height:10px; |
| 144 | + border-radius:50%; |
| 145 | + border:1px solid rgba(0,0,0,0.1) |
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | +## Usage Examples |
| 150 | + |
| 151 | +### Single Session, Multiple Activities |
| 152 | + |
| 153 | +``` |
| 154 | +Event 1: ● ● (blue, green) - Session A, Activity 1 |
| 155 | +Event 2: ● ● (blue, green) - Session A, Activity 1 |
| 156 | +Event 3: ● ● (blue, amber) - Session A, Activity 2 |
| 157 | +Event 4: ● ● (blue, amber) - Session A, Activity 2 |
| 158 | +``` |
| 159 | + |
| 160 | +All events share the same CustomerSession (blue dot), but activities 1 and 2 have different colors. |
| 161 | + |
| 162 | +### Multiple Sessions |
| 163 | + |
| 164 | +``` |
| 165 | +Event 1: ● ● (blue, green) - Session A, Activity 1 |
| 166 | +Event 2: ● ● (blue, green) - Session A, Activity 1 |
| 167 | +Event 3: ● ● (amber, red) - Session B, Activity 3 |
| 168 | +Event 4: ● ● (amber, red) - Session B, Activity 3 |
| 169 | +``` |
| 170 | + |
| 171 | +Different sessions have completely different color pairs. |
| 172 | + |
| 173 | +### Events Without Sessions |
| 174 | + |
| 175 | +If an event doesn't have CustomerSession or ActivitySession data, no dots are shown for those missing values: |
| 176 | + |
| 177 | +``` |
| 178 | +Event 1: ● (blue only) - Has CustomerSession, no ActivitySession |
| 179 | +Event 2: (no dots) - No session data |
| 180 | +Event 3: ● ● (blue, green) - Both sessions present |
| 181 | +``` |
| 182 | + |
| 183 | +## Tooltip Information |
| 184 | + |
| 185 | +Hovering over a dot shows the actual session ID: |
| 186 | + |
| 187 | +- **CustomerSession dot:** "Customer Session: a3b5c7d9-..." |
| 188 | +- **ActivitySession dot:** "Activity Session: f1e2d3c4-..." |
| 189 | + |
| 190 | +This helps when you need to reference the actual ID values. |
| 191 | + |
| 192 | +## Benefits |
| 193 | + |
| 194 | +✅ **Visual grouping** - Quickly identify related events without reading IDs |
| 195 | +✅ **Session boundaries** - Easily spot when a new session starts |
| 196 | +✅ **Activity transitions** - See when activities change within a session |
| 197 | +✅ **Pattern recognition** - Identify event sequences by color patterns |
| 198 | +✅ **Debugging** - Trace event flow through sessions and activities |
| 199 | + |
| 200 | +## Migration from Bay Display |
| 201 | + |
| 202 | +**Previous:** Each event showed "Bay: X" text |
| 203 | +**Now:** Events show session/activity colored dots |
| 204 | + |
| 205 | +The bay information is still available in the event data when you select an event for preview. The session indicators provide more useful grouping information at a glance. |
| 206 | + |
| 207 | +## Event Data Structure |
| 208 | + |
| 209 | +Session IDs are extracted from the `common` metadata in webhook events: |
| 210 | + |
| 211 | +```json |
| 212 | +{ |
| 213 | + "eventType": "TPS.SessionInfo", |
| 214 | + "data": { |
| 215 | + "common": { |
| 216 | + "CustomerSession": { |
| 217 | + "Id": "a3b5c7d9-e1f2-4a5b-8c9d-0e1f2a3b4c5d" |
| 218 | + }, |
| 219 | + "ActivitySession": { |
| 220 | + "Id": "f1e2d3c4-b5a6-4c7d-8e9f-0a1b2c3d4e5f" |
| 221 | + } |
| 222 | + } |
| 223 | + } |
| 224 | +} |
| 225 | +``` |
| 226 | + |
| 227 | +Or from the root level: |
| 228 | + |
| 229 | +```json |
| 230 | +{ |
| 231 | + "eventType": "TPS.Live.OnStrokeCompletedEvent", |
| 232 | + "common": { |
| 233 | + "CustomerSession": { "Id": "..." }, |
| 234 | + "ActivitySession": { "Id": "..." } |
| 235 | + } |
| 236 | +} |
| 237 | +``` |
| 238 | + |
| 239 | +## Testing |
| 240 | + |
| 241 | +1. **Send multiple events in the same session** |
| 242 | + - All should have the same CustomerSession dot color |
| 243 | + |
| 244 | +2. **Start a new activity within the same session** |
| 245 | + - CustomerSession dot color stays the same |
| 246 | + - ActivitySession dot color changes |
| 247 | + |
| 248 | +3. **Start a new customer session** |
| 249 | + - Both dot colors change |
| 250 | + |
| 251 | +4. **Mix events with and without session data** |
| 252 | + - Events without session data show no dots |
| 253 | + - Events with partial session data show only relevant dots |
| 254 | + |
| 255 | +## Future Enhancements |
| 256 | + |
| 257 | +Potential improvements (not implemented): |
| 258 | + |
| 259 | +1. **Legend** - Show all active sessions with their colors and IDs |
| 260 | +2. **Filtering** - Click a dot to filter events by that session |
| 261 | +3. **Custom colors** - Allow users to assign specific colors to known sessions |
| 262 | +4. **Session stats** - Show event count per session |
| 263 | +5. **Timeline view** - Visualize sessions on a timeline |
| 264 | + |
| 265 | +## Related Files |
| 266 | + |
| 267 | +- `src/components/WebhookInspector.tsx` - Main component logic |
| 268 | +- `src/components/WebhookInspector.css` - Styling for dots |
| 269 | +- `server/src/events.ts` - Event type definitions including CommonEventData |
| 270 | +- `server/src/webhook.ts` - Server-side event extraction |
| 271 | + |
| 272 | +## References |
| 273 | + |
| 274 | +- Session/Activity metadata is defined in `server/src/events.ts` (lines 322-333) |
| 275 | +- CustomerSession and ActivitySession are part of CommonEventData interface |
0 commit comments