Enhance myAvailability gems and integrate SignalR live updates - #420
Merged
Conversation
Adds a row of colour-coded count 'gems' (Activation Accepted, Available, Conditional, Unavailable, Unset) below the Incident Details header on the job view page. Counts and hover popovers listing responder names are populated via a new `lighthouseResponseGems()` function that calls the myavailability/incident Lambda (production only; non-prod Beacon gets placeholder data). Includes a loading pulse animation and full CSS styling for the gem bar.
…ems (#412) Response gems now show real counts/names even for closed activations (with a lock icon + note instead of blanking numbers), popovers pin open on click instead of only showing on hover, member names carry their id for future use, and long name lists are capped with a "+N more" indicator. Also adds a role-gated "Create Team" button on the Activation Accepted gem that opens /Teams/Create pre-filled with the accepted members and the incident's own HQ. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Adds LH-BeaconAuthorizerV2, a Lambda REQUEST authorizer wrapping the existing verifyBeaconToken logic (same trusted-issuer allow-list, same beaconApi scope check), and attaches it to all /lad_v2/... routes so invalid/missing tokens are rejected at the gateway before any backend Lambda runs. The five backend Lambdas now read the verified member id from the authorizer's context instead of re-verifying the token themselves, removing duplicated JWKS/JWT logic from each one. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
The popover panel is appended to <body>, not nested under the gem, so moving the mouse from the gem into the panel counted as a mouseleave on the gem and hid it instantly. Track hover on the panel itself once shown, with a short delay before hiding, so crossing the gap between gem and panel doesn't close it. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…#414) GitHub Actions runners are deprecating Node 20; actions/checkout@v3 and mnao305/chrome-extension-upload@v4.0.1 were being force-run on Node 24 with a deprecation warning. Bumping to actions/checkout@v7 and chrome-extension-upload@v6.0.0, both of which target Node 24 natively. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…o Available (#415) Dev/watch builds zero-padded the version timestamp (e.g. 2026.08.16.0941), which Chrome then displays with leading zeros stripped per segment (2026.8.16.941), making the on-disk manifest look out of sync with what's shown in chrome://extensions. Align dev/watch with prod's unpadded format. Also extend the "create team from responders" quick action to the Available gem, not just ActivationAccepted. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* Wire SignalR live updates into the tasking page, replacing periodic polling where push covers it Connects the tasking page to Beacon's Comms SignalR hub for near-real-time job/team/tasking/ops-log/ICEMS updates, alongside a resilient connection layer and a config-level kill switch, so REST polling can back off wherever push already keeps data fresh. - New src/pages/tasking/signalr/ module: connection manager with infinite backoff reconnect + manual-restart safety net, a lightweight Subject/ registry for routing named hub events, and a shared pushMode flag that Job/Team read to size their on-demand fetch cooldowns. - Job.js/Team.js/Tasking.js: handle jobCreated/jobUpdated/jobRejected (a Notification-record shape, not the job view-model it looks like -- JobId is the real id, not Id), teamCreated/teamUpdated (a full team object), taskingUpdated/taskingCreated, opsLogUpdated, and the ICEMS notification events, each admitted against the existing config filters so push can't add out-of-scope entities polling would never have fetched. - Bulk polls (fetchAllJobsData/fetchAllTeamData) and single-entity fetches (refreshData/fetchTasking/refreshIcemsIncident) now skip work already covered by a more recent push, without letting a push-authoritative refresh get blocked by that same cooldown. - Dropped the ICEMS agency-data poll entirely in favour of expand + push. - refreshInterval default raised 60s -> 180s (migrated via a renamed storage key so it doesn't silently apply to users who'd customized the old default); a new "Live Updates" config toggle disables the connection, the disconnect banner, and reverts the tightened cooldowns. - tasking.html: a persistent, high-visibility banner for any non-connected state, since this page depends on the connection for live data. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix job popup/list-row rendering breaking on tasking status updates Root cause was a malformed <button> tag in the team-tasking status dropdown (missing closing '>', lost when flashOnChange bindings were added) -- browsers mis-parse the unclosed tag, which corrupts Knockout's comment-based foreach/if tracking and throws "unmatched end comment" the first time that markup renders (row expand or popup open). Also fixes two related bugs found while tracking it down: - Tasking.team can be null before it resolves (a tasking upserted before its team ref is available); teamCallsign/hasTeam and several team.X template bindings dereferenced it unguarded. - addOrUpdateJobMarker's popup close/reopen has a 250ms deferred unbind (to let the close animation finish) that wasn't cancelled on a fast reopen, so a stale unbind could later wipe a popup that's live and visibly open again. Also brings in the rest of the SignalR live-update wiring already in progress on this branch: flashOnChange/flashTextOnChange bindings for push-driven value changes, jobUpdated now pulls a full refresh (its notification payload omits fields like Address/Sector), and refreshData's cooldown tracks real fetches instead of any merge. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…king (#417) * Highlight FR-1 rows and shore up push-notification reliability on tasking - Give FR-1 (Flood Rescue, Category 1) incident rows a distinct colour, subtly deeper than a normal Rescue-priority row, in both light and dark mode - Move unaccepted-notification refresh onto the shared jobs/teams refresh cycle instead of a per-job 30s timer, and drop a jobReceived fallback so jobs admitted straight from a push notification (which carries no JobReceived) aren't evicted by date filtering - Add the same clock-skew tolerance to the end-of-range date check as the existing start-of-range one, so jobs admitted right at the boundary via push aren't evicted by lag/skew - Make the incidents/teams toolbars and table columns responsive to a narrow sidebar (container queries + minmax column tracks), split the Received column into time/date lines, clamp wrapped Situation/Address text instead of letting it balloon row height, and add a manual per-incident refresh button Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix FR-1 row color inconsistency between light and dark mode Dark mode's row-rescue-fr1 (#7a2f22, L=31%) was lighter than row-rescue (#5a2a2a, L=26%), while light mode has it the other way round (fr1 darker than rescue) -- so which row read as "more severe" flipped depending on theme. Dark mode's fr1 is now darker and more saturated than rescue, matching light mode's direction. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…ate (#418) Adds fadeForeach/slideForeach binding handlers so team/job rows and taskings lists animate in and out on live add/remove instead of popping, applied across the main tables and both map popups. Fixes Team.refreshData never clearing taskingLoading after a SignalR-triggered force refresh (the injected fetchTeamById dependency is Promise-based, but refreshData was calling it callback-style, so the reset callback was silently dropped). Also quiets SignalR connection logging to Error level. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…refill race (#419) Replaces the direct single-category /Teams/Create navigation with a modal listing Accepted, Available, and Conditional responders as checkboxes, pre-ticked for whichever gem's button was clicked. Also fixes a race on the Team Create page where the page's own async Assigned To default could overwrite the incident's HQ passed via lhentityid. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request implements a centralized Lambda authorizer for Beacon token authentication, removing duplicated token verification logic from five
lad_v2Lambda handlers. Now, authentication is enforced by the newauthorizer-v2Lambda via API Gateway, and downstream handlers receive the verified Beacon member ID via the event context. The pull request also updates several GitHub Actions to use newer versions of dependencies and actions.Centralized Beacon token authentication:
lambda/authorizer-v2/index.mjs, a new Lambda authorizer that verifies Beacon tokens, centralizing the logic previously duplicated in multiple handlers. On success, it passes the verified Beacon member ID (sub) to downstream Lambdas via the event context.verifyBeaconTokenfromdefault-assets-v2,geocode-v2,map-layers-v2,route-v2, andshare-v2handlers. These handlers now trust the API Gateway authorizer and extract the user ID fromevent.requestContext.authorizer.lambda.sub. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]GitHub Actions and dependency updates:
actions/checkoutfrom v3 to v7 in.github/workflows/linter.yml,.github/workflows/publish_dev.yml, and.github/workflows/publish_prod.ymlfor improved CI reliability and features. [1] [2] [3]mnao305/chrome-extension-uploadaction from v4.0.1 to v6.0.0 in publish workflows to ensure compatibility and security. [1] [2]@microsoft/signalrv10.0.11 as a new dependency inpackage.json.These changes improve code maintainability, security, and reduce duplication by centralizing authentication logic.