diff --git a/.claude-context/sessions/2026-09-23-sheet-columns-sidebar-location.md b/.claude-context/sessions/2026-09-23-sheet-columns-sidebar-location.md new file mode 100644 index 0000000..4a0a39d --- /dev/null +++ b/.claude-context/sessions/2026-09-23-sheet-columns-sidebar-location.md @@ -0,0 +1,91 @@ +# 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** — `GoogleSheetConfig` holds all col indices as `int` properties. Set to `-1` to 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). `GoogleSheetService` reads `Location/Classroom` first; if empty, falls back to `Campus`. This means location data is recovered even when the classroom field is blank. +- **`RawSheetLocation` on `DashboardTile`** — 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`** — `BuildDashboard` skips any NTT ticket whose saved `StatusOverride` contains 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 a `showCollected` bool. Rejected alternative: copy-paste per panel. +- **Sidebar items are `` links** — Each sidebar item wraps in ``. The Collected button uses `event.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`): +1. Exact ID match +2. Exact name match (case-insensitive) +3. Substring match either direction (e.g. "Library Block A" matches location named "Library") +Falls back to storing raw text in `RawSheetLocation` if 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 `` 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 than `btn-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 ``; 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.json` growth** — resolved NTT tickets accumulate forever; a periodic cleanup of records older than N days with a closed `StatusOverride` would 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`