feat: replace blueimp jQuery-File-Upload with a dependency-free chunked uploader#7552
feat: replace blueimp jQuery-File-Upload with a dependency-free chunked uploader#7552orangewolf wants to merge 1 commit into
Conversation
Replaces the vendored, unversioned blueimp jQuery-File-Upload stack (jquery.fileupload*.js, jquery.iframe-transport.js) and its tmpl-based row rendering with Hyrax.Uploader, a small ES6 module with no jQuery dependency, served through the existing Sprockets/almond pipeline. The server contract is untouched: the widget speaks the same two-step staged upload protocol (POST /uploads with the filename to create the Hyrax::UploadedFile, then the bytes under that id, split into sequential Content-Range chunks above maxChunkSize — still Cloudflare-request-size-safe), injects the same hidden fields (uploaded_files[], files_files[], banner_files[], logo_files[], linkurl[]/alttext[]), honors Hyrax.config.uploader limits client-side, and DELETEs staged records on remove. Covered surfaces, matching the old widget: work new/edit Files tab (multi-file, folder upload via webkitdirectory, drag and drop, per-file progress/cancel/remove/errors), batch upload with per-file title/resource type inputs, file set version upload (single file, replace-on-reselect), collection branding banner (single file, clears the current banner and its banner_unchanged input) and logos (with per-logo link/alt inputs appended positionally). Row markup moves from blueimp x-tmpl scripts to server-rendered <template> elements (ERB keeps i18n and per-page variants); form inputs in rows are authored nameless and named on completion, so an in-flight upload can neither satisfy the required-files gate nor submit partial values. SaveWorkControl keeps working unchanged: the uploader fires the legacy jQuery event names (fileuploadadded/ -completed/-destroyed/-start/-stop, plus -fail) alongside hyrax:uploads:* CustomEvents; uploaded_files.es6 now also decrements its in-progress counter on fileuploadfail, fixing the legacy stuck Save button after a canceled or failed upload. blueimp's standalone tmpl.js helper stays vendored: the permissions and relationships editors use it (now loaded explicitly from hyrax.js). The upload widget initialization moved after almond since the uploader is an AMD module like the rest of Hyrax's ES6. Tests, run locally against the koppie test app: - karma/jasmine (headless Chrome against the compiled asset bundle): 91 of 91 pass — the new spec/javascripts/hyrax_uploader_spec.js (pre-create + upload + row fill, sequential Content-Range chunk math, legacy event ordering for the save gate, maxFileSize rejection) plus the entire pre-existing JS suite - view specs: hyrax/base/_form_files, hyrax/batch_uploads/_form, hyrax/file_sets/_versioning, hyrax/dashboard/collections/ _form_branding, hyrax/uploads/create.json.jbuilder — green - assets:precompile succeeds with the new module - browser feature specs (js: true) not run locally — the capybara setup targets a remote selenium grid; CI's dockerized matrix covers them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
||
| var logo = document.getElementById('fileuploadlogo'); | ||
| if (logo && !logo.hyraxUploader) { | ||
| new Hyrax.Uploader(logo, { rowTemplate: 'hyrax-upload-row-logo' }); |
There was a problem hiding this comment.
Do not use 'new' for side effects no-new
| } | ||
|
|
||
| var main = document.getElementById('fileupload'); | ||
| if (main && !main.hyraxUploader) { new Hyrax.Uploader(main, {}); } |
There was a problem hiding this comment.
Do not use 'new' for side effects no-new
| // expose the uploader for view-level initializers and overrides | ||
| window.Hyrax = window.Hyrax || {}; | ||
| if (!window.Hyrax.Uploader) { | ||
| window.Hyrax.Uploader = require('hyrax/uploader').Uploader; |
There was a problem hiding this comment.
Unexpected require() global-require
| } | ||
|
|
||
| // finalize a row: reveal the hidden id input, wire deletion | ||
| uploadCompleted(upload, record) { |
There was a problem hiding this comment.
Method 'uploadCompleted' has a complexity of 8 complexity
|
|
||
| // ---- validation -------------------------------------------------------- | ||
|
|
||
| validate(file) { |
There was a problem hiding this comment.
Method 'validate' has a complexity of 8 complexity
|
|
||
| // ---- queue ------------------------------------------------------------- | ||
|
|
||
| pump() { |
There was a problem hiding this comment.
Method 'pump' has a complexity of 8 complexity
| class Uploader { | ||
| // @param element [HTMLElement] the widget container (e.g. #fileupload) | ||
| // @param options [Object] overrides merged over Hyrax.config.uploader | ||
| constructor(element, options) { |
There was a problem hiding this comment.
Constructor has a complexity of 11 complexity
| @@ -0,0 +1,135 @@ | |||
| describe("Hyrax.Uploader", function() { | |||
| var Uploader = require('hyrax/uploader').Uploader; | |||
There was a problem hiding this comment.
Unexpected require() global-require
|
Superseded by #7558 — same change moved to an in-repo branch (active-storage-for-all/modern-uploader) and retitled. |
Summary
Replaces the vendored, unversioned blueimp jQuery-File-Upload stack with
Hyrax.Uploader— a small dependency-free ES6 module (~450 lines, no jQuery in the core) served through the existing Sprockets/almond pipeline. Net −2,300 lines. Part of the upload-unification chain, but independent: based onmain, server contract untouched — it merges before or after the Active Storage PRs (#7547–#7551) equally well.What's preserved (feature-for-feature)
webkitdirectory), drag & drop, per-file progress bar, cancel/remove, error displaytitle[<id>],resource_type[<id>][]), "set all to this resource type"files_files[]banner_unchangedinput), logos (append, per-logolinkurl[]/alttext[]kept positionally aligned)fileuploadadded/-completed/-destroyed/-start/-stop/-fail) alongsidehyrax:uploads:*CustomEventsPOST /uploads(filename →Hyrax::UploadedFileid) then bytes under that id in sequentialContent-Rangechunks abovemaxChunkSize(10 MB) — still Cloudflare-request-size-safe;Hyrax.config.uploaderlimits honored client-side;DELETEon removeImprovements
x-tmplscripts to server-rendered<template>elements (ERB keeps i18n + per-page variants; apps override partials as usual).linkurl[]).uploaded_files.es6now decrements its in-progress counter onfileuploadfail— fixing the legacy stuck Save button after a canceled/failed upload.Hyrax.config.uploader+data-*attributes (no more four-way config split).Notes for reviewers
tmpl.jshelper stays (the permissions and relationships editors use it; now required explicitly inhyrax.js).almondinhyrax.js.files_files[]so this PR stands alone; once feat: unify staged upload params behind an ownership-enforcing resolver #7551 (canonicaluploaded_files[]+ deprecation) lands, flipping the template's field name is a one-liner.Tests (run locally against the koppie test app)
spec/javascripts/hyrax_uploader_spec.js(pre-create + upload + row fill; sequentialContent-Rangechunk math0-9/25, 10-19/25, 20-24/25; legacy event ordering for the save gate;maxFileSizerejection) plus the entire pre-existing JS suite (which also proves the almond/require load order stays intact).hyrax/base/_form_files,hyrax/batch_uploads/_form,hyrax/file_sets/_versioning,hyrax/dashboard/collections/_form_branding,hyrax/uploads/create.json.jbuilder.rails assets:precompilesucceeds with the new module.js: true) were not run locally (the capybara setup targets a remote selenium grid); CI's dockerized matrix covers them — called out honestly.🤖 Generated with Claude Code