@progress/kendo-vue-upload
Version:
490 lines (489 loc) • 13.8 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import { defineComponent as E, createVNode as D } from "vue";
import { validatePackage as w, templateRendering as A, getListeners as _, getTabIndex as B } from "@progress/kendo-vue-common";
import { UploadFileStatus as u } from "./interfaces/UploadFileStatus.mjs";
import { UploadNavigation as N } from "./UploadNavigation.mjs";
import m from "axios";
import F from "./utils/utils.mjs";
import r from "./utils/stateUtils.mjs";
import d from "./utils/connectionUtils.mjs";
import O from "./utils/validationUtils.mjs";
import { packageMetadata as x } from "./package-metadata.mjs";
const Q = /* @__PURE__ */ E({
name: "KendoVueUpload",
props: {
autoUpload: {
type: Boolean,
default: !0
},
batch: {
type: Boolean,
default: !1
},
withCredentials: {
type: Boolean,
default: !0
},
saveField: {
type: String,
default: function() {
return "files";
}
},
saveHeaders: {
type: [String, Function, Object],
default: function() {
return {};
}
},
saveMethod: {
type: String,
default: function() {
return "POST";
}
},
saveUrl: {
type: [String, Function],
default: function() {
return "";
}
},
responseType: {
type: String,
default: function() {
return "json";
}
},
removeField: {
type: String,
default: function() {
return "fileNames";
}
},
removeHeaders: {
type: [String, Function, Object],
default: function() {
return {};
}
},
removeMethod: {
type: String,
default: function() {
return "POST";
}
},
removeUrl: {
type: [String, Function],
default: function() {
return "";
}
},
multiple: {
type: Boolean,
default: !0
},
disabled: {
type: Boolean,
default: !1
},
showFileList: {
type: Boolean,
default: !0
},
showActionButtons: {
type: Boolean,
default: !0
},
actionsLayout: {
type: String,
default: function() {
return "end";
}
},
tabIndex: Number,
accept: String,
list: [String, Function, Object],
restrictions: {
type: Object,
default: function() {
return {
allowedExtensions: [],
maxFileSize: 0,
minFileSize: 0
};
}
},
validateFile: Function,
files: Array,
defaultFiles: Array
},
emits: {
add: null,
beforeremove: null,
beforeupload: null,
cancel: null,
statuschange: null,
progress: null,
remove: null
},
created() {
this._httpSubscriptions = {}, w(x), this.$props.defaultFiles && (this.currentFiles = this.$props.defaultFiles);
},
data() {
return {
currentFiles: []
};
},
computed: {
computedAsync() {
const {
autoUpload: s,
batch: e,
removeField: t,
removeHeaders: i,
removeMethod: n,
removeUrl: o,
responseType: a,
saveField: p,
saveHeaders: h,
saveMethod: c,
saveUrl: l,
withCredentials: v
} = this.$props;
return {
autoUpload: s,
batch: e,
removeField: t,
removeHeaders: i,
removeMethod: n,
removeUrl: o,
responseType: a,
saveField: p,
saveHeaders: h,
saveMethod: c,
saveUrl: l,
withCredentials: v
};
},
computedFiles() {
return (this.isControlled ? this.$props.files : this.currentFiles) || [];
},
isControlled() {
return !this.$props.defaultFiles;
},
isCustomSave() {
return this.$props.saveUrl && typeof this.$props.saveUrl == "function";
},
isCustomRemove() {
return this.$props.removeUrl && typeof this.$props.removeUrl == "function";
},
fileStateCopy() {
return r.copyState(this.computedFiles);
},
actionElement() {
if (this._uploadNavigation)
return this._uploadNavigation.actionElement;
}
},
mounted() {
this._uploadNavigation = this.uploadNavigationRef;
},
methods: {
focus() {
this._uploadNavigation && this._uploadNavigation.focus();
},
uploadFiles(s) {
const e = this.computedAsync;
r.setFilesStatus(s, u.Uploading), r.groupForEach(s, (t, i) => {
const n = d.cloneRequestHeaders(e.saveHeaders || {}), a = {
target: this,
files: t,
headers: n,
additionalData: {}
};
this.$emit("beforeupload", a);
const p = d.populateRequestOptions(a.headers, this.computedAsync), h = d.populateUploadFormData(t, e.saveField, a.additionalData);
if (this.isCustomSave)
this.$props.saveUrl(t, {
formData: h,
requestOptions: p
}, this.onUploadProgress).then((c) => this.onUploadSuccess(c.uid)).catch((c) => this.onUploadError(c.uid));
else {
const c = m.CancelToken.source();
this._httpSubscriptions[i] = c, m({
method: e.saveMethod,
url: e.saveUrl,
data: h,
cancelToken: c.token,
...p,
onUploadProgress: (l) => this.onUploadProgress(i, l)
}).then((l) => this.onUploadSuccess(i, l)).catch((l) => this.onUploadError(i, l));
}
});
},
removeFiles(s) {
const e = this.computedAsync;
r.groupForEach(s, (t, i) => {
const n = d.cloneRequestHeaders(e.removeHeaders || {}), a = {
target: this,
files: t,
headers: n,
additionalData: {}
};
this.$emit("beforeremove", a);
const p = t.map((l) => l.name), h = d.populateRequestOptions(a.headers, this.computedAsync), c = d.populateRemoveFormData(p, e.removeField, a.additionalData);
this.isCustomRemove ? this.$props.removeUrl(t, {
formData: c,
requestOptions: h
}).then((l) => this.onRemoveSuccess(l.uid)).catch((l) => this.onRemoveError(l.uid)) : m({
method: e.removeMethod,
url: e.removeUrl,
data: c,
...h
}).then((l) => this.onRemoveSuccess(i, l)).catch((l) => this.onRemoveError(i, l));
});
},
onUpload() {
const s = this.fileStateCopy, e = r.groupFilesByUid(s), t = r.filesForUpload(e);
this.uploadFiles(t);
const i = () => {
const n = {
target: this,
newState: s,
affectedFiles: r.flatFileGroup(t)
};
this.$emit("statuschange", n);
};
this.isControlled || (this.currentFiles = s), i();
},
onAdd(s) {
let e = F.getAllFileInfo(s), t;
if (e = F.assignGuidToFiles(e, this.computedAsync.batch), O.validateFiles(e, this.$props.restrictions, this.validateFile), this.$props.multiple ? t = this.fileStateCopy : t = [], r.addMany(e, t), this.computedAsync.autoUpload) {
const n = r.groupFilesByUid(t);
this.uploadFiles(r.filesForUpload(n));
}
const i = () => {
const n = {
target: this,
newState: t,
affectedFiles: e
};
this.$emit("add", n);
};
this.isControlled || (this.currentFiles = t), i();
},
onUploadProgress(s, e) {
const t = e.total ? Math.round(100 * e.loaded / e.total) : 0, i = this.fileStateCopy, n = i.filter((a) => a.uid === s);
if (!n.length)
return;
n.forEach((a) => {
a.progress = t;
});
const o = () => {
const a = {
target: this,
newState: i,
affectedFiles: n
};
this.$emit("progress", a);
};
this.isControlled || (this.currentFiles = i), o();
},
onUploadSuccess(s, e) {
const t = this.fileStateCopy, i = t.filter((o) => o.uid === s);
i.forEach((o) => {
o.status = u.Uploaded;
}), delete this._httpSubscriptions[s];
const n = () => {
const o = {
target: this,
newState: t,
affectedFiles: i,
response: e ? d.convertAxiosResponse(e) : void 0
};
this.$emit("statuschange", o);
};
this.isControlled || (this.currentFiles = t), n();
},
onUploadError(s, e) {
const t = this.fileStateCopy, i = t.filter((o) => o.uid === s);
if (i.forEach((o) => {
o.status = u.UploadFailed;
}), delete this._httpSubscriptions[s], !i.length)
return;
const n = () => {
const o = {
target: this,
newState: t,
affectedFiles: i,
response: e ? d.convertAxiosResponse(e) : void 0
};
this.$emit("statuschange", o);
};
this.isControlled || (this.currentFiles = t), n();
},
onRemove(s) {
const e = this.fileStateCopy, t = e.filter((o) => o.uid === s), i = e.filter((o) => o.uid !== s), n = [u.Uploaded, u.Initial, u.RemoveFailed];
if (t[0] && n.indexOf(t[0].status) > -1) {
const o = {
[s]: t
};
r.setFilesStatus(o, u.Removing), this.removeFiles(o);
const a = () => {
const p = {
target: this,
newState: e,
affectedFiles: t
};
this.$emit("statuschange", p);
};
this.isControlled || (this.currentFiles = e), a();
} else {
const o = () => {
const a = {
target: this,
newState: i,
affectedFiles: t
};
this.$emit("remove", a);
};
this.isControlled || (this.currentFiles = i), o();
}
},
onRemoveSuccess(s, e) {
const t = this.fileStateCopy, i = t.filter((a) => a.uid === s), n = t.filter((a) => a.uid !== s), o = () => {
const a = {
target: this,
newState: n,
affectedFiles: i,
response: e ? d.convertAxiosResponse(e) : void 0
};
this.$emit("remove", a);
};
this.isControlled || (this.currentFiles = n), o();
},
onRemoveError(s, e) {
const t = this.fileStateCopy, i = t.filter((o) => o.uid === s);
i.forEach((o) => {
o.status = u.RemoveFailed;
});
const n = () => {
const o = {
target: this,
newState: t,
affectedFiles: i,
response: e ? d.convertAxiosResponse(e) : void 0
};
this.$emit("statuschange", o);
};
this.isControlled || (this.currentFiles = t), n();
},
onRetry(s) {
const e = this.fileStateCopy, t = r.groupFilesByUid(e.filter((n) => n.uid === s));
r.setFilesStatus(t, u.Uploading), this.uploadFiles(t);
const i = () => {
const n = {
target: this,
newState: e,
affectedFiles: r.flatFileGroup(t)
};
this.$emit("statuschange", n);
};
this.isControlled || (this.currentFiles = e), i();
},
onCancel(s) {
const e = this.fileStateCopy, t = e.filter((a) => a.uid !== s), i = e.filter((a) => a.uid === s);
this._httpSubscriptions[s] && (this._httpSubscriptions[s].cancel(), delete this._httpSubscriptions[s]);
const n = {
target: this,
uid: s
};
this.$emit("cancel", n);
const o = () => {
const a = {
target: this,
newState: t,
affectedFiles: i
};
this.$emit("remove", a);
};
this.isControlled || (this.currentFiles = e), o();
},
onClear() {
if (!this.computedFiles.length)
return;
Object.keys(this._httpSubscriptions).forEach((e) => {
this._httpSubscriptions[e].cancel();
}), this._httpSubscriptions = {};
const s = () => {
const e = {
target: this,
newState: [],
affectedFiles: this.fileStateCopy
};
this.$emit("remove", e);
};
this.isControlled || (this.currentFiles = []), s();
}
},
render() {
const {
showFileList: s,
autoUpload: e,
showActionButtons: t,
actionsLayout: i,
tabIndex: n,
disabled: o,
batch: a,
withCredentials: p,
saveField: h,
saveHeaders: c,
saveMethod: l,
saveUrl: v,
responseType: T,
removeField: M,
removeHeaders: H,
removeMethod: k,
removeUrl: P,
multiple: g,
accept: S,
restrictions: y,
files: U,
defaultFiles: C
} = this.$props, R = A.call(this, this.$props.list, _.call(this)), f = r.groupFilesByUid(this.computedFiles), b = r.filesForUpload(f);
return D(N, {
groupedFiles: f,
className: this.$props.className,
showFileList: s && !!Object.keys(f).length,
showActionButtons: t && !e && !!Object.keys(b).length,
actionsLayout: i,
disabled: o,
onAdd: this.onAdd,
onRemove: this.onRemove,
onClear: this.onClear,
onUpload: this.onUpload,
onRetry: this.onRetry,
onCancel: this.onCancel,
tabIndex: B(n, o),
ref: ($) => {
this.uploadNavigationRef = $;
},
multiple: g,
accept: S,
list: R,
restrictions: y,
files: U,
defaultFiles: C,
async: this.computedAsync
}, null);
}
});
export {
Q as Upload
};