Skip to content

Admin: preview, crop & shuffle the Star Wars easter-egg figure in the Person cropper (#1304) - #1306

Merged
jonfroehlich merged 1 commit into
masterfrom
1304-easter-egg-picker
Jun 15, 2026
Merged

Admin: preview, crop & shuffle the Star Wars easter-egg figure in the Person cropper (#1304)#1306
jonfroehlich merged 1 commit into
masterfrom
1304-easter-egg-picker

Conversation

@jonfroehlich

@jonfroehlich jonfroehlich commented Jun 15, 2026

Copy link
Copy Markdown
Member

Closes #1304.

What & why

A brand-new Person has no easter_egg image, so the Cropper.js widget was blank on load and Person.save() assigned a random Star Wars LEGO figure invisibly — no way to preview, re-roll, or crop it up front. This wires a figure picker into the easter-egg cropper.

Behavior

  • New Person: a random figure shows in the cropper on load — preview/crop it immediately, no save-first round trip.
  • 🎲 Shuffle button cycles to another random figure. Offered on existing People too, so a student can swap their current easter egg to a figure.
  • Upload still wins: choosing your own image overrides the figure (already worked; the picker defers to it).
  • Whatever is shown — chosen figure or upload — persists on save with its crop box.
  • The random fallback is unchanged for the untouched / non-admin / bulk path.

How it works

  • EasterEggCropImageWidget (a CropImageWidget subclass) embeds the figure list as JSON and renders an accessible <button type="button"> Shuffle control.
  • ml_cropper.js seeds a default on an empty field, reveals Shuffle on every Person, records the chosen figure's basename in a hidden easter_egg_starwars_choice field, and clears it on upload.
  • PersonAdminForm validates the choice against the known figure list (guards path traversal) and copies that figure into easter_egg on save when the editor shuffled and didn't upload.
  • fileutils.list_starwars_images() is the single source of truth; the random picker now draws from it.
  • Data layer untouched: ImageRatioField / crop_corners / easy_thumbnails are unchanged.

Design questions (from the issue)

  1. Figure listfileutils.list_starwars_images(), embedded in the widget (no new endpoint).
  2. Default timing → admin commits whatever's shown; Person.save() random fallback retained for non-admin/bulk.
  3. Crop of a non-uploaded default → the figure is copied into easter_egg; easter_egg_crop holds the box.
  4. Scopeeaster_egg only (headshot image keeps the plain crop widget).

Tests

website/tests/test_easter_egg_picker.py (10 tests) covers the three save paths (chosen / shuffled-on-existing / uploaded), the random fallback, untouched-edit preservation, and path-traversal rejection. Full suite: 159 passing.

Screenshots

Here's the UI:

image

A11y

Shuffle is a semantic <button>; the existing keyboard-accessible numeric crop controls are unchanged. Run the Pa11y profile before merge.

🤖 Generated with Claude Code

…opper (#1304)

A new Person has no easter_egg image, so the Cropper.js widget was blank and
Person.save() assigned a random Star Wars figure invisibly — no way to preview,
re-roll, or crop it up front. This wires a figure picker into the easter-egg
cropper:

- New EasterEggCropImageWidget (CropImageWidget subclass) embeds the figure
  list as JSON and renders an accessible "Shuffle" button.
- ml_cropper.js seeds a random figure on an empty field (new Person), reveals
  Shuffle on every Person (so an existing easter egg can be swapped too), and
  clears the choice when the editor uploads their own image (upload wins).
- PersonAdminForm copies the chosen figure into easter_egg on save when the
  editor shuffled and didn't upload; the hidden choice field is validated
  against the known figure list (guards path traversal). The crop box persists
  via the existing easter_egg_crop ratio field.
- Person.save()'s random fallback is unchanged for the untouched/non-admin path.
- fileutils.list_starwars_images() is the single source of truth; the random
  picker now draws from it.

Tests: website/tests/test_easter_egg_picker.py covers all three save paths
(chosen / shuffled-on-existing / uploaded), the random fallback, untouched-edit
preservation, and the path-traversal rejection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jonfroehlich
jonfroehlich merged commit 086c02f into master Jun 15, 2026
1 check passed
@jonfroehlich
jonfroehlich deleted the 1304-easter-egg-picker branch June 22, 2026 20:36
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.

Admin: preview + pick the Star Wars easter-egg image in the Person cropper (default on load)

1 participant