Skip to content

Commit

Permalink
Merge pull request #5491 from getkirby/v4/enhancement/js-upload-queue
Browse files Browse the repository at this point in the history
`$panel.upload()`: use async upload queue
  • Loading branch information
bastianallgeier authored Aug 30, 2023
2 parents a28c3d5 + 64bf10d commit 4c2c399
Showing 1 changed file with 67 additions and 41 deletions.
108 changes: 67 additions & 41 deletions panel/src/panel/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,63 +260,89 @@ export default (panel) => {
return this.done();
}

// upload each file individually and keep track of the progress
// gather upload queue for all files
const queue = [];

for (const file of this.files) {
// don't upload completed files again
// skip file if alreay completed
if (file.completed === true) {
continue;
}

// reset progress and error before
// the upload starts
file.error = null;
file.progress = 0;

// ensure that all files have a unique name
const duplicates = this.files.filter(
(f) => f.name === file.name && f.extension === file.extension
);

if (duplicates.length > 1) {
if (
this.files.filter(
(f) => f.name === file.name && f.extension === file.extension
).length > 1
) {
file.error = panel.t("error.file.name.unique");
continue;
}

upload(file.src, {
attributes: this.attributes,
headers: {
"x-csrf": panel.system.csrf
},
filename: file.name + "." + file.extension,
url: this.url,
error: (xhr, src, response) => {
panel.error(response, false);

// store the error message to show it in
// the dialog for example
file.error = response.message;

// reset the progress bar on error
file.progress = 0;
},
progress: (xhr, src, progress) => {
file.progress = progress;
},
success: (xhr, src, response) => {
file.completed = true;
file.model = response.data;

if (this.files.length === this.completed.length) {
this.done();
}
}
});
// reset progress and error before
// the upload starts
file.error = null;
file.progress = 0;

// add file to upload queue
queue.push(file);

// if there is sort data, increment in the loop for next file
if (this.attributes?.sort !== undefined) {
this.attributes.sort++;
}
}

// async uploader function:
// uploads the next file in the queue
// and triggers itself again after completion
const uploader = async () => {
if (queue.length === 0) {
return;
}

try {
const file = queue.shift();
await upload(file.src, {
attributes: this.attributes,
headers: {
"x-csrf": panel.system.csrf
},
filename: file.name + "." + file.extension,
url: this.url,
error: (xhr, src, response) => {
panel.error(response, false);

// store the error message to show it in
// the dialog for example
file.error = response.message;

// reset the progress bar on error
file.progress = 0;
},
progress: (xhr, src, progress) => {
file.progress = progress;
},
success: (xhr, src, response) => {
file.completed = true;
file.model = response.data;

if (this.files.length === this.completed.length) {
this.done();
}
}
});
} finally {
uploader();
}
};

// initialize the uploader for the first up to 20 files,
// uploader function will then trigger itself after completion
// until the full queue has been processed
for (let i = 0; i < Math.min(queue.length, 20); i++) {
uploader();
}
}
};
};

0 comments on commit 4c2c399

Please sign in to comment.