99 lines
2.6 KiB
JavaScript
99 lines
2.6 KiB
JavaScript
import { DirectUpload } from '@rails/activestorage';
|
|
import { ajax } from '@utils';
|
|
import ProgressBar from './progress-bar';
|
|
import FileUploadError, {
|
|
errorFromDirectUploadMessage,
|
|
ERROR_CODE_ATTACH
|
|
} from './file-upload-error';
|
|
|
|
/**
|
|
Uploader class is a delegate for DirectUpload instance
|
|
used to track lifecycle and progress of an upload.
|
|
*/
|
|
export default class Uploader {
|
|
constructor(input, file, directUploadUrl, autoAttachUrl) {
|
|
this.directUpload = new DirectUpload(file, directUploadUrl, this);
|
|
this.progressBar = new ProgressBar(input, this.directUpload.id, file);
|
|
this.autoAttachUrl = autoAttachUrl;
|
|
}
|
|
|
|
/**
|
|
Upload (and optionally attach) the file.
|
|
Returns the blob signed id on success.
|
|
Throws a FileUploadError on failure.
|
|
*/
|
|
async start() {
|
|
this.progressBar.start();
|
|
|
|
try {
|
|
let blobSignedId = await this._upload();
|
|
|
|
if (this.autoAttachUrl) {
|
|
await this._attach(blobSignedId);
|
|
// On response, the attachment HTML fragment will replace the progress bar.
|
|
} else {
|
|
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.
|
|
Throws a FileUploadError on failure.
|
|
*/
|
|
async _upload() {
|
|
return new Promise((resolve, reject) => {
|
|
this.directUpload.create((errorMsg, attributes) => {
|
|
if (errorMsg) {
|
|
let error = errorFromDirectUploadMessage(errorMsg);
|
|
reject(error);
|
|
} else {
|
|
resolve(attributes.signed_id);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
Attach the file by sending a POST request to the autoAttachUrl.
|
|
Throws a FileUploadError on failure (containing the first validation
|
|
error message, if any).
|
|
*/
|
|
async _attach(blobSignedId) {
|
|
const attachmentRequest = {
|
|
url: this.autoAttachUrl,
|
|
type: 'PUT',
|
|
data: `blob_signed_id=${blobSignedId}`
|
|
};
|
|
|
|
try {
|
|
await ajax(attachmentRequest);
|
|
} catch (e) {
|
|
let message = e.response && e.response.errors && e.response.errors[0];
|
|
throw new FileUploadError(
|
|
message || 'Error attaching file.',
|
|
e.xhr.status,
|
|
ERROR_CODE_ATTACH
|
|
);
|
|
}
|
|
}
|
|
|
|
uploadRequestDidProgress(event) {
|
|
const progress = (event.loaded / event.total) * 100;
|
|
if (progress) {
|
|
this.progressBar.progress(progress);
|
|
}
|
|
}
|
|
|
|
directUploadWillStoreFileWithXHR(xhr) {
|
|
xhr.upload.addEventListener('progress', (event) =>
|
|
this.uploadRequestDidProgress(event)
|
|
);
|
|
}
|
|
}
|