js: reorganize Javascript file structure.
Move Javascript files from app/components/**/*.js back to app/javascript/src/javascripts/*.js. This way Javascript files are in one place, which simplifies import paths and makes it easier to see all Javascript at once.
This commit is contained in:
@@ -1,163 +0,0 @@
|
||||
import Dropzone from 'dropzone';
|
||||
import Utility from "../../javascript/src/javascripts/utility.js";
|
||||
import capitalize from "lodash/capitalize";
|
||||
|
||||
export default class FileUploadComponent {
|
||||
static initialize() {
|
||||
$(".file-upload-component").toArray().forEach(element => {
|
||||
new FileUploadComponent($(element));
|
||||
});
|
||||
}
|
||||
|
||||
constructor($component) {
|
||||
this.$component = $component;
|
||||
this.$component.on("ajax:success", e => this.onSubmit(e));
|
||||
this.$component.on("ajax:error", e => this.onError(e));
|
||||
this.$dropTarget.on("paste.danbooru", e => this.onPaste(e));
|
||||
this.dropzone = this.initializeDropzone();
|
||||
|
||||
// If the source field is pre-filled, then immediately submit the upload.
|
||||
if (/^https?:\/\//.test(this.$sourceField.val())) {
|
||||
this.$component.find("input[type='submit']").click();
|
||||
}
|
||||
}
|
||||
|
||||
initializeDropzone() {
|
||||
if (!window.FileReader) {
|
||||
this.$dropzone.addClass("hidden");
|
||||
this.$component.find("input[type='file']").removeClass("hidden");
|
||||
return null;
|
||||
}
|
||||
|
||||
let dropzone = new Dropzone(this.$dropTarget.get(0), {
|
||||
url: "/uploads.json",
|
||||
paramName: "upload[file]",
|
||||
clickable: this.$dropzone.get(0),
|
||||
previewsContainer: this.$dropzone.get(0),
|
||||
thumbnailHeight: null,
|
||||
thumbnailWidth: null,
|
||||
addRemoveLinks: false,
|
||||
maxFiles: 1,
|
||||
maxFilesize: this.maxFileSize,
|
||||
maxThumbnailFilesize: this.maxFileSize,
|
||||
timeout: 0,
|
||||
acceptedFiles: "image/jpeg,image/png,image/gif,video/mp4,video/webm",
|
||||
previewTemplate: this.$component.find(".dropzone-preview-template").html(),
|
||||
});
|
||||
|
||||
dropzone.on("complete", file => {
|
||||
this.$dropzone.find(".dz-progress").hide();
|
||||
});
|
||||
|
||||
dropzone.on("addedfile", file => {
|
||||
this.$dropzone.removeClass("error");
|
||||
this.$dropzone.find(".dropzone-hint").hide();
|
||||
|
||||
// Remove all files except the file just added.
|
||||
dropzone.files.forEach(f => {
|
||||
if (f !== file) {
|
||||
dropzone.removeFile(f);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
dropzone.on("success", file => {
|
||||
this.$dropzone.addClass("success");
|
||||
let upload = JSON.parse(file.xhr.response)
|
||||
this.pollStatus(upload);
|
||||
});
|
||||
|
||||
dropzone.on("error", (file, msg) => {
|
||||
this.$dropzone.addClass("error");
|
||||
});
|
||||
|
||||
return dropzone;
|
||||
}
|
||||
|
||||
onPaste(e) {
|
||||
let url = e.originalEvent.clipboardData.getData("text");
|
||||
this.$component.find("input[name='upload[source]']:not([disabled])").val(url);
|
||||
|
||||
if (/^https?:\/\//.test(url)) {
|
||||
this.$component.find("input[type='submit']:not([disabled])").click();
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
onSubmit(e) {
|
||||
let upload = e.originalEvent.detail[0];
|
||||
this.pollStatus(upload);
|
||||
}
|
||||
|
||||
// Called after the upload is submitted via AJAX. Polls the upload until it
|
||||
// is complete, then redirects to the upload page.
|
||||
async pollStatus(upload) {
|
||||
this.$component.find("progress").removeClass("hidden");
|
||||
this.$component.find("input").attr("disabled", "disabled");
|
||||
|
||||
while (upload.status === "pending" || upload.status === "processing") {
|
||||
await Utility.delay(500);
|
||||
upload = await $.get(`/uploads/${upload.id}.json`);
|
||||
}
|
||||
|
||||
if (upload.status === "completed") {
|
||||
let params = new URLSearchParams(window.location.search);
|
||||
let isBookmarklet = params.has("url");
|
||||
params.delete("url");
|
||||
params.delete("ref");
|
||||
|
||||
let url = new URL(`/uploads/${upload.id}`, window.location.origin);
|
||||
url.search = params.toString();
|
||||
|
||||
if (isBookmarklet) {
|
||||
window.location.replace(url);
|
||||
} else {
|
||||
window.location.assign(url);
|
||||
}
|
||||
} else if (upload.status === "error") {
|
||||
this.$dropzone.removeClass("success");
|
||||
this.$component.find("progress").addClass("hidden");
|
||||
this.$component.find("input").removeAttr("disabled");
|
||||
|
||||
Utility.error(`Upload failed: ${upload.error}.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Called when creating the upload failed because of a validation error (normally, because the source URL was not a real URL).
|
||||
async onError(e) {
|
||||
let errors = e.originalEvent.detail[0].errors;
|
||||
let message = Object.keys(errors).map(attribute => {
|
||||
return errors[attribute].map(error => {
|
||||
if (attribute === "base") {
|
||||
return `${error}`;
|
||||
} else {
|
||||
return `${capitalize(attribute)} ${error}`;
|
||||
}
|
||||
});
|
||||
}).join("; ");
|
||||
|
||||
Utility.error(message);
|
||||
}
|
||||
|
||||
get $dropzone() {
|
||||
return this.$component.find(".dropzone-container");
|
||||
}
|
||||
|
||||
get $sourceField() {
|
||||
return this.$component.find("input[name='upload[source]']");
|
||||
}
|
||||
|
||||
get maxFileSize() {
|
||||
return Number(this.$component.attr("data-max-file-size")) / (1024 * 1024);
|
||||
}
|
||||
|
||||
// The element to listen for drag and drop events and paste events. By default,
|
||||
// it's the `.file-upload-component` element. If `data-drop-target` is the `body`
|
||||
// element, then you can drop images or paste URLs anywhere on the page.
|
||||
get $dropTarget() {
|
||||
return $(this.$component.attr("data-drop-target") || this.$component);
|
||||
}
|
||||
}
|
||||
|
||||
$(FileUploadComponent.initialize);
|
||||
Reference in New Issue
Block a user