diff --git a/app/Conductors/Conductor.php b/app/Conductors/Conductor.php
index 7750dba..a79e907 100644
--- a/app/Conductors/Conductor.php
+++ b/app/Conductors/Conductor.php
@@ -593,7 +593,7 @@ class Conductor
$requestIncludes = [];
$modelFields = $conductor->fields(new $conductor->class());
-
+
// Limit fields
$limitFields = $modelFields;
if ($fields instanceof Request) {
diff --git a/app/Conductors/MediaJobConductor.php b/app/Conductors/MediaJobConductor.php
index 9c50c76..a55ef30 100644
--- a/app/Conductors/MediaJobConductor.php
+++ b/app/Conductors/MediaJobConductor.php
@@ -2,6 +2,7 @@
namespace App\Conductors;
+use App\Models\MediaJob;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
index 3499f12..692cc89 100644
--- a/app/Providers/RouteServiceProvider.php
+++ b/app/Providers/RouteServiceProvider.php
@@ -42,7 +42,7 @@ class RouteServiceProvider extends ServiceProvider
if ($rateLimitEnabled === true) {
RateLimiter::for('api', function (Request $request) {
- return Limit::perMinute(180)->by($request->user()?->id ?: $request->ip());
+ return Limit::perMinute(800)->by($request->user()?->id ?: $request->ip());
});
} else {
RateLimiter::for('api', function () {
diff --git a/database/migrations/2023_09_10_085850_add_progress_max_to_media_jobs_table.php b/database/migrations/2023_09_10_085850_add_progress_max_to_media_jobs_table.php
new file mode 100644
index 0000000..74aec2b
--- /dev/null
+++ b/database/migrations/2023_09_10_085850_add_progress_max_to_media_jobs_table.php
@@ -0,0 +1,28 @@
+integer('progress_max')->default(0);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('media_jobs', function (Blueprint $table) {
+ $table->dropColumn('progress_max');
+ });
+ }
+};
diff --git a/resources/js/components/dialogs/SMDialogMedia.vue b/resources/js/components/dialogs/SMDialogMedia.vue
index ceda1c5..939e9c9 100644
--- a/resources/js/components/dialogs/SMDialogMedia.vue
+++ b/resources/js/components/dialogs/SMDialogMedia.vue
@@ -151,8 +151,8 @@
{{
+ class="bg-white bg-op-90 w-full h-full">
+ {{
getMediaStatusText(item)
}}
@@ -197,6 +197,27 @@
width: `${computedUploadProgress}%`,
}">
+
+ {{ computedUploadMediaStatus }}
+
+
+
+
+ {{ computedProcessingMediaTitle }}
+
+
+
+ {{ computedProcessingMediaStatus }}
+
{
const handleFilesUpload = (files: FileList) => {
const fileList = [];
let count = 0;
+ let maxCount = 15;
let warnedUser = false;
fileList.push(...Array.from(files));
@@ -826,7 +848,7 @@ const handleFilesUpload = (files: FileList) => {
if (mimeMatches(props.mime, file.type) == true) {
count = getUploadingMediaItems().length;
- if (count < 5) {
+ if (count <= maxCount) {
const uploadId = generateRandomId("upload_", 8, (s) => {
return getMediaItemById(s) != null;
});
@@ -834,18 +856,19 @@ const handleFilesUpload = (files: FileList) => {
mediaItems.value.unshift(
createMediaItem({
id: uploadId,
+ name: convertFileNameToTitle(file.name),
}),
);
window.setTimeout(() => {
uploadFileById(uploadId, file);
}, 50);
- } else if (count >= 5 && warnedUser == false) {
+ } else if (count > maxCount && warnedUser == false) {
warnedUser = true;
useToastStore().addToast({
title: "Maximum Files",
type: "warning",
- content: "You cannot upload more than 5 files at a time",
+ content: `You cannot upload more than ${maxCount} files at a time`,
});
return;
@@ -861,18 +884,33 @@ const handleFilesUpload = (files: FileList) => {
};
const getUploadingMediaItems = (): Media[] => {
- return mediaItems.value.filter((item) => item.id.startsWith("upload_"));
+ return mediaItems.value.filter((item) => {
+ return (
+ item.id.startsWith("upload_") &&
+ item.jobs.length > 0 &&
+ item.jobs[0].status === "uploading"
+ );
+ });
};
const computedUploadMediaTitle = computed(() => {
const items = getUploadingMediaItems();
- let prefix = "Uploading";
+ return `Uploading ${items.length} File${items.length == 1 ? "" : "s"}`;
+});
- if (computedUploadProgress.value >= 100) {
- prefix = "Processing";
- }
+const computedUploadMediaStatus = computed(() => {
+ const items = getUploadingMediaItems();
+ let bytes = 0;
+ let maxBytes = 0;
- return `${prefix} ${items.length} File${items.length == 1 ? "" : "s"}`;
+ items.forEach((item) => {
+ if (item.jobs.length > 0) {
+ bytes += item.jobs[0].progress;
+ maxBytes += item.jobs[0].progress_max;
+ }
+ });
+
+ return `${bytesReadable(bytes)} of ${bytesReadable(maxBytes)}`;
});
const computedUploadProgress = computed(() => {
@@ -883,7 +921,10 @@ const computedUploadProgress = computed(() => {
const totalProgress = items.reduce((accumulator, item) => {
if (item.jobs.length > 0) {
- accumulator += item.jobs[0].progress || 100;
+ accumulator +=
+ Math.floor(
+ (item.jobs[0].progress / item.jobs[0].progress_max) * 100,
+ ) || 100;
}
return accumulator;
}, 0);
@@ -891,6 +932,65 @@ const computedUploadProgress = computed(() => {
return Math.floor(totalProgress / items.length);
});
+const getProcessingMediaItems = (): Media[] => {
+ return mediaItems.value.filter((item) => {
+ return (
+ item.id.startsWith("upload_") &&
+ item.jobs.length > 0 &&
+ item.jobs[0].status !== "uploading"
+ );
+ });
+};
+
+const computedProcessingMediaTitle = computed(() => {
+ const items = getProcessingMediaItems();
+ return `Processing ${items.length} File${items.length == 1 ? "" : "s"}`;
+});
+
+const computedProcessingProgress = computed(() => {
+ const items = getProcessingMediaItems();
+ if (items.length === 0) {
+ return 100;
+ }
+
+ const totalProgress = items.reduce((accumulator, item) => {
+ if (item.jobs.length > 0) {
+ if (item.jobs[0].progress_max != 0) {
+ accumulator +=
+ Math.floor(
+ (item.jobs[0].progress / item.jobs[0].progress_max) *
+ 100,
+ ) || 100;
+ }
+ }
+ return accumulator;
+ }, 0);
+
+ return Math.floor(totalProgress / items.length);
+});
+
+const computedProcessingMediaStatus = computed(() => {
+ const items = getProcessingMediaItems();
+ let status = "";
+
+ items.every((item) => {
+ let itemStatus = getMediaStatusText(item);
+ if (status == "" || (itemStatus != "" && itemStatus != "Queued")) {
+ const endLoop = !(status == "");
+ status = `${item.name}: ${itemStatus}`;
+
+ if (endLoop == true) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ return status;
+ // return `${bytesReadable(bytes)} of ${bytesReadable(maxBytes)}`;
+});
+
/**
* Upload a File to the server.
* @param {string} uploadId The ID of the new media item.
@@ -909,14 +1009,14 @@ const uploadFileById = (uploadId: string, file: File): void => {
headers: {
"Content-Type": "multipart/form-data",
},
+ chunk: "file",
progress: (progressEvent) => {
const mediaItem = getMediaItemById(uploadId);
if (mediaItem != null) {
mediaItem.jobs[0] = createMediaJobItem({
status: "uploading",
- progress: Math.floor(
- (progressEvent.loaded / progressEvent.total) * 100,
- ),
+ progress: progressEvent.loaded,
+ progress_max: progressEvent.total,
});
}
},
@@ -934,10 +1034,20 @@ const uploadFileById = (uploadId: string, file: File): void => {
}
})
.catch((error) => {
- // let errorString = "A server error occurred";
- // if (error.status == 413) {
- // errorString = `The file is larger than ${max_upload_size.value}`;
- // }
+ if (error.status == 413) {
+ useToastStore().addToast({
+ title: "File too large",
+ type: "danger",
+ content: `Cannot upload the file ${file.name} as it larger than ${max_upload_size.value}.`,
+ });
+ } else {
+ useToastStore().addToast({
+ title: "File upload error",
+ type: "danger",
+ content: `Cannot upload the file ${file.name} as a server error occurred.`,
+ });
+ }
+
console.log(error);
});
};
@@ -949,7 +1059,7 @@ const uploadFileById = (uploadId: string, file: File): void => {
*/
const updateMediaItem = (id: string): void => {
let media = getMediaItemById(id);
- let timeout = 50;
+ let timeout = 200;
if (media != null && media.jobs.length > 0) {
if (id.startsWith("upload_")) {
@@ -964,10 +1074,13 @@ const updateMediaItem = (id: string): void => {
if (data.media_job.media_id != null) {
media.id = data.media_job.media_id;
}
+ if (data.media_job.id == media.jobs[0].id) {
+ media.jobs[0] = data.media_job;
+ }
})
.catch((error) => {
if (error.status == 429) {
- timeout = 500;
+ timeout = 1000;
}
/* error */
@@ -1398,7 +1511,7 @@ const postUpdate = (data: MediaUpdate): void => {
description: data.description,
},
}).catch((error) => {
- console.log(error);
+ console.log("postupdate: " + error);
});
};
diff --git a/resources/js/helpers/api.ts b/resources/js/helpers/api.ts
index b1c0b91..e2f6ffa 100644
--- a/resources/js/helpers/api.ts
+++ b/resources/js/helpers/api.ts
@@ -134,8 +134,6 @@ export const api = {
for (const header in options.headers) {
xhr.setRequestHeader(header, options.headers[header]);
}
- xhr.send(options.body as XMLHttpRequestBodyInit);
-
xhr.onload = function () {
const result = {
status: xhr.status,
@@ -188,6 +186,12 @@ export const api = {
return;
}
};
+
+ try {
+ xhr.send(options.body as XMLHttpRequestBodyInit);
+ } catch (e) {
+ console.log(e);
+ }
} else {
const fetchOptions: RequestInit = {
method: options.method.toUpperCase() || "GET",
@@ -379,7 +383,7 @@ export const api = {
const file = apiOptions.body.get(apiOptions.chunk);
if (file instanceof File) {
- const chunkSize = 50 * 1024 * 1024;
+ const chunkSize = 2 * 1024 * 1024;
let chunk = 0;
let chunkCount = 1;
let job_id = -1;
diff --git a/resources/js/helpers/api.types.ts b/resources/js/helpers/api.types.ts
index 7237ce0..f341e92 100644
--- a/resources/js/helpers/api.types.ts
+++ b/resources/js/helpers/api.types.ts
@@ -95,6 +95,7 @@ export interface MediaJob {
status: string;
status_text: string;
progress: number;
+ progress_max: number;
}
export interface MediaJobResponse {
diff --git a/resources/js/helpers/media.ts b/resources/js/helpers/media.ts
index 0dd192b..6dd99b1 100644
--- a/resources/js/helpers/media.ts
+++ b/resources/js/helpers/media.ts
@@ -193,15 +193,15 @@ export const getMediaStatusText = (media: Media): string => {
) {
if (media.jobs[0].status_text != "") {
status = toTitleCase(media.jobs[0].status_text);
- if (
- media.jobs[0].status == "processing" &&
- media.jobs[0].progress > -1
- ) {
- status += ` ${media.jobs[0].progress}%`;
- }
} else {
status = toTitleCase(media.jobs[0].status);
}
+
+ if (media.jobs[0].progress_max != 0) {
+ status += ` ${Math.floor(
+ (media.jobs[0].progress / media.jobs[0].progress_max) * 100,
+ )}%`;
+ }
}
}
@@ -234,6 +234,7 @@ export interface MediaJobParams {
status?: string;
status_text?: string;
progress?: number;
+ progress_max?: number;
}
export const createMediaItem = (params?: MediaParams): Media => {
@@ -267,6 +268,7 @@ export const createMediaJobItem = (params?: MediaJobParams): MediaJob => {
status: params.status || "",
status_text: params.status_text || "",
progress: params.progress || 0,
+ progress_max: params.progress_max || 0,
};
return job;