There will be no progress bar if there is only a single chunk to be uploaded.
element.append(errorElement);
}
+function trackUploadProgress(element: HTMLElement, file: WoltlabCoreFileElement): void {
+ const progress = document.createElement("progress");
+ progress.classList.add("attachment__item__progress__bar");
+ progress.max = 100;
+ const readout = document.createElement("span");
+ readout.classList.add("attachment__item__progress__readout");
+
+ file.addEventListener("uploadProgress", (event: CustomEvent<number>) => {
+ progress.value = event.detail;
+ readout.textContent = `${event.detail}%`;
+
+ if (progress.parentNode === null) {
+ element.classList.add("attachment__item--uploading");
+
+ const wrapper = document.createElement("div");
+ wrapper.classList.add("attachment__item__progress");
+ wrapper.append(progress, readout);
+
+ element.append(wrapper);
+ }
+ });
+}
+
+function removeUploadProgress(element: HTMLElement): void {
+ if (!element.classList.contains("attachment__item--uploading")) {
+ return;
+ }
+
+ element.classList.remove("attachment__item--uploading");
+ element.querySelector(".attachment__item__progress")?.remove();
+}
+
export function createAttachmentFromFile(file: WoltlabCoreFileElement, editor: HTMLElement) {
const element = document.createElement("li");
element.classList.add("attachment__item");
})
.catch((reason) => {
fileInitializationFailed(element, file, reason);
+ })
+ .finally(() => {
+ removeUploadProgress(element);
});
+ trackUploadProgress(element, file);
+
return element;
}
const chunkSize = Math.ceil(file.size / numberOfChunks);
- // TODO: Can we somehow report any meaningful upload progress?
+ notifyChunkProgress(fileElement, 0, numberOfChunks);
for (let i = 0; i < numberOfChunks; i++) {
const start = i * chunkSize;
throw response.error;
}
+ notifyChunkProgress(fileElement, i + 1, numberOfChunks);
+
await chunkUploadCompleted(fileElement, response.value);
if (response.value.completed) {
}
}
+function notifyChunkProgress(element: WoltlabCoreFileElement, currentChunk: number, numberOfChunks: number): void {
+ // Suppress the progress bar for uploads that are processed in a single
+ // request, because we cannot track the upload progress within a chunk.
+ if (numberOfChunks === 1) {
+ return;
+ }
+
+ const event = new CustomEvent<number>("uploadProgress", {
+ detail: Math.floor((currentChunk / numberOfChunks) * 100),
+ });
+ element.dispatchEvent(event);
+}
+
async function chunkUploadCompleted(fileElement: WoltlabCoreFileElement, result: UploadChunkResponse): Promise<void> {
if (!result.completed) {
return;
errorElement.textContent = errorMessage;
element.append(errorElement);
}
+ function trackUploadProgress(element, file) {
+ const progress = document.createElement("progress");
+ progress.classList.add("attachment__item__progress__bar");
+ progress.max = 100;
+ const readout = document.createElement("span");
+ readout.classList.add("attachment__item__progress__readout");
+ file.addEventListener("uploadProgress", (event) => {
+ progress.value = event.detail;
+ readout.textContent = `${event.detail}%`;
+ if (progress.parentNode === null) {
+ element.classList.add("attachment__item--uploading");
+ const wrapper = document.createElement("div");
+ wrapper.classList.add("attachment__item__progress");
+ wrapper.append(progress, readout);
+ element.append(wrapper);
+ }
+ });
+ }
+ function removeUploadProgress(element) {
+ if (!element.classList.contains("attachment__item--uploading")) {
+ return;
+ }
+ element.classList.remove("attachment__item--uploading");
+ element.querySelector(".attachment__item__progress")?.remove();
+ }
function createAttachmentFromFile(file, editor) {
const element = document.createElement("li");
element.classList.add("attachment__item");
})
.catch((reason) => {
fileInitializationFailed(element, file, reason);
+ })
+ .finally(() => {
+ removeUploadProgress(element);
});
+ trackUploadProgress(element, file);
return element;
}
exports.createAttachmentFromFile = createAttachmentFromFile;
}
const { identifier, numberOfChunks } = response.value;
const chunkSize = Math.ceil(file.size / numberOfChunks);
- // TODO: Can we somehow report any meaningful upload progress?
+ notifyChunkProgress(fileElement, 0, numberOfChunks);
for (let i = 0; i < numberOfChunks; i++) {
const start = i * chunkSize;
const end = start + chunkSize;
fileElement.uploadFailed(response.error);
throw response.error;
}
+ notifyChunkProgress(fileElement, i + 1, numberOfChunks);
await chunkUploadCompleted(fileElement, response.value);
if (response.value.completed) {
return response.value;
}
}
}
+ function notifyChunkProgress(element, currentChunk, numberOfChunks) {
+ // Suppress the progress bar for uploads that are processed in a single
+ // request, because we cannot track the upload progress within a chunk.
+ if (numberOfChunks === 1) {
+ return;
+ }
+ const event = new CustomEvent("uploadProgress", {
+ detail: Math.floor((currentChunk / numberOfChunks) * 100),
+ });
+ element.dispatchEvent(event);
+ }
async function chunkUploadCompleted(fileElement, result) {
if (!result.completed) {
return;
justify-content: end;
}
+.attachment__item__progress {
+ align-items: center;
+ column-gap: 10px;
+ display: flex;
+ grid-area: buttons;
+}
+
+.attachment__item__progress__readout {
+ @include wcfFontSmall;
+}
+
.formAttachmentContent {
.formAttachmentList {
display: flex;