Gallery Creator: Springs vs Springs Pro
Problem Summary
In Gallery Creator, Springs and Springs Pro are listed as separate camps. The observed behavior:
Selecting Springs → all photos shown, including those belonging to Springs Pro campers.
Jesse's diagnosis: "Springs has a Final Destination folder, and Springs Pro does not have one at all."
Root Cause 1: Location Name Collision
Springs and Springs Pro share the same physical location, "Pine Cove Springs." When bridge-api resolves a folder path for any YouthCamp-type session it calls resolveAppDisplayLocation, which strips the "Pine Cove " prefix from the location name:
// bridge-api/server/src/service/camp-session.service.ts:90 static resolveAppDisplayLocation(campSessionDTO, showCitySession = false): string { // YouthCamp: resolves to location.name, then strips "Pine Cove " locationName = CampSessionService.resolveLocationName(campSessionDTO); locationName = locationName.replace('Pine Cove ', ''); // Both "Springs" and "Springs Pro" resolve to → "Springs" }
Without an override, both camps produce a locationName of "Springs". All S3 paths and gallery album folder paths for both camps collapse into the same Springs folder.
Root Cause 2: The Override Was Never Triggered
gallery-folder-generator.ts has a Springs Pro override in two places:
// bridge-api/.../gallery-folder-generator.ts:167–171 (standard session folder creation) let locationName = CampSessionService.resolveAppDisplayLocation(campSession, true); if (campSession.camp.name === 'Springs Pro') { locationName = 'Springs Pro'; } locationName = locationName.replace('Pine Cove ', '');
The same override is at lines 776–778 for default album row creation.
Root Cause 3: The LIKE Query Bug
Gallery Creator searches photos by filtering image.source (the S3 path) with a LIKE pattern:
// bridge-api/server/src/service/image.service.ts:170 query.andWhere('image.source LIKE :campPattern', { campPattern: `%/${camp}%` });
When camp = "Springs" the pattern is %/Springs%, which matches both:
| S3 Path | Matches %/Springs%? |
|---|---|
2025/Springs/Week 1/Photos/1Sun/… | Yes (intended) |
2025/Springs Pro/Week 1/Photos/1Sun/… | Yes (unintended — "Springs Pro" contains "Springs") |
When camp = "Springs Pro" the pattern %/Springs Pro% is correct in theory — but since no photos exist at a /Springs Pro/ path, the query returns nothing.
Album-Level Filtering Is Fine
Gallery album queries use an exact campName match, not a LIKE:
query.andWhere('ga.campName = :camp', { camp });
Springs Pro albums exist as distinct rows in the database. The problem is upstream — no photos have ever been routed to Springs Pro S3 paths, so album photo lookups return empty even though the album rows are correct.
Solutions
Option B — Provision Springs Pro Its Own Folder
Run the gallery folder-creation function for Springs Pro camp sessions. The override is already coded at gallery-folder-generator.ts:169 — it just needs to be triggered.
- Call
createCloudFilesFoldersForStandardSessionAsyncfor each current and upcoming Springs ProCampSession. This creates2025/Springs Pro/Week N/Photos/{day}/…in the media S3 bucket. - Verify the tagged-media processing pipeline routes Springs Pro photos (identified by
tagInfo.campName === "Springs Pro") to the correct folder. The lambda already extracts camp name from the inbox S3 path. - Optionally backfill: identify images with
source LIKE '%/Springs/%'that belong to Springs Pro sessions via camper registrations, and move them to/Springs Pro/paths.
Pros
- Clean, permanent separation of both camps
- No logic changes — override already written
- Springs galleries stop showing Springs Pro photos
Cons
- Requires infrastructure provisioning step
- Backfilling misrouted photos is manual effort
Option A — Shared Photo Pool
Change Springs Pro's photo query to also search Springs-pathed photos. Both camps draw from the same S3 folder.
Pros
- No S3 provisioning required
- Fastest to implement
Cons
- Springs and Springs Pro galleries permanently cross-contaminate
- Ties two distinct camps together in the data layer
- Requires extra filtering to exclude wrong-camp campers
Secondary Fix: Tighten the LIKE Pattern
Even after Option B is applied, the LIKE query in image.service.ts:170 should be hardened with a trailing slash so Springs no longer matches Springs Pro paths:
// Current — matches both /Springs/ and /Springs Pro/ campPattern: `%/${camp}%` // Fixed — exact path segment boundary campPattern: `%/${camp}/%`
Key Files
| File | Lines | What It Does |
|---|---|---|
bridge-api/…/gallery-folder-generator.ts |
167–173, 775–779 | Springs Pro locationName override for folder creation |
bridge-api/…/camp-session.service.ts |
90–121 | resolveAppDisplayLocation — where both camps collapse to "Springs" |
bridge-api/…/image.service.ts |
165–172, 355–365 | LIKE query that accidentally matches Springs Pro when filtering Springs |
bridge-api/…/gallery-album.service.ts |
1009–1075 | Album filtering by exact campName (correct, not the problem) |
sidekick-portal/…/GalleryCreator/GalleryCreator.tsx |
— | Frontend; no Springs-specific logic; delegates entirely to the API |