From 2cc8ea5dae64ab36953e89d32deeb4887d8a72be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8F=A4=E5=A4=A7=E7=BE=8A?=
Date: Tue, 7 May 2024 22:33:45 +0800
Subject: [PATCH] feat: make uploadsLimit into user setting
---
frontend/src/components/prompts/Upload.vue | 13 ++++++++++---
frontend/src/i18n/en.json | 3 ++-
frontend/src/i18n/zh-cn.json | 3 ++-
frontend/src/i18n/zh-tw.json | 3 ++-
frontend/src/stores/upload.ts | 16 +++++++---------
frontend/src/types/settings.d.ts | 1 +
frontend/src/types/user.d.ts | 2 ++
frontend/src/utils/upload.ts | 5 +++--
frontend/src/views/files/FileListing.vue | 22 ++++++++++++++++------
frontend/src/views/settings/Profile.vue | 11 +++++++++++
http/auth.go | 2 ++
users/users.go | 17 +++++++++++++++--
12 files changed, 73 insertions(+), 25 deletions(-)
diff --git a/frontend/src/components/prompts/Upload.vue b/frontend/src/components/prompts/Upload.vue
index bb8ec40e..bb4e69cc 100644
--- a/frontend/src/components/prompts/Upload.vue
+++ b/frontend/src/components/prompts/Upload.vue
@@ -37,11 +37,13 @@ import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
+import { useAuthStore } from "@/stores/auth";
import * as upload from "@/utils/upload";
const { t } = useI18n();
const route = useRoute();
+const authStore = useAuthStore();
const fileStore = useFileStore();
const layoutStore = useLayoutStore();
@@ -54,6 +56,11 @@ const uploadInput = (event: Event) => {
if (files === null) return;
let folder_upload = !!files[0].webkitRelativePath;
+ let uploadsLimit = 1
+ if (authStore.user!=null){
+ uploadsLimit = authStore.user.uploadsLimit
+ }
+
const uploadFiles: UploadList = [];
for (let i = 0; i < files.length; i++) {
@@ -77,19 +84,19 @@ const uploadInput = (event: Event) => {
action: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, false);
+ upload.handleFiles(uploadFiles, path, uploadsLimit);
},
confirm: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, true);
+ upload.handleFiles(uploadFiles, path, uploadsLimit, true);
},
});
return;
}
- upload.handleFiles(uploadFiles, path);
+ upload.handleFiles(uploadFiles, path, uploadsLimit);
};
const openUpload = (isFolder: boolean) => {
diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json
index 00d43b9d..b148367a 100644
--- a/frontend/src/i18n/en.json
+++ b/frontend/src/i18n/en.json
@@ -236,7 +236,8 @@
"userManagement": "User Management",
"userUpdated": "User updated!",
"username": "Username",
- "users": "Users"
+ "users": "Users",
+ "uploadsLimit":"Limit of concurrent uploads"
},
"sidebar": {
"help": "Help",
diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json
index 1aea4134..06f97ef0 100644
--- a/frontend/src/i18n/zh-cn.json
+++ b/frontend/src/i18n/zh-cn.json
@@ -236,7 +236,8 @@
"userManagement": "用户管理",
"userUpdated": "用户已更新!",
"username": "用户名",
- "users": "用户"
+ "users": "用户",
+ "uploadsLimit":"上传并行任务数限制"
},
"sidebar": {
"help": "帮助",
diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json
index fdb2447c..f9f4c840 100644
--- a/frontend/src/i18n/zh-tw.json
+++ b/frontend/src/i18n/zh-tw.json
@@ -236,7 +236,8 @@
"userManagement": "使用者管理",
"userUpdated": "使用者已更新!",
"username": "使用者名稱",
- "users": "使用者"
+ "users": "使用者",
+ "uploadsLimit":"上傳並行任務數限制"
},
"sidebar": {
"help": "幫助",
diff --git a/frontend/src/stores/upload.ts b/frontend/src/stores/upload.ts
index 4e814454..88a00520 100644
--- a/frontend/src/stores/upload.ts
+++ b/frontend/src/stores/upload.ts
@@ -4,8 +4,6 @@ import { files as api } from "@/api";
import throttle from "lodash/throttle";
import buttons from "@/utils/buttons";
-// TODO: make this into a user setting
-const UPLOADS_LIMIT = 5;
const beforeUnload = (event: Event) => {
event.preventDefault();
@@ -145,7 +143,7 @@ export const useUploadStore = defineStore("upload", {
removeJob(id: number) {
delete this.uploads[id];
},
- upload(item: UploadItem) {
+ upload(item: UploadItem,uploadsLimit:number) {
const uploadsCount = Object.keys(this.uploads).length;
const isQueueEmpty = this.queue.length == 0;
@@ -157,17 +155,17 @@ export const useUploadStore = defineStore("upload", {
}
this.addJob(item);
- this.processUploads();
+ this.processUploads(uploadsLimit);
},
- finishUpload(item: UploadItem) {
+ finishUpload(item: UploadItem,uploadsLimit:number) {
this.setProgress({ id: item.id, loaded: item.file.size > 0 });
this.removeJob(item.id);
- this.processUploads();
+ this.processUploads(uploadsLimit);
},
- async processUploads() {
+ async processUploads(uploadsLimit:number) {
const uploadsCount = Object.keys(this.uploads).length;
- const isBellowLimit = uploadsCount < UPLOADS_LIMIT;
+ const isBellowLimit = uploadsCount < uploadsLimit;
const isQueueEmpty = this.queue.length == 0;
const isUploadsEmpty = uploadsCount == 0;
@@ -204,7 +202,7 @@ export const useUploadStore = defineStore("upload", {
.catch(this.setError);
}
- this.finishUpload(item);
+ this.finishUpload(item,uploadsLimit);
}
},
setUploadSpeed(value: number) {
diff --git a/frontend/src/types/settings.d.ts b/frontend/src/types/settings.d.ts
index a2c19f76..f7d2c208 100644
--- a/frontend/src/types/settings.d.ts
+++ b/frontend/src/types/settings.d.ts
@@ -20,6 +20,7 @@ interface SettingsDefaults {
commands: any[];
hideDotfiles: boolean;
dateFormat: boolean;
+ uploadsLimit:number;
}
interface SettingsBranding {
diff --git a/frontend/src/types/user.d.ts b/frontend/src/types/user.d.ts
index b81806fc..a44aaf84 100644
--- a/frontend/src/types/user.d.ts
+++ b/frontend/src/types/user.d.ts
@@ -13,6 +13,7 @@ interface IUser {
dateFormat: boolean;
viewMode: ViewModeType;
sorting?: Sorting;
+ uploadsLimit:number;
}
type ViewModeType = "list" | "mosaic" | "mosaic gallery";
@@ -30,6 +31,7 @@ interface IUserForm {
hideDotfiles?: boolean;
singleClick?: boolean;
dateFormat?: boolean;
+ uploadsLimit:number;
}
interface Permissions {
diff --git a/frontend/src/utils/upload.ts b/frontend/src/utils/upload.ts
index e7ce8bec..0358cf34 100644
--- a/frontend/src/utils/upload.ts
+++ b/frontend/src/utils/upload.ts
@@ -123,7 +123,8 @@ function detectType(mimetype: string): ResourceType {
export function handleFiles(
files: UploadList,
base: string,
- overwrite = false
+ uploadsLimit:number,
+ overwrite = false,
) {
const uploadStore = useUploadStore();
@@ -149,6 +150,6 @@ export function handleFiles(
...(!file.isDir && { type: detectType((file.file as File).type) }),
};
- uploadStore.upload(item);
+ uploadStore.upload(item,uploadsLimit);
}
}
diff --git a/frontend/src/views/files/FileListing.vue b/frontend/src/views/files/FileListing.vue
index a26ac67e..9ad61294 100644
--- a/frontend/src/views/files/FileListing.vue
+++ b/frontend/src/views/files/FileListing.vue
@@ -731,25 +731,30 @@ const drop = async (event: DragEvent) => {
let conflict = upload.checkConflict(files, items);
+ let uploadsLimit = 1
+ if (authStore.user!=null){
+ uploadsLimit = authStore.user.uploadsLimit
+ }
+
if (conflict) {
layoutStore.showHover({
prompt: "replace",
action: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(files, path, false);
+ upload.handleFiles(files, path,uploadsLimit);
},
confirm: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(files, path, true);
+ upload.handleFiles(files, path,uploadsLimit, true,);
},
});
return;
}
- upload.handleFiles(files, path);
+ upload.handleFiles(files, path,uploadsLimit);
};
const uploadInput = (event: Event) => {
@@ -776,25 +781,30 @@ const uploadInput = (event: Event) => {
let path = route.path.endsWith("/") ? route.path : route.path + "/";
let conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
+ let uploadsLimit = 1
+ if (authStore.user!=null){
+ uploadsLimit = authStore.user.uploadsLimit
+ }
+
if (conflict) {
layoutStore.showHover({
prompt: "replace",
action: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, false);
+ upload.handleFiles(uploadFiles, path, uploadsLimit);
},
confirm: (event: Event) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, true);
+ upload.handleFiles(uploadFiles, path, uploadsLimit,true);
},
});
return;
}
- upload.handleFiles(uploadFiles, path);
+ upload.handleFiles(uploadFiles, path,uploadsLimit);
};
const resetOpacity = () => {
diff --git a/frontend/src/views/settings/Profile.vue b/frontend/src/views/settings/Profile.vue
index c677092f..6f1cac72 100644
--- a/frontend/src/views/settings/Profile.vue
+++ b/frontend/src/views/settings/Profile.vue
@@ -19,11 +19,18 @@
{{ t("settings.setDateFormat") }}
+ {{ t("settings.uploadsLimit") }}
+
{{ t("settings.language") }}
+
@@ -98,6 +105,7 @@ const hideDotfiles = ref(false);
const singleClick = ref(false);
const dateFormat = ref(false);
const locale = ref("");
+const uploadsLimit = ref(0);
const passwordClass = computed(() => {
const baseClass = "input input--block";
@@ -120,6 +128,7 @@ onMounted(() => {
hideDotfiles.value = authStore.user.hideDotfiles;
singleClick.value = authStore.user.singleClick;
dateFormat.value = authStore.user.dateFormat;
+ uploadsLimit.value = authStore.user.uploadsLimit;
layoutStore.loading = false;
return true;
});
@@ -163,6 +172,7 @@ const updateSettings = async (event: Event) => {
hideDotfiles: hideDotfiles.value,
singleClick: singleClick.value,
dateFormat: dateFormat.value,
+ uploadsLimit:uploadsLimit.value,
};
await api.update(data, [
@@ -170,6 +180,7 @@ const updateSettings = async (event: Event) => {
"hideDotfiles",
"singleClick",
"dateFormat",
+ "uploadsLimit",
]);
authStore.updateUser(data);
$showSuccess(t("settings.settingsUpdated"));
diff --git a/http/auth.go b/http/auth.go
index 23dc7b77..26b8a734 100644
--- a/http/auth.go
+++ b/http/auth.go
@@ -30,6 +30,7 @@ type userInfo struct {
LockPassword bool `json:"lockPassword"`
HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"`
+ UploadsLimit uint `json:"uploadsLimit"`
}
type authToken struct {
@@ -195,6 +196,7 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use
Commands: user.Commands,
HideDotfiles: user.HideDotfiles,
DateFormat: user.DateFormat,
+ UploadsLimit: user.GetUploadsLimit(),
},
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()),
diff --git a/users/users.go b/users/users.go
index ec613856..20c41693 100644
--- a/users/users.go
+++ b/users/users.go
@@ -15,8 +15,10 @@ import (
type ViewMode string
const (
- ListViewMode ViewMode = "list"
- MosaicViewMode ViewMode = "mosaic"
+ ListViewMode ViewMode = "list"
+ MosaicViewMode ViewMode = "mosaic"
+ DefaultUploadsLimit = uint(5)
+ MaxUploadsLimit = uint(10)
)
// User describes a user.
@@ -36,6 +38,17 @@ type User struct {
Rules []rules.Rule `json:"rules"`
HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"`
+ UploadsLimit uint `json:"uploadsLimit"`
+}
+
+func (u *User) GetUploadsLimit() uint {
+ if u.UploadsLimit == 0 {
+ return DefaultUploadsLimit
+ }
+ if u.UploadsLimit > MaxUploadsLimit {
+ return MaxUploadsLimit
+ }
+ return u.UploadsLimit
}
// GetRules implements rules.Provider.