* fix(gallery): show other guests' colour labels in the grid (#1178) A colour set by one guest was visible to others in the lightbox and invisible on the tile. The lightbox reads /photos/:id/feedback, which returns per-colour tallies across everyone; the grid reads /photos, whose payload carried only `my_color_label` — so PhotoCard could render nothing else. The feature simply was not extended to the grid. /photos now also returns `other_color_labels`: the DISTINCT colours other viewers put on each photo, gated on show_feedback_to_guests like every other aggregate. `my_color_label` stays ungated, because a viewer's own selection is not shared data — that distinction is unchanged. Distinct colours rather than counts, and capped at three dots: a tile has room for a couple of marks, and "who marked this, and how many" is a question the lightbox already answers properly. The viewer's own colour is excluded from the dots so the badge and the dots never say the same thing twice, and they sit in opposite corners so they do not read as one group. The inset ring stays the viewer's own signal, which is what the badge was built for. Not addressed: the same issue asks for an identity-less shared colour tag — one tag per photo that any guest can overwrite. Neither existing identity mode does that (`simple` scopes by device fingerprint, `guest` by guest_id), so it is a third model touching the feedback schema, the per-guest caps, moderation and the admin aggregates. That is a feature with its own design, not part of this fix. * fix(gallery): carry other guests' labels into the premium and story grids too (#1178) PhotoCard was not the only place the badge renders. GalleryPremiumLayout and StoryPhotoCard have their own copies, and both still passed only my_color_label — so the fix would have covered the default grid and left the two full-bleed layouts showing nothing, which is the same shape of gap the original bug had. Found by driving a real gallery rather than reading the diff: the masonry grid rendered the dots correctly, and a grep for the remaining call sites turned up these two. * fix(gallery): keep the other-viewers colour dots out of the contested corner (#1178) The dots were placed bottom-left, which is the busiest corner in every layout: Timeline paints a timestamp chip there on every tile, and Grid, Mosaic and Masonry a media-type badge. All of them render after the badge, so the dots sat underneath them. Moved into a single row in the corner the colour-label dot already owns, next to the viewer's own mark. Nothing new is contested, and the grouping reads better anyway — your mark and everyone else's are the same kind of information. --------- Co-authored-by: Paul Nothaft <[email protected]>
This commit is contained in:
co-authored by
Paul Nothaft
parent
849a5807b7
commit
51d20c5920
@@ -969,6 +969,46 @@ router.get('/:slug/photos', verifyGalleryAccess, resolveGuest, async (req, res)
|
||||
});
|
||||
}
|
||||
|
||||
// OTHER viewers' colour labels, per photo (#1178).
|
||||
//
|
||||
// The lightbox has always shown these — /photos/:id/feedback returns
|
||||
// per-colour tallies across everyone — but the grid had no field carrying
|
||||
// them, so a label set by one guest was visible in fullscreen and invisible
|
||||
// on the tile. With sharing on, that is just a hole.
|
||||
//
|
||||
// DISTINCT colours, not counts: a tile has room for a couple of dots, and
|
||||
// "who else marked this, and how" is a lightbox question. The viewer's own
|
||||
// colour is excluded here so the badge and the dots never say the same
|
||||
// thing twice — the frontend renders `my_color_label` as the badge and
|
||||
// these beside it.
|
||||
//
|
||||
// Gated on showFeedbackToGuests, like every other aggregate: this is other
|
||||
// people's feedback, unlike my_color_label above.
|
||||
const otherColorLabelsByPhoto = {};
|
||||
if (photos.length > 0 && showFeedbackToGuests) {
|
||||
const othersQuery = db('photo_feedback')
|
||||
.where({ event_id: req.event.id, feedback_type: 'color_label', is_hidden: false })
|
||||
.whereIn('photo_id', photos.map(p => p.id))
|
||||
.whereNotNull('color_label');
|
||||
if (req.guest?.id) {
|
||||
othersQuery.where(function () {
|
||||
this.whereNot('guest_id', req.guest.id).orWhereNull('guest_id');
|
||||
});
|
||||
} else {
|
||||
const mine = generateGuestIdentifier(req);
|
||||
othersQuery.where(function () {
|
||||
this.whereNot('guest_identifier', mine).orWhereNull('guest_identifier');
|
||||
});
|
||||
}
|
||||
const otherRows = await othersQuery.distinct('photo_id', 'color_label');
|
||||
otherRows.forEach(row => {
|
||||
if (!otherColorLabelsByPhoto[row.photo_id]) otherColorLabelsByPhoto[row.photo_id] = [];
|
||||
if (!otherColorLabelsByPhoto[row.photo_id].includes(row.color_label)) {
|
||||
otherColorLabelsByPhoto[row.photo_id].push(row.color_label);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// People in each photo (#1074). Two independent gates: the feature must
|
||||
// be on for this event AND, for a plain guest, the photographer must have
|
||||
// left the strip visible. A client (PIN access) is the photographer's own
|
||||
@@ -1249,6 +1289,10 @@ router.get('/:slug/photos', verifyGalleryAccess, resolveGuest, async (req, res)
|
||||
// grid badge disappears on refresh for the very guest who set it.
|
||||
color_label_count: showFeedbackToGuests ? (photo.color_label_count || 0) : 0,
|
||||
my_color_label: myColorLabelByPhoto[photo.id] || null,
|
||||
// Distinct colours other viewers put on this photo (#1178), so the
|
||||
// grid can show them beside the viewer's own badge. Empty with
|
||||
// sharing off — it is other people's feedback.
|
||||
other_color_labels: otherColorLabelsByPhoto[photo.id] || [],
|
||||
// People in this photo (#1074). Empty array when the feature is
|
||||
// off for this event or hidden from guests, so the frontend has
|
||||
// one shape to handle. Riding along on this payload is what keeps
|
||||
|
||||
Reference in New Issue
Block a user