Fix JS and JS-based image upload
This commit is contained in:
parent
36984ff1d4
commit
fa8a7fc77a
6 changed files with 95 additions and 51 deletions
|
|
@ -1,21 +1,23 @@
|
||||||
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
|
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
|
||||||
import "@hotwired/turbo-rails"
|
// import "@hotwired/turbo-rails"
|
||||||
import "controllers"
|
// import "controllers"
|
||||||
|
|
||||||
// Initialize the upload form.
|
// Initialize the upload form.
|
||||||
function upload_form_init() {
|
function upload_form_init() {
|
||||||
// Disable the submit button if Javascript is supported.
|
// Disable the submit button if Javascript is supported.
|
||||||
// Upload will start right after selecting images.
|
// Upload will start right after selecting images.
|
||||||
// $("#file-submit").hide();
|
const fileSubmit = document.getElementById("file-submit");
|
||||||
document.getElementById("file-submit").style.display = "none";
|
if (fileSubmit)
|
||||||
|
{
|
||||||
|
fileSubmit.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
// Install event handler to notice when files were selected.
|
// Install event handler to notice when files were selected.
|
||||||
// $("#file").on("change", upload_form_files_selected);
|
document.getElementById("file")?.addEventListener("change", upload_form_files_selected);
|
||||||
document.getElementById("file").addEventListener("change", upload_form_files_selected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function upload_form_files_selected() {
|
function upload_form_files_selected() {
|
||||||
no_files = this.files.length;
|
var no_files = this.files.length;
|
||||||
if (no_files > 0) {
|
if (no_files > 0) {
|
||||||
document.getElementById("file-label").innerHTML = `${no_files} files selected - uploading…`;
|
document.getElementById("file-label").innerHTML = `${no_files} files selected - uploading…`;
|
||||||
document.getElementById("file-select-button").disabled = true;
|
document.getElementById("file-select-button").disabled = true;
|
||||||
|
|
@ -28,7 +30,7 @@ function upload_form_files_selected() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Ctrl-V to paste an image directly
|
// Handle Ctrl-V to paste an image directly
|
||||||
export function upload_paste_handler(event) {
|
function upload_paste_handler(event, uploadUrl) {
|
||||||
console.log("paste!");
|
console.log("paste!");
|
||||||
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||||
|
|
||||||
|
|
@ -48,45 +50,48 @@ export function upload_paste_handler(event) {
|
||||||
console.log(item.type);
|
console.log(item.type);
|
||||||
var file = item.getAsFile();
|
var file = item.getAsFile();
|
||||||
console.log(file);
|
console.log(file);
|
||||||
upload_file_with_ajax(file);
|
upload_file_with_ajax(file, uploadUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function upload_file_with_ajax(file) {
|
function upload_file_with_ajax(file, uploadUrl) {
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
console.log("File was null. Strange.");
|
console.log("File was null. Strange.");
|
||||||
display_error("Maybe the image was too large.");
|
display_error("Maybe the image was too large.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
|
console.log(formData);
|
||||||
|
|
||||||
fetch(ajax_upload_url, {
|
fetch(uploadUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: formData,
|
body: formData,
|
||||||
headers: {
|
headers: {
|
||||||
|
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content,
|
||||||
// 'Content-Type' is omitted to let the browser set it automatically
|
// 'Content-Type' is omitted to let the browser set it automatically
|
||||||
// with the proper boundary for FormData
|
// with the proper boundary for FormData
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(async (response) => {
|
.then(async (response) => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
console.log(`AJAX file upload returned error: ${response.statusText}`);
|
console.log(`AJAX file upload returned error: ${response.statusText}`);
|
||||||
display_error(errorData);
|
display_error(errorData);
|
||||||
throw new Error("Upload failed");
|
throw new Error("Upload failed");
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log("AJAX file upload was ok");
|
console.log("AJAX file upload was ok");
|
||||||
window.location.replace(after_upload_url);
|
window.location.replace(after_upload_url);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error.message !== "Upload failed") {
|
if (error.message !== "Upload failed") {
|
||||||
console.log(`AJAX file upload error: ${error}`);
|
console.log(`AJAX file upload error: ${error}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// $.ajax(ajax_upload_url, {
|
// $.ajax(ajax_upload_url, {
|
||||||
// type: "POST",
|
// type: "POST",
|
||||||
|
|
@ -107,7 +112,8 @@ function upload_file_with_ajax(file) {
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
function display_error(msg) {
|
function display_error(msg) { console.log("foo");
|
||||||
|
|
||||||
// $("#messages").html(
|
// $("#messages").html(
|
||||||
// '<div class="callout alert alert-callout-subtle radius">Sorry, pasting did not work. ' + msg + "</div>"
|
// '<div class="callout alert alert-callout-subtle radius">Sorry, pasting did not work. ' + msg + "</div>"
|
||||||
// );
|
// );
|
||||||
|
|
@ -117,3 +123,21 @@ function display_error(msg) {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
console.log("DOM loaded");
|
||||||
|
// Handle uploads on specific views/pages. The DIV with ID
|
||||||
|
// #data-js-upload-form carries data attributes that tell us where
|
||||||
|
// uploads will be sent from Javascript.
|
||||||
|
let element = document.getElementById("data-js-upload-form");
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
console.log("upload_form_init");
|
||||||
|
// console.log(element.dataset);
|
||||||
|
// console.log(element.dataset.uploadUrl);
|
||||||
|
upload_form_init(element.dataset.uploadUrl);
|
||||||
|
// document.onpaste = upload_paste_handler(element.dataset.uploadUrl);
|
||||||
|
document.onpaste = function(event) { upload_paste_handler(event, element.dataset.uploadUrl); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
/ Render this callout on top of the package's details page
|
/ Render this callout on top of the package's details page
|
||||||
/ if images have just been uploaded.
|
/ if images have just been uploaded.
|
||||||
|
|
||||||
|
// Make variables accessible by the JS that handles uploads
|
||||||
|
#data-js-upload-form data-upload-url=upload_receive_json_path
|
||||||
|
|
||||||
- if (@valid_images and @valid_images.any?) or (@invalid_images and @invalid_images.any?)
|
- if (@valid_images and @valid_images.any?) or (@invalid_images and @invalid_images.any?)
|
||||||
.callout.warning
|
.callout.warning
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,13 +66,8 @@
|
||||||
= render(partial: 'details_rightbox', locals: {pkg: @package})
|
= render(partial: 'details_rightbox', locals: {pkg: @package})
|
||||||
|
|
||||||
javascript:
|
javascript:
|
||||||
import {upload_paste_handler} from 'aplication';
|
|
||||||
|
|
||||||
// Handle Ctrl-V to paste an image directly
|
|
||||||
document.onpaste = upload_paste_handler;
|
|
||||||
|
|
||||||
// Where to send POST requests for uploads
|
// Where to send POST requests for uploads
|
||||||
var ajax_upload_url = '#{{upload_receive_json_path}}';
|
let ajax_upload_url = '#{{upload_receive_json_path}}';
|
||||||
|
|
||||||
// Where to go to after a successful image upload
|
// Where to go to after a successful image upload
|
||||||
var after_upload_url = '#{{package_path(@package)}}';
|
let after_upload_url = '#{{package_path(@package)}}';
|
||||||
|
|
|
||||||
|
|
@ -64,18 +64,11 @@ h1 = "Upload screenshots for #{@package.name}"
|
||||||
' from a shell using after setting "export LANG=C".
|
' from a shell using after setting "export LANG=C".
|
||||||
li can be pasted here from your clipboard (Ctrl-V)
|
li can be pasted here from your clipboard (Ctrl-V)
|
||||||
|
|
||||||
/ javascript:
|
javascript:
|
||||||
/ // Hide the submit button unless images are selected for upload
|
// todo: use data attributes to pass this information to javascript
|
||||||
/ // $(document).ready(upload_form_init);
|
// https://chat.deepseek.com/a/chat/s/41a4350b-7799-42bf-aec9-3c205b22ab24
|
||||||
/ import upload_form_init from '../../assets/javascripts/upload.js';
|
// Where to send POST requests for uploads
|
||||||
/ document.addEventListener('DOMContentLoaded', upload_form_init);
|
let ajax_upload_url = '#{{upload_receive_json_path}}';
|
||||||
|
|
||||||
/ // import upload_paste_handler from '../../assets/javascripts/debshots.js';
|
// Where to go to after a successful image upload
|
||||||
/ // Handle Ctrl-V to paste an image directly
|
let after_upload_url = '#{{package_path(@package)}}';
|
||||||
/ document.onpaste = upload_paste_handler;
|
|
||||||
|
|
||||||
/ // Where to send POST requests for uploads
|
|
||||||
/ var ajax_upload_url = '#{{upload_receive_json_path}}';
|
|
||||||
|
|
||||||
/ // Where to go to after a successful image upload
|
|
||||||
/ var after_upload_url = '#{{package_path(@package)}}';
|
|
||||||
|
|
|
||||||
7
config/importmap.rb
Normal file
7
config/importmap.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Pin npm packages by running ./bin/importmap
|
||||||
|
|
||||||
|
pin 'application'
|
||||||
|
pin '@hotwired/turbo-rails', to: 'turbo.min.js'
|
||||||
|
pin '@hotwired/stimulus', to: 'stimulus.min.js'
|
||||||
|
pin '@hotwired/stimulus-loading', to: 'stimulus-loading.js'
|
||||||
|
pin_all_from 'app/javascript/controllers', under: 'controllers'
|
||||||
21
config/webpack/webpack.config.js
Normal file
21
config/webpack/webpack.config.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
const path = require("path")
|
||||||
|
const webpack = require("webpack")
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mode: "production",
|
||||||
|
devtool: "source-map",
|
||||||
|
entry: {
|
||||||
|
application: "./app/javascript/application.js"
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: "[name].js",
|
||||||
|
sourceMapFilename: "[file].map",
|
||||||
|
chunkFormat: "module",
|
||||||
|
path: path.resolve(__dirname, '..', '..', 'app/assets/builds')
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.optimize.LimitChunkCountPlugin({
|
||||||
|
maxChunks: 1
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue