Skip to content

ERA-13076: Remove approach to loading icons via one enormous sprite#1529

Open
jeslefcourt wants to merge 7 commits into
developfrom
ERA-13076-remove-sprite-approach-to-loading-icons
Open

ERA-13076: Remove approach to loading icons via one enormous sprite#1529
jeslefcourt wants to merge 7 commits into
developfrom
ERA-13076-remove-sprite-approach-to-loading-icons

Conversation

@jeslefcourt
Copy link
Copy Markdown
Contributor

@jeslefcourt jeslefcourt commented Apr 8, 2026

Summary

  • Replaces SVG sprite-based icon loading with direct <img> tags referencing static SVG file URLs
  • Removes the preloaded ReportTypeIconSprite from App.js and the calcIconUrl sprite-lookup logic from DasIcon
  • Updates CSS selectors in patrol/report list and header styles from svg to img, replacing fill with filter: invert(1)

Jira

ERA-13076

Test plan

  • Event icons render correctly in the report list
  • Patrol icons render correctly in the patrol list and detail view
  • Collection icons show the correct badge icon
  • Generic fallback icon displays when an icon is missing
  • Community-scoped routes load icons from the community API endpoint

🤖 Generated with Claude Code

Replace SVG sprite-based icon loading with direct img tags using static SVG file URLs, simplifying the icon rendering pipeline and removing the preloaded sprite dependency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jeslefcourt jeslefcourt self-assigned this Apr 8, 2026
@jeslefcourt jeslefcourt requested a review from luixlive April 8, 2026 21:55
Copy link
Copy Markdown
Contributor

@luixlive luixlive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple small suggestions and a couple questions. Nothing hard-blocking, but worth taking a minute to think them through.

Comment thread src/DasIcon/index.js Outdated
Comment thread src/DasIcon/index.js Outdated
Comment thread src/EventIcon/index.js Outdated
Comment thread src/EventIcon/index.js
Comment thread src/PatrolDetailView/Header/styles.module.scss Outdated
Comment thread src/App.js

This comment was marked as outdated.

…mage files. Had a bit of a snowball effect into things impacted by cascading styles.

This comment was marked as outdated.

- Remove !important flags on svgs
- Fixed icon colors in clusters and cluster popups changing when editing events before saving
- Sanitize SVGs to avoid injection attacks
@jeslefcourt jeslefcourt requested a review from Copilot April 9, 2026 04:52

This comment was marked as outdated.

This comment was marked as outdated.

@jeslefcourt jeslefcourt force-pushed the ERA-13076-remove-sprite-approach-to-loading-icons branch from d4bcd19 to 3d4d8ab Compare April 9, 2026 06:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 27 changed files in this pull request and generated 3 comments.

Comment thread src/DasIcon/index.js Outdated
Comment thread src/DasIcon/index.js
Comment thread src/EventIcon/index.js Outdated
@jeslefcourt jeslefcourt changed the title ERA-13076: Remove sprite approach to loading icons ERA-13076: Remove approach to loading icons via one enormous sprite Apr 9, 2026
@jeslefcourt jeslefcourt requested a review from luixlive April 9, 2026 07:40
Copy link
Copy Markdown
Collaborator

@JoshuaVulcan JoshuaVulcan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks and feels pretty good so far! Will keep manually testing. My feedback on this review pass is around finishing off the refactor by making sure files and names are cleaned up.

import mapboxgl from 'mapbox-gl';

import { CLUSTER_CLICK_ZOOM_THRESHOLD, LAYER_IDS, SUBJECT_FEATURE_CONTENT_TYPE } from '../constants';
import { calcSvgImageIconId } from '../MapImageFromSvgSpriteRenderer';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like MapImageFromSvgSpriteRenderer should be removed entirely, and the utility function to calculate image URLS lifted/shifted elsewhere.

const getFeatureIcon = (feature, mapImages) =>
mapImages[`${feature.properties.icon_id}-${feature.properties.priority}`]?.image;
const getFeatureIcon = (feature, mapImages, locallyEditedEvent, eventStore) => {
const isLocally = locallyEditedEvent?.id === feature.properties.id;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variable naming nit: isLocally 😢

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. isLocally is ambiguous. The code that defines the variable isn't, but I'd rather have something like isLocallyEditedEventFeature.

Comment thread src/DasIcon/index.test.js
@@ -0,0 +1,64 @@
import React from 'react';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the changes here. Seems like we'd want to rename away from DasIcon as well?

Copy link
Copy Markdown
Contributor

@luixlive luixlive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple more comments and questions. I see now we are also updating the clusters when we have a locally edited event, which is a nice addition, but it's increasing the size of this PR considerably.

Once these comments are solved / responded, I'll be ready to approve. Still think we will need a special treatment from QA to make sure all icons render correctly and that clusters work and update correctly when we have local changes in an event that haven't been saved yet 👍 @AlanCalvillo


useMapEventBinding('sourcedata', onSourceData);

useEffect(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these useEffects can have a performance impact. Their dependency arrays include the callback itself (updateClusterMarkersCallback), this means that everytime the callback gets redefined, they will be called. In other words, whenever any of the following variables changes, we will be running the markers update:
addClusterPolygon, eventStore, locallyEditedEvent, map, onShowClusterSelectPopup, removeClusterPolygon.

Probably we could stabilize this with a useRef or a more complex useEffect that only triggers the callback specifically when locallyEditedEvent and mapImages change.

mapImages[`${feature.properties.icon_id}-${feature.properties.priority}`]?.image;
const getFeatureIcon = (feature, mapImages, locallyEditedEvent, eventStore) => {
const isLocally = locallyEditedEvent?.id === feature.properties.id;
if (isLocally) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code block gives me the impression that the agent thought locally edited events could update their icons, but they can't. All the user can changes that results in an update to the icon is priority. I feel this method can be simplified, something like:

const getFeatureIcon = (feature, mapImages) => {
  const priority = locallyEditedEvent?.id === feature.properties.id
    ? locallyEditedEvent.priority
    : feature.properties.priority

  return mapImages[calcSvgImageIconId({ icon_id: feature.properties.icon_id, priority })]?.image;
}

Unless of course I'm missing something 🤔

Comment thread src/DasIcon/index.js

const CONTAINER_SELECTOR = 'svg,g,defs,symbol,marker,clipPath,mask,pattern';

const sanitizeSvg = (text) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like a brute-force approach to clean the icons. I guess it's better to keep this file than the sprites file. Probably would try a last prompt to Claude like: "Refactor this file and apply clean code practices plus explanatory comments to improve its readability and maintainability". And I would say this requires some thorough manual testing in a couple envs just to make sure all icons render correctly 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants