Skip to content

Phase 2: Media Uploader Unification

jedmund requested to merge devin/1764000722-media-uploader-unification into main

Created by: devin-ai-integration[bot]

Phase 2: Extract Shared Media Upload Logic

Summary

This PR extracts duplicated upload logic from GalleryUploader and ImageUploader into shared helper functions in mediaHelpers.ts. This is Phase 2 of the admin form system unification plan.

Changes:

  • Added validateImageFile() helper for file type and size validation
  • Added uploadMediaFiles() function to centralize /api/media/upload fetch logic
  • Added SerializedMedia type to properly represent API responses (dates as strings)
  • Replaced inline upload icon SVGs with existing FileIcon component
  • Refactored both uploaders to use the new shared helpers

Impact:

  • Removes ~165 lines of duplicated code
  • Makes upload behavior consistent across components
  • Easier to maintain and extend upload functionality in the future

Review & Testing Checklist for Human

️ Browser Testing Limited - Local dev server was started and admin area was accessed, but testing stopped at the login page due to lack of credentials. The refactoring extracts existing logic without changing behavior, but please test thoroughly:

  • Upload single image with description in ImageUploader - Verify the description field is saved correctly (this now uses extraFields parameter instead of direct FormData append - this is the highest risk change)
  • Upload multiple images in GalleryUploader - Verify all files upload successfully and display correctly
  • Test file validation errors - Try uploading non-image files and files over the size limit to ensure error messages display correctly
  • Verify upload progress indicators - Check that the progress bars/spinners still work during upload
  • Check date handling - The refactored code returns SerializedMedia (string dates) cast to Media (Date objects). Verify no date-related bugs appear in the UI

Notes

Type Safety Concern: The uploadMediaFiles function returns SerializedMedia[] (with string dates from JSON), which is then cast to Media[] (with Date objects). This works because the components handle both string and Date types (as fixed in Phase 1), but it's worth being aware of this type mismatch.

Incomplete Refactoring: The uploadMediaFiles function has an onProgress callback parameter that isn't used yet. Both uploaders still do their own progress simulation with setInterval. This is intentional - further progress refactoring can be done in a future PR if needed.

Code Quality: All changes pass eslint src/ with zero errors and introduce no new TypeScript errors per pnpm run check.


Session: https://app.devin.ai/sessions/9c28151548c1410ca9948853ad0c04ad
Requested by: Justin Edmund (@jedmund)

Merge request reports

Loading