Skip to content

Commit b6e8a60

Browse files
committed
reworked image upload to use QPixel#fetch helper
1 parent 3cd4742 commit b6e8a60

4 files changed

Lines changed: 40 additions & 35 deletions

File tree

app/assets/javascripts/posts.js

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ $(() => {
5757

5858
const $fileInput = $tgt.find('input[type="file"]');
5959
const files = /** @type {HTMLInputElement} */ ($fileInput[0]).files;
60+
const form = /** @type {HTMLFormElement} */ ($tgt[0]);
6061

6162
// TODO: MaxUploadSize is a site setting and can be changed
6263
if (files.length > 0 && files[0].size >= 2000000) {
@@ -80,40 +81,23 @@ $(() => {
8081
$tgt.find('.js-max-size').removeClass('has-color-red-700');
8182
}
8283

83-
const resp = await fetch($tgt.attr('action'), {
84-
method: $tgt.attr('method'),
85-
body: new FormData(/** @type {HTMLFormElement} */ ($tgt[0]))
84+
const data = await QPixel.upload($tgt.attr('action'), form);
85+
86+
QPixel.handleJSONResponse(data, (data) => {
87+
form.reset();
88+
89+
const $postField = $('.js-post-field');
90+
const postText = $postField.val()?.toString();
91+
$postField.val(postText.replace(placeholder, `![Image_alt_text](${data.link})`));
92+
$tgt.parents('.modal').removeClass('is-active');
93+
94+
$postFields.trigger('change');
95+
}, (data) => {
96+
if (data.status === 'failed') {
97+
const $postField = $('.js-post-field');
98+
$postField.val($postField.val()?.toString().replace(placeholder, ''));
99+
}
86100
});
87-
88-
const data = await resp.json();
89-
90-
if (resp.status === 200) {
91-
$tgt.trigger('ajax:success', data);
92-
}
93-
else {
94-
$tgt.trigger('ajax:failure', data);
95-
}
96-
});
97-
98-
$uploadForm.on('ajax:success', async (evt, data) => {
99-
const $tgt = $(evt.target);
100-
/** @type {HTMLFormElement} */ ($tgt[0]).reset();
101-
102-
const $postField = $('.js-post-field');
103-
const postText = $postField.val()?.toString();
104-
$postField.val(postText.replace(placeholder, `![Image_alt_text](${data.link})`));
105-
$tgt.parents('.modal').removeClass('is-active');
106-
107-
$postFields.trigger('change')
108-
});
109-
110-
$uploadForm.on('ajax:failure', async (evt, data) => {
111-
const $tgt = $(evt.target);
112-
const $postField = $('.js-post-field');
113-
const error = data['error'];
114-
QPixel.createNotification('danger', error);
115-
$tgt.parents('.modal').removeClass('is-active');
116-
$postField.val($postField.val()?.toString().replace(placeholder, ''));
117101
});
118102

119103
/**

app/assets/javascripts/qpixel_api.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,15 @@ window.QPixel = {
457457
return QPixel.parseJSONResponse(resp, 'Failed to vote');
458458
},
459459

460+
upload: async (url, form) => {
461+
const resp = await QPixel.fetch(url, {
462+
method: 'POST',
463+
body: new FormData(form)
464+
});
465+
466+
return QPixel.parseJSONResponse(resp, 'Failed to upload');
467+
},
468+
460469
archiveThread: async (id) => {
461470
const resp = await QPixel.fetchJSON(`/comments/thread/${id}/archive`, {}, {
462471
headers: { 'Accept': 'application/json' },

app/controllers/posts_controller.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,14 +510,16 @@ def document
510510

511511
def upload
512512
unless helpers.valid_upload?(params[:file])
513-
render json: { error: "Images must be one of #{helpers.allowed_upload_extensions.join(', ')}" },
513+
render json: { status: 'failed',
514+
message: "Images must be one of #{helpers.allowed_upload_extensions.join(', ')}" },
514515
status: :bad_request
515516
return
516517
end
517518

518519
@blob = ActiveStorage::Blob.create_and_upload!(io: params[:file], filename: params[:file].original_filename,
519520
content_type: params[:file].content_type)
520-
render json: { link: uploaded_url(@blob.key) }
521+
render json: { status: 'success',
522+
link: uploaded_url(@blob.key) }
521523
end
522524

523525
def help_center

global.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ type QPixelResponseJSON<
213213
Success extends object = object
214214
> = (Success & QPixelSuccessResponseJSON) | QPixelFailedResponseJSON
215215

216+
type QPixelUploadResponseJSON = QPixelResponseJSON<{
217+
link: string
218+
}>
219+
216220
type QPixelVoteResponseJSON = QPixelResponseJSON<{
217221
vote_id: number
218222
upvotes: number
@@ -640,6 +644,12 @@ interface QPixel {
640644
*/
641645
vote?: (postId: string, voteType: string) => Promise<QPixelVoteResponseJSON>
642646

647+
/**
648+
* @param url upload endpoint URL (differs between routes)
649+
* @param form upload form to get the file from
650+
*/
651+
upload?: (url: string, form: HTMLFormElement) => Promise<QPixelUploadResponseJSON>
652+
643653
// qpixel_dom
644654
DOM?: QPixelDOM;
645655
// qpixel Markdown

0 commit comments

Comments
 (0)