DEV: Drop jQuery file uploader and old upload components (#15376)

This commit removes jQuery file uploader from Discourse,
completing the transition to Uppy. The image-uploader
and UploadMixin components are also removed in this commit
as they have already been replaced and are the only things
using jQuery file upload.

            .-'~~~`-.
          .'         `.
          |  R  I  P  |
          |   jquery  |
          |    file   |
          |   upload  |
          |           |
        \\| 2013-2021 |//
        -----------------
This commit is contained in:
Martin Brennan
2021-12-22 08:59:44 +10:00
committed by GitHub
parent 72ad5bf8bd
commit 667a8a63b3
11 changed files with 0 additions and 2194 deletions

View File

@@ -1,135 +0,0 @@
import Component from "@ember/component";
import deprecated from "discourse-common/lib/deprecated";
import UploadMixin from "discourse/mixins/upload";
import { ajax } from "discourse/lib/ajax";
import discourseComputed from "discourse-common/utils/decorators";
import { getURLWithCDN } from "discourse-common/lib/get-url";
import { isEmpty } from "@ember/utils";
import lightbox from "discourse/lib/lightbox";
import { next } from "@ember/runloop";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Component.extend(UploadMixin, {
classNames: ["image-uploader"],
loadingLightbox: false,
init() {
this._super(...arguments);
// TODO (martin) (2022-01-22) Remove this component.
deprecated(
"image-uploader will be removed in a future version, use uppy-image-uploader instead (the API is the same)"
);
this._applyLightbox();
},
willDestroyElement() {
this._super(...arguments);
const elem = $("a.lightbox");
if (elem && typeof elem.magnificPopup === "function") {
$("a.lightbox").magnificPopup("close");
}
},
@discourseComputed("imageUrl", "placeholderUrl")
showingPlaceholder(imageUrl, placeholderUrl) {
return !imageUrl && placeholderUrl;
},
@discourseComputed("placeholderUrl")
placeholderStyle(url) {
if (isEmpty(url)) {
return "".htmlSafe();
}
return `background-image: url(${url})`.htmlSafe();
},
@discourseComputed("imageUrl")
imageCDNURL(url) {
if (isEmpty(url)) {
return "".htmlSafe();
}
return getURLWithCDN(url);
},
@discourseComputed("imageCDNURL")
backgroundStyle(url) {
return `background-image: url(${url})`.htmlSafe();
},
@discourseComputed("imageUrl")
imageBaseName(imageUrl) {
if (isEmpty(imageUrl)) {
return;
}
return imageUrl.split("/").slice(-1)[0];
},
validateUploadedFilesOptions() {
return { imagesOnly: true };
},
uploadDone(upload) {
this.setProperties({
imageUrl: upload.url,
imageId: upload.id,
imageFilesize: upload.human_filesize,
imageFilename: upload.original_filename,
imageWidth: upload.width,
imageHeight: upload.height,
});
this._applyLightbox();
if (this.onUploadDone) {
this.onUploadDone(upload);
}
},
_openLightbox() {
next(() =>
$(this.element.querySelector("a.lightbox")).magnificPopup("open")
);
},
_applyLightbox() {
if (this.imageUrl) {
next(() => lightbox(this.element, this.siteSettings));
}
},
actions: {
toggleLightbox() {
if (this.imageFilename) {
this._openLightbox();
} else {
this.set("loadingLightbox", true);
ajax(`/uploads/lookup-metadata`, {
type: "POST",
data: { url: this.imageUrl },
})
.then((json) => {
this.setProperties({
imageFilename: json.original_filename,
imageFilesize: json.human_filesize,
imageWidth: json.width,
imageHeight: json.height,
});
this._openLightbox();
this.set("loadingLightbox", false);
})
.catch(popupAjaxError);
}
},
trash() {
this.setProperties({ imageUrl: null, imageId: null });
if (this.onUploadDeleted) {
this.onUploadDeleted();
}
},
},
});

View File

@@ -1,134 +0,0 @@
import {
displayErrorForUpload,
validateUploadedFiles,
} from "discourse/lib/uploads";
import I18n from "I18n";
import Mixin from "@ember/object/mixin";
import bootbox from "bootbox";
import { deepMerge } from "discourse-common/lib/object";
import getUrl from "discourse-common/lib/get-url";
import { on } from "@ember/object/evented";
import { warn } from "@ember/debug";
export default Mixin.create({
uploading: false,
uploadProgress: 0,
uploadDone() {
warn("You should implement `uploadDone`", {
id: "discourse.upload.missing-upload-done",
});
},
validateUploadedFilesOptions() {
return {};
},
calculateUploadUrl() {
return (
getUrl(this.getWithDefault("uploadUrl", "/uploads")) +
".json?client_id=" +
(this.messageBus && this.messageBus.clientId) +
this.uploadUrlParams
);
},
uploadUrlParams: "",
uploadOptions() {
return {};
},
_initialize: on("didInsertElement", function () {
const $upload = $(this.element);
const reset = () => {
this.setProperties({ uploading: false, uploadProgress: 0 });
document.getElementsByClassName("hidden-upload-field")[0].value = "";
};
const maxFiles = this.getWithDefault(
"maxFiles",
this.siteSettings.simultaneous_uploads
);
$upload.on("fileuploaddone", (e, data) => {
let upload = data.result;
this.uploadDone(upload);
reset();
});
$upload.fileupload(
deepMerge(
{
url: this.calculateUploadUrl(),
dataType: "json",
replaceFileInput: false,
dropZone: $upload,
pasteZone: $upload,
},
this.uploadOptions()
)
);
$upload.on("fileuploaddrop", (e, data) => {
if (maxFiles > 0 && data.files.length > maxFiles) {
bootbox.alert(
I18n.t("post.errors.too_many_dragged_and_dropped_files", {
count: maxFiles,
})
);
return false;
} else {
return true;
}
});
$upload.on("fileuploadsubmit", (e, data) => {
const opts = deepMerge(
{
bypassNewUserRestriction: true,
user: this.currentUser,
siteSettings: this.siteSettings,
},
this.validateUploadedFilesOptions()
);
const isValid = validateUploadedFiles(data.files, opts);
const type = this.type;
let form = type ? { type } : {};
if (this.data) {
form = Object.assign(form, this.data);
}
data.formData = form;
this.setProperties({ uploadProgress: 0, uploading: isValid });
return isValid;
});
$upload.on("fileuploadprogressall", (e, data) => {
if (this.isDestroying || this.isDestroyed) {
return;
}
const progress = parseInt((data.loaded / data.total) * 100, 10);
this.set("uploadProgress", progress);
});
$upload.on("fileuploadfail", (e, data) => {
displayErrorForUpload(data, this.siteSettings, data.files[0].name);
reset();
});
}),
_destroy: on("willDestroyElement", function () {
this.messageBus && this.messageBus.unsubscribe("/uploads/" + this.type);
const $upload = $(this.element);
try {
$upload.fileupload("destroy");
} catch (e) {
/* wasn't initialized yet */
}
$upload.off();
}),
});

View File

@@ -1,45 +0,0 @@
<div class="uploaded-image-preview input-xxlarge" style={{backgroundStyle}}>
{{#if showingPlaceholder}}
<div class="placeholder-overlay" style={{placeholderStyle}}></div>
{{/if}}
<div class="image-upload-controls">
<label class="btn btn-default pad-left no-text {{if uploading "disabled"}}">
{{d-icon "far-image"}}
<input class="hidden-upload-field" disabled={{uploading}} type="file" accept="image/*">
</label>
{{#if imageUrl}}
{{d-button
action=(action "trash")
class="btn-danger pad-left no-text"
icon="far-trash-alt"
type="button"
}}
{{d-button
icon="discourse-expand"
title="expand"
type="button"
class="image-uploader-lightbox-btn no-text"
action=(action "toggleLightbox")
disabled=loadingLightbox
}}
{{/if}}
<span class="btn {{unless uploading "hidden"}}">{{i18n "upload_selector.uploading"}} {{uploadProgress}}%</span>
</div>
{{#if imageUrl}}
<a class="lightbox"
href={{imageCDNURL}}
title={{imageFilename}}
rel="nofollow ugc noopener">
<div class="meta">
<span class="informations">
{{imageWidth}}x{{imageHeight}} {{imageFilesize}}
</span>
</div>
</a>
{{/if}}
</div>

View File

@@ -42,8 +42,6 @@ module.exports = function (defaults) {
app.import(vendorJs + "bootbox.js");
app.import(vendorJs + "bootstrap-modal.js");
app.import(vendorJs + "jquery.ui.widget.js");
app.import(vendorJs + "jquery.fileupload.js");
app.import(vendorJs + "jquery.fileupload-process.js");
app.import(vendorJs + "caret_position.js");
app.import("node_modules/ember-source/dist/ember-template-compiler.js", {
type: "test",

View File

@@ -1,97 +0,0 @@
import componentTest, {
setupRenderingTest,
} from "discourse/tests/helpers/component-test";
import {
count,
discourseModule,
exists,
} from "discourse/tests/helpers/qunit-helpers";
import { click } from "@ember/test-helpers";
import hbs from "htmlbars-inline-precompile";
discourseModule("Integration | Component | image-uploader", function (hooks) {
setupRenderingTest(hooks);
componentTest("with image", {
template: hbs`
{{image-uploader imageUrl='/images/avatar.png' placeholderUrl='/not/used.png'}}
`,
async test(assert) {
assert.strictEqual(
count(".d-icon-far-image"),
1,
"it displays the upload icon"
);
assert.strictEqual(
count(".d-icon-far-trash-alt"),
1,
"it displays the trash icon"
);
assert.ok(
!exists(".placeholder-overlay"),
"it does not display the placeholder image"
);
await click(".image-uploader-lightbox-btn");
assert.strictEqual(
document.querySelectorAll(".mfp-container").length,
1,
"it displays the image lightbox"
);
},
});
componentTest("without image", {
template: hbs`{{image-uploader}}`,
test(assert) {
assert.strictEqual(
count(".d-icon-far-image"),
1,
"it displays the upload icon"
);
assert.ok(
!exists(".d-icon-far-trash-alt"),
"it does not display trash icon"
);
assert.ok(
!exists(".image-uploader-lightbox-btn"),
"it does not display the button to open image lightbox"
);
},
});
componentTest("with placeholder", {
template: hbs`{{image-uploader placeholderUrl='/images/avatar.png'}}`,
test(assert) {
assert.strictEqual(
count(".d-icon-far-image"),
1,
"it displays the upload icon"
);
assert.ok(
!exists(".d-icon-far-trash-alt"),
"it does not display trash icon"
);
assert.ok(
!exists(".image-uploader-lightbox-btn"),
"it does not display the button to open image lightbox"
);
assert.strictEqual(
count(".placeholder-overlay"),
1,
"it displays the placeholder image"
);
},
});
});

View File

@@ -18,9 +18,6 @@
//= require popper.js
//= require bootstrap-modal.js
//= require caret_position
//= require jquery.fileupload.js
//= require jquery.iframe-transport.js
//= require jquery.fileupload-process.js
//= require jquery.sortable.js
//= require lodash.js
//= require itsatrap.js

View File

@@ -11,9 +11,6 @@
//= require popper.js
//= require bootstrap-modal.js
//= require caret_position
//= require jquery.fileupload.js
//= require jquery.iframe-transport.js
//= require jquery.fileupload-process.js
//= require jquery.sortable.js
//= require lodash.js
//= require itsatrap.js

View File

@@ -1,7 +1,6 @@
//= require ember_jquery
//= require template_include.js
//= require jquery.ui.widget.js
//= require jquery.fileupload.js
//= require uppy.js
//= require bootstrap-modal.js
//= require bootbox.js