6.5 KiB
Google Sheet Column Remapping, Sidebar Panels & Location Display
Date: 2026-09-23 Project: disco-service-tracker-plugin Status: resolved Tags: google-sheet, column-mapping, sidebar, location, ntt, dashboard, bugfix
Context
The NTT Google Sheet had columns added and reordered, breaking field mapping for AssignedTo, Status, and Notes. Separately, the dashboard sidebar needed new panels (Awaiting Vendor, Awaiting Parts), sidebar items needed to be clickable links, and NTT sheet jobs needed to show their raw location text on the tile. Several bugs were also fixed: closed NTT jobs reappearing, the On Hold panel being missing from the sidebar.
Key Decisions
- Column indices stored in config, not hardcoded —
GoogleSheetConfigholds all col indices asintproperties. Set to-1to disable a column (e.g.ColCompletionDate = -1). This lets the Config UI page update them without a rebuild. - Campus column as location fallback — Added
ColCampus(col 8).GoogleSheetServicereadsLocation/Classroomfirst; if empty, falls back toCampus. This means location data is recovered even when the classroom field is blank. RawSheetLocationonDashboardTile— When the sheet's location text can't be fuzzy-matched to a configured Disco location, the raw string is stored on the tile and displayed as a plain italic 📍 pill. Rejected alternative: silently dropping unmatched locations (loses visible info).- Sidebar buckets are mutually exclusive, priority-ordered — rfr → onHold → awaitingVendor → awaitingParts → main. A ticket can only be in one sidebar panel. Rejected alternative: showing tickets in both sidebar and main grid.
- Closed NTT tickets suppressed by
StatusOverride—BuildDashboardskips any NTT ticket whose savedStatusOverridecontains a closed keyword (resolved,dismissed,complete,closed,done,cancel,finished), even if the sheet row still shows as open. This prevents dismissed jobs from reappearing on every refresh. SidebarPanel()helper — Extracted repeated sidebar panel HTML into one method taking title, accent colour, item list, url, and ashowCollectedbool. Rejected alternative: copy-paste per panel.- Sidebar items are
<a>links — Each sidebar item wraps in<a class='rfr-item rfr-link' href='/Detail?...'>. The Collected button usesevent.stopPropagation()so clicking it submits the form rather than following the link.
Technical Details
New sheet column layout (0-based):
| Col | Field | Property |
|---|---|---|
| 0 | Timestamp | ColTimestamp |
| 1 | Email address | ColEmail |
| 2 | What is the task/request? | ColTask |
| 3 | Detailed Description | ColIssue |
| 4 | Location / Classroom | ColLocation |
| 5 | Requested By | ColRequestedBy |
| 6 | Priority Level | ColPriority |
| 7 | Preferred Completion Date | ColPreferredDate |
| 8 | Campus | ColCampus |
| 9 | Assigned to | ColAssignedTo |
| 10 | Status | ColStatus |
| 11 | Column 1 (junk) | ignored |
| 12 | Campus (duplicate) | ignored |
| 13 | Notes | ColNotes |
| 14 | Category | ignored |
| 15 | Resolution Confirmed | ignored |
ColCompletionDate = -1 — SafeGet() returns null for index < 0, so no out-of-bounds risk.
Location fuzzy matching (ServiceTrackerService.MatchSheetLocation):
- Exact ID match
- Exact name match (case-insensitive)
- Substring match either direction (e.g. "Library Block A" matches location named "Library")
Falls back to storing raw text in
RawSheetLocationif no match.
Sidebar bucket match strings:
- Ready for Return: status contains
"ready for return"or"ready for pickup" - On Hold: contains
"on hold" - Awaiting Vendor: contains
"awaiting vendor" - Awaiting Parts: contains
"awaiting parts"
Closed status keywords (ClosedStatusKeywords array):
"resolved", "dismissed", "complete", "closed", "done", "cancel", "finished"
CSS classes added:
.rfr-link— makes sidebar<a>items block-level, no text-decoration, colour inherit.rfr-link:hover— light blue bg + blue border.trsl— italic grey for raw sheet location pill on tiles.sp-ct— coloured count badge in sidebar panel headings.btn-xs— 2px/7px padding, 10px font (smaller thanbtn-sm)
After install: delete sheet_cache.csv from App_Data/Plugins/Disco.Plugins.ServiceTracker/ and save Config once to write new column indices to config.json.
Code Changes
| File | Change |
|---|---|
Models/ServiceTrackerConfig.cs |
Added ColCampus property; updated GoogleSheetConfig() constructor and CreateDefault() to new column indices (AssignedTo→9, Status→10, ColCompletionDate→-1, Notes→13) |
Models/DashboardViewModel.cs |
Added RawSheetLocation to DashboardTile; added AwaitingVendor and AwaitingParts lists to DashboardViewModel |
Services/GoogleSheetService.cs |
Reads ColCampus as location fallback; SafeGet handles index -1 gracefully; updated to use new column properties |
Services/ServiceTrackerService.cs |
Added ClosedStatusKeywords — skips NTT tickets with closed StatusOverride; added awaitingVendor and awaitingParts bucket queries; added MatchSheetLocation(); sets RawSheetLocation on unmatched tiles; bumped through v1.5.5→v1.5.9 |
WebHandler/ServiceTrackerWebHandler.cs |
Added SidebarPanel() helper; sidebar items are <a rfr-link>; Collected button has stopPropagation; Config page col grid updated with Campus field and correct labels/indices; CSS additions (rfr-link, trsl, sp-ct, btn-xs) |
Open Questions / Next Steps
- Category field (col 14) — currently ignored; could be surfaced as a tag or filter on tiles if useful
- Resolution Confirmed (col 15) — could auto-close NTT tickets when this is populated, rather than requiring manual status override
- Campus as a proper location dimension — currently only used as a fallback for the Location/Classroom field; could be shown separately on the tile (e.g. as a secondary badge) if campuses are meaningful for filtering
external_tickets.jsongrowth — resolved NTT tickets accumulate forever; a periodic cleanup of records older than N days with a closedStatusOverridewould help- Sheet cache invalidation — currently time-based only; a manual "Refresh Now" button on the dashboard would be useful
Artifacts
- Repo: https://gitea.hideawaygaming.com.au/jessikitty/disco-service-tracker-plugin
- Version at session end: v1.5.9
- Sheet URL (published CSV):
https://docs.google.com/spreadsheets/d/e/2PACX-.../pub?output=csv&gid=170394795