javascript: move auto-upload attachment to the Uploader class
Rationale: - It makes more sense to handle the progress bar updates in a single class; - This will allow us to unify the error handling.
This commit is contained in:
parent
256362efd3
commit
d8f3b86b0e
2 changed files with 57 additions and 59 deletions
|
@ -1,6 +1,5 @@
|
|||
import Uploader from '../../shared/activestorage/uploader';
|
||||
import ProgressBar from '../../shared/activestorage/progress-bar';
|
||||
import { ajax, show, hide, toggle } from '@utils';
|
||||
import { show, hide, toggle } from '@utils';
|
||||
|
||||
// Given a file input in a champ with a selected file, upload a file,
|
||||
// then attach it to the dossier.
|
||||
|
@ -11,27 +10,19 @@ export default class AutoUploadController {
|
|||
constructor(input, file) {
|
||||
this.input = input;
|
||||
this.file = file;
|
||||
this.uploader = new Uploader(
|
||||
input,
|
||||
file,
|
||||
input.dataset.directUploadUrl,
|
||||
input.dataset.autoAttachUrl
|
||||
);
|
||||
}
|
||||
|
||||
async start() {
|
||||
try {
|
||||
this._begin();
|
||||
|
||||
// Sanity checks
|
||||
const autoAttachUrl = this.input.dataset.autoAttachUrl;
|
||||
if (!autoAttachUrl) {
|
||||
throw new Error('L’attribut "data-auto-attach-url" est manquant');
|
||||
}
|
||||
|
||||
// Upload the file (using Direct Upload)
|
||||
let blobSignedId = await this._upload();
|
||||
|
||||
// Attach the blob to the champ
|
||||
// (The request responds with Javascript, which displays the attachment HTML fragment).
|
||||
await this._attach(blobSignedId, autoAttachUrl);
|
||||
|
||||
// Everything good: clear the original file input value
|
||||
this.input.value = null;
|
||||
await this.uploader.start();
|
||||
this._succeeded();
|
||||
} catch (error) {
|
||||
this._failed(error);
|
||||
throw error;
|
||||
|
@ -45,35 +36,8 @@ export default class AutoUploadController {
|
|||
this._hideErrorMessage();
|
||||
}
|
||||
|
||||
async _upload() {
|
||||
const uploader = new Uploader(
|
||||
this.input,
|
||||
this.file,
|
||||
this.input.dataset.directUploadUrl
|
||||
);
|
||||
return await uploader.start();
|
||||
}
|
||||
|
||||
async _attach(blobSignedId, autoAttachUrl) {
|
||||
// Now that the upload is done, display a new progress bar
|
||||
// to show that the attachment request is still pending.
|
||||
const progressBar = new ProgressBar(
|
||||
this.input,
|
||||
`${this.input.id}-progress-bar`,
|
||||
this.file
|
||||
);
|
||||
progressBar.progress(100);
|
||||
progressBar.end();
|
||||
|
||||
const attachmentRequest = {
|
||||
url: autoAttachUrl,
|
||||
type: 'PUT',
|
||||
data: `blob_signed_id=${blobSignedId}`
|
||||
};
|
||||
await ajax(attachmentRequest);
|
||||
|
||||
// The progress bar has been destroyed by the attachment HTML fragment that replaced the input,
|
||||
// so no further cleanup is needed.
|
||||
_succeeded() {
|
||||
this.input.value = null;
|
||||
}
|
||||
|
||||
_failed(error) {
|
||||
|
@ -81,12 +45,10 @@ export default class AutoUploadController {
|
|||
return;
|
||||
}
|
||||
|
||||
let progressBar = this.input.parentElement.querySelector('.direct-upload');
|
||||
if (progressBar) {
|
||||
progressBar.remove();
|
||||
}
|
||||
this.uploader.progressBar.destroy();
|
||||
|
||||
this._displayErrorMessage(error);
|
||||
let message = this._messageFromError(error);
|
||||
this._displayErrorMessage(message);
|
||||
}
|
||||
|
||||
_done() {
|
||||
|
@ -126,11 +88,10 @@ export default class AutoUploadController {
|
|||
}
|
||||
}
|
||||
|
||||
_displayErrorMessage(error) {
|
||||
_displayErrorMessage(message) {
|
||||
let errorNode = this.input.parentElement.querySelector('.attachment-error');
|
||||
if (errorNode) {
|
||||
show(errorNode);
|
||||
let message = this._messageFromError(error);
|
||||
errorNode.querySelector('.attachment-error-title').textContent =
|
||||
message.title || '';
|
||||
errorNode.querySelector('.attachment-error-description').textContent =
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { DirectUpload } from '@rails/activestorage';
|
||||
import { ajax } from '@utils';
|
||||
import ProgressBar from './progress-bar';
|
||||
import errorFromDirectUploadMessage from './errors';
|
||||
|
||||
|
@ -7,29 +8,65 @@ import errorFromDirectUploadMessage from './errors';
|
|||
used to track lifecycle and progress of an upload.
|
||||
*/
|
||||
export default class Uploader {
|
||||
constructor(input, file, directUploadUrl) {
|
||||
constructor(input, file, directUploadUrl, autoAttachUrl) {
|
||||
this.directUpload = new DirectUpload(file, directUploadUrl, this);
|
||||
this.progressBar = new ProgressBar(input, this.directUpload.id, file);
|
||||
this.autoAttachUrl = autoAttachUrl;
|
||||
}
|
||||
|
||||
start() {
|
||||
/**
|
||||
Upload (and optionally attach) the file.
|
||||
Returns the blob signed id on success.
|
||||
*/
|
||||
async start() {
|
||||
this.progressBar.start();
|
||||
|
||||
try {
|
||||
let blobSignedId = await this._upload();
|
||||
|
||||
if (this.autoAttachUrl) {
|
||||
await this._attach(blobSignedId);
|
||||
}
|
||||
|
||||
this.progressBar.end();
|
||||
this.progressBar.destroy();
|
||||
|
||||
return blobSignedId;
|
||||
} catch (error) {
|
||||
this.progressBar.error(error.message);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Upload the file using the DirectUpload instance, and return the blob signed_id.
|
||||
*/
|
||||
async _upload() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.directUpload.create((errorMsg, attributes) => {
|
||||
if (errorMsg) {
|
||||
this.progressBar.error(errorMsg);
|
||||
let error = errorFromDirectUploadMessage(errorMsg);
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(attributes.signed_id);
|
||||
}
|
||||
this.progressBar.end();
|
||||
this.progressBar.destroy();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
Attach the file by sending a POST request to the autoAttachUrl.
|
||||
*/
|
||||
async _attach(blobSignedId) {
|
||||
const attachmentRequest = {
|
||||
url: this.autoAttachUrl,
|
||||
type: 'PUT',
|
||||
data: `blob_signed_id=${blobSignedId}`
|
||||
};
|
||||
|
||||
await ajax(attachmentRequest);
|
||||
}
|
||||
|
||||
uploadRequestDidProgress(event) {
|
||||
const progress = (event.loaded / event.total) * 100;
|
||||
if (progress) {
|
||||
|
|
Loading…
Reference in a new issue