Current section

Files

Jump to
phoenix_live_view assets js phoenix_live_view upload_entry.js
Raw

assets/js/phoenix_live_view/upload_entry.js

import {
PHX_ACTIVE_ENTRY_REFS,
PHX_LIVE_FILE_UPDATED,
PHX_PREFLIGHTED_REFS,
} from "./constants";
import { channelUploader, logError } from "./utils";
import LiveUploader from "./live_uploader";
export default class UploadEntry {
static isActive(fileEl, file) {
const isNew = file._phxRef === undefined;
const activeRefs = fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(",");
const isActive = activeRefs.indexOf(LiveUploader.genFileRef(file)) >= 0;
return file.size > 0 && (isNew || isActive);
}
static isPreflighted(fileEl, file) {
const preflightedRefs = fileEl
.getAttribute(PHX_PREFLIGHTED_REFS)
.split(",");
const isPreflighted =
preflightedRefs.indexOf(LiveUploader.genFileRef(file)) >= 0;
return isPreflighted && this.isActive(fileEl, file);
}
static isPreflightInProgress(file) {
return file._preflightInProgress === true;
}
static markPreflightInProgress(file) {
file._preflightInProgress = true;
}
constructor(fileEl, file, view, autoUpload) {
this.ref = LiveUploader.genFileRef(file);
this.fileEl = fileEl;
this.file = file;
this.view = view;
this.meta = null;
this._isCancelled = false;
this._isDone = false;
this._progress = 0;
this._lastProgressSent = -1;
this._onDone = function () {};
this._onElUpdated = this.onElUpdated.bind(this);
this.fileEl.addEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated);
this.autoUpload = autoUpload;
}
metadata() {
return this.meta;
}
progress(progress) {
this._progress = Math.floor(progress);
if (this._progress > this._lastProgressSent) {
if (this._progress >= 100) {
this._progress = 100;
this._lastProgressSent = 100;
this._isDone = true;
this.view.pushFileProgress(this.fileEl, this.ref, 100, () => {
LiveUploader.untrackFile(this.fileEl, this.file);
this._onDone();
});
} else {
this._lastProgressSent = this._progress;
this.view.pushFileProgress(this.fileEl, this.ref, this._progress);
}
}
}
isCancelled() {
return this._isCancelled;
}
cancel() {
this.file._preflightInProgress = false;
this._isCancelled = true;
this._isDone = true;
this._onDone();
}
isDone() {
return this._isDone;
}
error(reason = "failed") {
this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated);
this.view.pushFileProgress(this.fileEl, this.ref, { error: reason });
if (!this.isAutoUpload()) {
LiveUploader.clearFiles(this.fileEl);
}
}
isAutoUpload() {
return this.autoUpload;
}
//private
onDone(callback) {
this._onDone = () => {
this.fileEl.removeEventListener(PHX_LIVE_FILE_UPDATED, this._onElUpdated);
callback();
};
}
onElUpdated() {
const activeRefs = this.fileEl
.getAttribute(PHX_ACTIVE_ENTRY_REFS)
.split(",");
if (activeRefs.indexOf(this.ref) === -1) {
LiveUploader.untrackFile(this.fileEl, this.file);
this.cancel();
}
}
toPreflightPayload() {
return {
last_modified: this.file.lastModified,
name: this.file.name,
relative_path: this.file.webkitRelativePath,
size: this.file.size,
type: this.file.type,
ref: this.ref,
meta: typeof this.file.meta === "function" ? this.file.meta() : undefined,
};
}
uploader(uploaders) {
if (this.meta.uploader) {
const callback =
uploaders[this.meta.uploader] ||
logError(`no uploader configured for ${this.meta.uploader}`);
return { name: this.meta.uploader, callback: callback };
} else {
return { name: "channel", callback: channelUploader };
}
}
zipPostFlight(resp) {
this.meta = resp.entries[this.ref];
if (!this.meta) {
logError(`no preflight upload response returned with ref ${this.ref}`, {
input: this.fileEl,
response: resp,
});
}
}
}