Files
c-relay-pg/docs/subscription_table_grouping_plan.md
T
2025-10-31 10:39:06 -04:00

5.4 KiB

Subscription Table WSI Pointer Grouping Implementation Plan

Objective

Modify the subscription details table to show the WSI Pointer value only once per group - on the first row of each WSI Pointer group, leaving it blank for subsequent rows with the same WSI Pointer.

Current Behavior

  • All rows show the WSI Pointer value
  • Rows are sorted by WSI Pointer (grouping is working)
  • Visual grouping is not clear

Desired Behavior

  • First row of each WSI Pointer group shows the full WSI Pointer value
  • Subsequent rows in the same group have an empty cell for WSI Pointer
  • This creates a clear visual grouping effect

Implementation Details

File to Modify

api/index.js - Function populateSubscriptionDetailsTable() (lines 4277-4384)

Code Changes Required

Current Code (lines 4291-4383):

// Sort subscriptions by wsi_pointer to group them together
subscriptionsData.sort((a, b) => {
    const wsiA = a.wsi_pointer || '';
    const wsiB = b.wsi_pointer || '';
    return wsiA.localeCompare(wsiB);
});

subscriptionsData.forEach((subscription, index) => {
    const row = document.createElement('tr');

    // Calculate duration
    const now = Math.floor(Date.now() / 1000);
    const duration = now - subscription.created_at;
    const durationStr = formatDuration(duration);

    // Format client IP (show full IP for admin view)
    const clientIP = subscription.client_ip || 'unknown';

    // Format wsi_pointer (show full pointer)
    const wsiPointer = subscription.wsi_pointer || 'N/A';

    // Format filters (show actual filter details)
    let filtersDisplay = 'None';
    // ... filter formatting code ...

    row.innerHTML = `
        <td style="font-family: 'Courier New', monospace; font-size: 12px;">${wsiPointer}</td>
        <td style="font-family: 'Courier New', monospace; font-size: 12px;">${subscription.id || 'N/A'}</td>
        <!-- <td style="font-family: 'Courier New', monospace; font-size: 12px;">${clientIP}</td> -->
        <td>${durationStr}</td>
        <td>${filtersDisplay}</td>
    `;
    tableBody.appendChild(row);
});

Modified Code:

// Sort subscriptions by wsi_pointer to group them together
subscriptionsData.sort((a, b) => {
    const wsiA = a.wsi_pointer || '';
    const wsiB = b.wsi_pointer || '';
    return wsiA.localeCompare(wsiB);
});

// Track previous WSI Pointer to detect group changes
let previousWsiPointer = null;

subscriptionsData.forEach((subscription, index) => {
    const row = document.createElement('tr');

    // Calculate duration
    const now = Math.floor(Date.now() / 1000);
    const duration = now - subscription.created_at;
    const durationStr = formatDuration(duration);

    // Format client IP (show full IP for admin view)
    const clientIP = subscription.client_ip || 'unknown';

    // Format wsi_pointer - only show if it's different from previous row
    const currentWsiPointer = subscription.wsi_pointer || 'N/A';
    let wsiPointerDisplay = '';
    
    if (currentWsiPointer !== previousWsiPointer) {
        // This is the first row of a new group - show the WSI Pointer
        wsiPointerDisplay = currentWsiPointer;
        previousWsiPointer = currentWsiPointer;
    } else {
        // This is a continuation of the same group - leave blank
        wsiPointerDisplay = '';
    }

    // Format filters (show actual filter details)
    let filtersDisplay = 'None';
    // ... filter formatting code remains the same ...

    row.innerHTML = `
        <td style="font-family: 'Courier New', monospace; font-size: 12px;">${wsiPointerDisplay}</td>
        <td style="font-family: 'Courier New', monospace; font-size: 12px;">${subscription.id || 'N/A'}</td>
        <!-- <td style="font-family: 'Courier New', monospace; font-size: 12px;">${clientIP}</td> -->
        <td>${durationStr}</td>
        <td>${filtersDisplay}</td>
    `;
    tableBody.appendChild(row);
});

Key Changes Explained

  1. Add tracking variable: let previousWsiPointer = null; before the forEach loop
  2. Store current WSI Pointer: const currentWsiPointer = subscription.wsi_pointer || 'N/A';
  3. Compare with previous: Check if currentWsiPointer !== previousWsiPointer
  4. Conditional display:
    • If different: Show the WSI Pointer value and update previousWsiPointer
    • If same: Show empty string (blank cell)
  5. Use display variable: Replace ${wsiPointer} with ${wsiPointerDisplay} in the row HTML

Visual Result

Before:

WSI Pointer    | Subscription ID | Duration | Filters
0x12345678     | sub-001        | 5m 30s   | kinds:[1]
0x12345678     | sub-002        | 3m 15s   | kinds:[3]
0x87654321     | sub-003        | 1m 45s   | kinds:[1,3]

After:

WSI Pointer    | Subscription ID | Duration | Filters
0x12345678     | sub-001        | 5m 30s   | kinds:[1]
               | sub-002        | 3m 15s   | kinds:[3]
0x87654321     | sub-003        | 1m 45s   | kinds:[1,3]

Testing Checklist

  1. ✅ Verify first row of each group shows WSI Pointer
  2. ✅ Verify subsequent rows in same group are blank
  3. ✅ Verify grouping works with multiple subscriptions per WSI Pointer
  4. ✅ Verify single subscription per WSI Pointer still shows the value
  5. ✅ Verify empty/null WSI Pointers are handled correctly
  6. ✅ Verify table still displays correctly when no subscriptions exist

Next Steps

  1. Review this plan
  2. Switch to Code mode
  3. Implement the changes in api/index.js
  4. Test the implementation
  5. Verify the visual grouping effect