From 756c4518c710cb57cffc08f9fa2a6f0338acb50d Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Sun, 18 May 2025 11:30:50 +0800 Subject: [PATCH] feat(workflow): import files from external storage --- public/locales/en-US/application.json | 7 ++- public/locales/en-US/dashboard.json | 19 +++++-- public/locales/ja-JP/application.json | 7 ++- public/locales/ja-JP/dashboard.json | 18 +++++-- public/locales/zh-CN/application.json | 7 ++- public/locales/zh-CN/dashboard.json | 28 ++++++++--- public/locales/zh-TW/application.json | 7 ++- public/locales/zh-TW/dashboard.json | 26 +++++++--- src/api/api.ts | 18 +++++++ src/api/explorer.ts | 1 + src/api/workflow.ts | 10 ++++ .../Common/SinglePolicySelectionInput.tsx | 2 +- src/component/Admin/File/FileSetting.tsx | 8 +++ src/component/Admin/Settings/Event/Events.tsx | 1 + src/component/Admin/Task/TaskContent.tsx | 1 + .../Admin/Task/TaskFilterPopover.tsx | 1 + .../Pages/Tasks/StepProgressPopover.tsx | 49 ++++++++++++------- src/component/Pages/Tasks/TaskCard.tsx | 2 + src/component/Pages/Tasks/TaskProgress.tsx | 32 ++++++------ src/component/Pages/Tasks/TaskProps.tsx | 10 +++- .../Pages/Tasks/TaskSummaryTitle.tsx | 20 ++++++++ 21 files changed, 211 insertions(+), 63 deletions(-) diff --git a/public/locales/en-US/application.json b/public/locales/en-US/application.json index 122cf9a..72181fa 100644 --- a/public/locales/en-US/application.json +++ b/public/locales/en-US/application.json @@ -707,6 +707,10 @@ "sendTask": "Send task", "sendTaskDes": "Send the task to a node to process.", "downloaded": "Downloaded", + "importingFiles": "Import files", + "importingFilesDes": "Index files and importing them to the specified folder.", + "importedFiles": "Imported files", + "indexedFiles": "Indexed files", "extractedFiles": "Extracted files", "extractedFilesSize": "Extracted files size", "extractingFiles": "Extracting files", @@ -822,7 +826,8 @@ "loginApp": "You can start using the App now. If you encounter problems with the QR Code, you can also try to manually enter your username and password to log in.", "relocateFileTo": "Relocate storage policy to {{policy}} for <0>{{more}}", "extractFileTo": "Extract <0>{{more}} to <1>", - "createArchiveTo": "Create archive file to <1> for <0>{{more}}" + "createArchiveTo": "Create archive file to <1> for <0>{{more}}", + "importFileTo": "Import files from {{policy}} to <0>" }, "vas": { "points": "Points", diff --git a/public/locales/en-US/dashboard.json b/public/locales/en-US/dashboard.json index 68f6af7..4594d46 100644 --- a/public/locales/en-US/dashboard.json +++ b/public/locales/en-US/dashboard.json @@ -563,6 +563,7 @@ "toggleAll": "Toggle all", "toggleAllDes": "Enable or disable all events in this category.", "event": { + "file_imported": "External file imported", "server_start": "Server start", "user_signup": "User signup", "email_sent": "Email sent", @@ -1173,14 +1174,15 @@ "searchFileName": "Search file name", "storagePolicy": "Storage policy", "selectTargetUser": "Select target user", - "importTaskCreated": "Import task created, you can view its status in the Tasks - General.", + "importTaskCreated": "Import task created, you can view its status in the background tasks list.", "manuallyPathOnly": "The selected storage policy only supports manually inputting path.", "selectFolder": "Select folder", + "import": "Import", "importExternalFolder": "Import external folders", - "importExternalFolderDes": "You can import existing files and directory structures from your storage policy into Cloudreve. The import operation will not take up additional physical storage, but will still deduct the user's used storage quota as normal. The import will be halted when there is not enough quota.", + "importExternalFolderDes": "You can import existing files and directory structures from your storage policy into Cloudreve. The import operation will not take up additional physical storage, but will still deduct the user's used storage quota as normal.", "storagePolicyDes": "Select the storage policy where the files to be imported are currently stored.", "targetUser": "Target user", - "targetUserDes": "Select which user's file system you want to import the files to, you can search users by nickname or email.", + "targetUserDes": "Select which user's file system you want to import the files to.", "srcFolderPath": "Source folder path", "select": "Select", "selectSrcDes": "The path of the directory to be imported on the storage side.", @@ -1189,7 +1191,16 @@ "recursivelyImport": "Recursively import", "recursivelyImportDes": "Whether to import all subdirectories under the directory recursively.", "createImportTask": "Create import task", - "unlink": "Unlink (Keep physical file)" + "unlink": "Unlink (Keep physical file)", + "searchUser": "Search user by name or email...", + "extractMediaMeta": "Extract media information", + "extractMediaMetaDes": "Whether to extract media information for each file during import.", + "importWarning": "Warning", + "importWarnings": [ + "After import, the physical file will be taken over by Cloudreve, please do not modify it externally afterwards.", + "Do not import the same file multiple times.", + "If the user's file conflicts, this file will be skipped." + ] }, "entity": { "refenenceCount": "Reference count", diff --git a/public/locales/ja-JP/application.json b/public/locales/ja-JP/application.json index 64edac0..ab96735 100644 --- a/public/locales/ja-JP/application.json +++ b/public/locales/ja-JP/application.json @@ -706,6 +706,10 @@ "sendTask": "タスク送信", "sendTaskDes": "処理ノードにタスクを送信します。", "downloaded": "ダウンロード済み", + "importingFiles": "ファイルをインポート", + "importingFilesDes": "ファイルを検索し、指定されたフォルダにインポートします。", + "importedFiles": "インポート済みファイル", + "indexedFiles": "インデックス済みファイル", "extractedFiles": "解凍済みファイル数", "extractedFilesSize": "解凍済みファイルサイズ", "extractingFiles": "ファイル解凍", @@ -822,7 +826,8 @@ "loginApp": "バインドが完了したら、クライアントを使用できます。QRコードによるバインドに問題がある場合は、ユーザー名とパスワードを手動で入力してログインすることもできます。", "relocateFileTo": "<0>{{more}} のストレージポリシーを {{policy}} に変更します", "extractFileTo": "<0>{{more}} を <1> に解凍します", - "createArchiveTo": "<0>{{more}} を <1> に圧縮します" + "createArchiveTo": "<0>{{more}} を <1> に圧縮します", + "importFileTo": "{{policy}} のファイルを <1> に導入します" }, "vas": { "points": "ポイント", diff --git a/public/locales/ja-JP/dashboard.json b/public/locales/ja-JP/dashboard.json index dee199b..76cdbf6 100644 --- a/public/locales/ja-JP/dashboard.json +++ b/public/locales/ja-JP/dashboard.json @@ -559,6 +559,7 @@ "toggleAll": "全イベントの有効化/無効化", "toggleAllDes": "このカテゴリ内の全イベントを有効化または無効化します。", "event": { + "file_imported": "外部ファイル導入", "server_start": "サーバー起動", "user_signup": "ユーザー登録", "email_sent": "メール送信", @@ -1162,11 +1163,12 @@ "importTaskCreated": "インポートタスクが作成されました。「永続タスク」で実行状況を確認できます", "manuallyPathOnly": "選択されたストレージポリシーは手動でパスを入力するのみサポートしています", "selectFolder": "ディレクトリを選択", + "import": "インポート", "importExternalFolder": "外部ディレクトリのインポート", - "importExternalFolderDes": "ストレージポリシーにある既存のファイル、ディレクトリ構造をCloudreveにインポートできます。インポート操作は物理ストレージ容量を消費しませんが、ユーザーの使用済み容量は通常通り減算されます。容量不足の場合はインポートが停止します。", + "importExternalFolderDes": "ストレージポリシーにある既存のファイル、ディレクトリ構造をCloudreveにインポートできます。インポート操作は物理ストレージ容量を消費しませんが、ユーザーの使用済み容量は通常通り減算されます。", "storagePolicyDes": "インポート対象ファイルの保存先のストレージポリシーを選択", "targetUser": "対象ユーザー", - "targetUserDes": "ファイルをインポートするユーザーのファイルシステムを選択してください。ニックネームまたはメールアドレスでユーザーを検索できます。", + "targetUserDes": "ファイルをインポートするユーザーのファイルシステムを選択してください。", "srcFolderPath": "元のディレクトリパス", "select": "選択", "selectSrcDes": "ストレージ上のインポート対象ディレクトリのパス", @@ -1175,7 +1177,16 @@ "recursivelyImport": "再帰的にサブディレクトリをインポート", "recursivelyImportDes": "ディレクトリ内のすべてのサブディレクトリを再帰的にインポートしますか?", "createImportTask": "インポートタスクの作成", - "unlink": "関連付け解除(物理ファイルは保持)" + "unlink": "関連付け解除(物理ファイルは保持)", + "searchUser": "ニックネームまたはメールアドレスでユーザーを検索...", + "extractMediaMeta": "メディア情報の抽出", + "extractMediaMetaDes": "インポート時に各ファイルのメディア情報を抽出するかどうか。", + "importWarning": "注意事項", + "importWarnings": [ + "インポート後、物理ファイルはCloudreveに移行されます。外部での変更はお控えください。", + "同じファイルを複数回インポートしないでください。", + "ユーザーのファイルが衝突した場合、このファイルはスキップされます。" + ] }, "entity": { "refenenceCount": "参照回数", @@ -1241,6 +1252,7 @@ "file": "ファイル" }, "task": { + "import": "ファイルのインポート", "confirmDelete": "このタスクを削除しますか?", "confirmBatchDelete": "{{num}}個のタスクを削除しますか?", "deleteXTasks": "{{num}}個のタスクを削除", diff --git a/public/locales/zh-CN/application.json b/public/locales/zh-CN/application.json index 3469508..a1b0520 100644 --- a/public/locales/zh-CN/application.json +++ b/public/locales/zh-CN/application.json @@ -706,6 +706,10 @@ "sendTask": "发送任务", "sendTaskDes": "将任务发送到处理节点。", "downloaded": "已下载", + "importingFiles": "导入文件", + "importingFilesDes": "检索文件并将其导入到指定目录。", + "importedFiles": "已导入文件", + "indexedFiles": "已索引文件", "extractedFiles": "已解压文件数量", "extractedFilesSize": "已解压文件大小", "extractingFiles": "解压文件", @@ -822,7 +826,8 @@ "loginApp": "完成绑定,你可以开始使用客户端了。如果扫码绑定遇到问题,你也可以尝试手动输入用户名和密码登录。", "relocateFileTo": "将 <0>{{more}} 的存储策略转移至 {{policy}}", "extractFileTo": "将 <0>{{more}} 解压缩至 <1>", - "createArchiveTo": "将 <0>{{more}} 打包至 <1>" + "createArchiveTo": "将 <0>{{more}} 打包至 <1>", + "importFileTo": "将 {{policy}} 中的文件导入至 <0>" }, "vas": { "points": "积分", diff --git a/public/locales/zh-CN/dashboard.json b/public/locales/zh-CN/dashboard.json index e8e7950..cd43d03 100644 --- a/public/locales/zh-CN/dashboard.json +++ b/public/locales/zh-CN/dashboard.json @@ -559,6 +559,7 @@ "toggleAll": "启用/禁用所有事件", "toggleAllDes": "启用或禁用此类别中的所有事件。", "event": { + "file_imported": "外部文件导入", "server_start": "服务器启动", "user_signup": "用户注册", "email_sent": "邮件发送", @@ -1159,23 +1160,33 @@ "searchFileName": "搜索文件名", "storagePolicy": "存储策略", "selectTargetUser": "请先选择目标用户", - "importTaskCreated": "导入任务已创建,你可以在“持久任务”中查看执行情况", + "importTaskCreated": "导入任务已创建,你可以在“后台任务”中查看执行情况", "manuallyPathOnly": "选择的存储策略只支持手动输入路径", "selectFolder": "选择目录", + "import": "导入", "importExternalFolder": "导入外部目录", - "importExternalFolderDes": "你可以将存储策略中已有文件、目录结构导入到 Cloudreve 中,导入操作不会额外占用物理存储空间,但仍会正常扣除用户已用容量空间,空间不足时将停止导入。", - "storagePolicyDes": "选择要导入文件目前存储所在的存储策略", + "importExternalFolderDes": "你可以将存储策略中已有文件、目录结构导入到 Cloudreve 中,导入操作不会额外占用物理存储空间,但仍会正常扣除用户已用容量空间。", + "storagePolicyDes": "选择要导入文件目前存储所在的存储策略。", "targetUser": "目标用户", - "targetUserDes": "选择要将文件导入到哪个用户的文件系统中,可通过昵称、邮箱搜索用户", + "targetUserDes": "选择要将文件导入到哪个用户的文件系统中。", "srcFolderPath": "原始目录路径", "select": "选择", - "selectSrcDes": "要导入的目录在存储端的路径", + "selectSrcDes": "要导入的目录在存储端的路径。", "dstFolderPath": "目的目录路径", - "dstFolderPathDes": "要将目录导入到用户文件系统中的路径", + "dstFolderPathDes": "要将目录导入到用户文件系统中的路径。", "recursivelyImport": "递归导入子目录", - "recursivelyImportDes": "是否将目录下的所有子目录递归导入", + "recursivelyImportDes": "是否将目录下的所有子目录递归导入。", "createImportTask": "创建导入任务", - "unlink": "解除关联(保留物理文件)" + "unlink": "解除关联(保留物理文件)", + "searchUser": "搜索用户昵称或邮箱...", + "extractMediaMeta": "提取媒体信息", + "extractMediaMetaDes": "是否在导入文件的同时尝试提取每个文件的媒体信息。", + "importWarning": "注意事项", + "importWarnings": [ + "导入后,物理文件将由 Cloudreve 接管,后续请不要在外部修改此文件;", + "不要重复导入相同的文件;", + "如果用户文件冲突,此文件会被跳过;" + ] }, "entity": { "refenenceCount": "引用次数", @@ -1241,6 +1252,7 @@ "file": "文件" }, "task": { + "import": "导入文件", "confirmDelete": "确认要删除这个任务?", "confirmBatchDelete": "确认要删除 {{num}} 个任务?", "deleteXTasks": "删除 {{num}} 个任务", diff --git a/public/locales/zh-TW/application.json b/public/locales/zh-TW/application.json index c7739f9..7d4d20f 100644 --- a/public/locales/zh-TW/application.json +++ b/public/locales/zh-TW/application.json @@ -706,6 +706,10 @@ "sendTask": "傳送任務", "sendTaskDes": "將任務傳送到處理節點。", "downloaded": "已下載", + "importingFiles": "匯入檔案", + "importingFilesDes": "檢索檔案並將其匯入到指定目錄。", + "importedFiles": "已匯入檔案", + "indexedFiles": "已索引檔案", "extractedFiles": "已解壓檔案數量", "extractedFilesSize": "已解壓檔案大小", "extractingFiles": "解壓檔案", @@ -822,7 +826,8 @@ "loginApp": "完成繫結,你可以開始使用客戶端了。如果掃碼繫結遇到問題,你也可以嘗試手動輸入使用者名稱和密碼登入。", "relocateFileTo": "將 <0>{{more}} 的儲存策略轉移至 {{policy}}", "extractFileTo": "將 <0>{{more}} 解壓縮至 <1>", - "createArchiveTo": "將 <0>{{more}} 打包至 <1>" + "createArchiveTo": "將 <0>{{more}} 打包至 <1>", + "importFileTo": "將 {{policy}} 中的文件導入至 <0>" }, "vas": { "points": "積分", diff --git a/public/locales/zh-TW/dashboard.json b/public/locales/zh-TW/dashboard.json index cf355ec..e63c746 100644 --- a/public/locales/zh-TW/dashboard.json +++ b/public/locales/zh-TW/dashboard.json @@ -556,6 +556,7 @@ "toggleAll": "啟用/禁用所有事件", "toggleAllDes": "啟用或禁用此類別中的所有事件。", "event": { + "file_imported": "外部檔案導入", "server_start": "伺服器啟動", "user_signup": "使用者注冊", "email_sent": "郵件傳送", @@ -1156,23 +1157,33 @@ "searchFileName": "搜尋檔名", "storagePolicy": "儲存策略", "selectTargetUser": "請先選擇目標使用者", - "importTaskCreated": "匯入任務已建立,你可以在“持久任務”中檢視執行情況", + "importTaskCreated": "匯入任務已建立,你可以在“後臺任務”中檢視執行情況", "manuallyPathOnly": "選擇的儲存策略只支援手動輸入路徑", "selectFolder": "選擇目錄", + "import": "匯入", "importExternalFolder": "匯入外部目錄", - "importExternalFolderDes": "你可以將儲存策略中已有檔案、目錄結構匯入到 Cloudreve 中,匯入操作不會額外佔用物理儲存空間,但仍會正常扣除使用者已用容量空間,空間不足時將停止匯入。", - "storagePolicyDes": "選擇要匯入檔案目前儲存所在的儲存策略", + "importExternalFolderDes": "你可以將儲存策略中已有檔案、目錄結構匯入到 Cloudreve 中,匯入操作不會額外佔用物理儲存空間,但仍會正常扣除使用者已用容量空間。", + "storagePolicyDes": "選擇要匯入檔案目前儲存所在的儲存策略。", "targetUser": "目標使用者", - "targetUserDes": "選擇要將檔案匯入到哪個使用者的檔案系統中,可通過暱稱、郵箱搜尋使用者", + "targetUserDes": "選擇要將檔案匯入到哪個使用者的檔案系統中。", "srcFolderPath": "原始目錄路徑", "select": "選擇", "selectSrcDes": "要匯入的目錄在儲存端的路徑", "dstFolderPath": "目的目錄路徑", - "dstFolderPathDes": "要將目錄匯入到使用者檔案系統中的路徑", + "dstFolderPathDes": "要將目錄匯入到使用者檔案系統中的路徑。", "recursivelyImport": "遞迴匯入子目錄", - "recursivelyImportDes": "是否將目錄下的所有子目錄遞迴匯入", + "recursivelyImportDes": "是否將目錄下的所有子目錄遞迴匯入。", "createImportTask": "建立匯入任務", - "unlink": "解除關聯(保留物理檔案)" + "unlink": "解除關聯(保留物理檔案)", + "searchUser": "搜尋使用者昵稱或郵箱...", + "extractMediaMeta": "提取媒体信息", + "extractMediaMetaDes": "是否在匯入檔案的同時嘗試提取每個檔案的媒體資訊。", + "importWarning": "注意事項", + "importWarnings": [ + "匯入後,物理檔案將由 Cloudreve 接管,後續請不要在外部修改此檔案;", + "不要重複匯入相同的檔案;", + "如果使用者檔案衝突,此檔案會被跳過;" + ] }, "entity": { "refenenceCount": "引用次數", @@ -1238,6 +1249,7 @@ "file": "檔案" }, "task": { + "import": "導入檔案", "confirmDelete": "確認要刪除這個任務?", "confirmBatchDelete": "確認要刪除 {{num}} 個任務?", "deleteXTasks": "刪除 {{num}} 個任務", diff --git a/src/api/api.ts b/src/api/api.ts index d3f222a..6c5f6bc 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -94,6 +94,7 @@ import { import { ArchiveWorkflowService, DownloadWorkflowService, + ImportWorkflowService, ListTaskService, SetDownloadFilesService, TaskListResponse, @@ -1950,3 +1951,20 @@ export function sendCalibrateUserStorage(id: number): ThunkResponse { ); }; } + +export function sendImport(req: ImportWorkflowService): ThunkResponse { + return async (dispatch, _getState) => { + return await dispatch( + send( + "/workflow/import", + { + data: req, + method: "POST", + }, + { + ...defaultOpts, + }, + ), + ); + }; +} diff --git a/src/api/explorer.ts b/src/api/explorer.ts index 26d3991..3304439 100644 --- a/src/api/explorer.ts +++ b/src/api/explorer.ts @@ -366,6 +366,7 @@ export const AuditLogType = { add_passkey: 52, remove_passkey: 53, redeem_gift_code: 54, + file_imported: 55, }; export interface MultipleUriService { diff --git a/src/api/workflow.ts b/src/api/workflow.ts index 1647b8e..65362d9 100644 --- a/src/api/workflow.ts +++ b/src/api/workflow.ts @@ -100,6 +100,15 @@ export interface DownloadWorkflowService { dst: string; } +export interface ImportWorkflowService { + src: string; + dst: string; + extract_media_meta?: boolean; + user_id: string; + recursive?: boolean; + policy_id: number; +} + export interface ListTaskService { page_size: number; category: ListTaskCategory; @@ -120,6 +129,7 @@ export enum TaskType { entity_recycle_routine = "entity_recycle_routine", explicit_entity_recycle = "explicit_entity_recycle", upload_sentinel_check = "upload_sentinel_check", + import = "import", } export enum TaskStatus { diff --git a/src/component/Admin/Common/SinglePolicySelectionInput.tsx b/src/component/Admin/Common/SinglePolicySelectionInput.tsx index 1645b40..cf7a6f3 100644 --- a/src/component/Admin/Common/SinglePolicySelectionInput.tsx +++ b/src/component/Admin/Common/SinglePolicySelectionInput.tsx @@ -8,7 +8,7 @@ import { DenseSelect } from "../../Common/StyledComponents"; import { SquareMenuItem } from "../../FileManager/ContextMenu/ContextMenu"; export interface SinglePolicySelectionInputProps { - value: number; + value: number | undefined; onChange: (value: number) => void; emptyValue?: number; emptyText?: string; diff --git a/src/component/Admin/File/FileSetting.tsx b/src/component/Admin/File/FileSetting.tsx index dae72b9..43189c8 100644 --- a/src/component/Admin/File/FileSetting.tsx +++ b/src/component/Admin/File/FileSetting.tsx @@ -26,6 +26,7 @@ import { File } from "../../../api/dashboard"; import { useAppDispatch } from "../../../redux/hooks"; import { confirmOperation } from "../../../redux/thunks/dialog"; import { NoWrapTableCell, SecondaryButton, StyledTableContainerPaper } from "../../Common/StyledComponents"; +import ArrowImport from "../../Icons/ArrowImport"; import ArrowSync from "../../Icons/ArrowSync"; import Filter from "../../Icons/Filter"; import PageContainer from "../../Pages/PageContainer"; @@ -36,6 +37,7 @@ import UserDialog from "../User/UserDialog/UserDialog"; import FileDialog from "./FileDialog/FileDialog"; import FileFilterPopover from "./FileFilterPopover"; import FileRow from "./FileRow"; +import { ImportFileDialog } from "./ImportFileDialog"; export const StoragePolicyQuery = "storage_policy"; export const OwnerQuery = "owner"; @@ -62,6 +64,7 @@ const FileSetting = () => { const [count, setCount] = useState(0); const [selected, setSelected] = useState([]); const [createNewOpen, setCreateNewOpen] = useState(false); + const [importFileDialogOpen, setImportFileDialogOpen] = useState(false); const filterPopupState = usePopupState({ variant: "popover", popupId: "userFilterPopover", @@ -200,9 +203,14 @@ const FileSetting = () => { }} /> setUserDialogOpen(false)} userID={userDialogID} /> + setImportFileDialogOpen(false)} /> + + ( { @@ -40,6 +38,27 @@ const ProgressBar = ({ pkey, p }: { pkey: string; p: TaskProgress }) => { ); } + if (pkey == ProgressKeys.imported) { + return ( + + ); + } + + if (pkey == ProgressKeys.indexed) { + return ( + + ); + } + if (pkey.startsWith(ProgressKeys.upload_single_)) { return ( { } }; -const StepProgressPopover = ({ - task, - open, - ...rest -}: StepProgressPopoverProps) => { +const StepProgressPopover = ({ task, open, ...rest }: StepProgressPopoverProps) => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const stopPropagation = useCallback((e: any) => e.stopPropagation(), []); - const [progress, setProgress] = useState( - undefined, - ); + const [progress, setProgress] = useState(undefined); useEffect(() => { if (open) { @@ -188,9 +201,7 @@ const StepProgressPopover = ({ Object.keys(progress).map((key, index) => ( <> - {index < Object.keys(progress).length - 1 && ( - - )} + {index < Object.keys(progress).length - 1 && } ))} {progress && Object.keys(progress).length == 0 && ( diff --git a/src/component/Pages/Tasks/TaskCard.tsx b/src/component/Pages/Tasks/TaskCard.tsx index 6d3b7b9..cfd468f 100644 --- a/src/component/Pages/Tasks/TaskCard.tsx +++ b/src/component/Pages/Tasks/TaskCard.tsx @@ -23,6 +23,7 @@ import { DefaultButton } from "../../Common/StyledComponents.tsx"; import FileIcon from "../../FileManager/Explorer/FileIcon.tsx"; import Archive from "../../Icons/Archive.tsx"; import ArchiveArrow from "../../Icons/ArchiveArrow.tsx"; +import ArrowImport from "../../Icons/ArrowImport.tsx"; import StorageOutlined from "../../Icons/StorageOutlined.tsx"; import TaskDetail from "./TaskDetail.tsx"; import TaskSummaryStatus from "./TaskSummaryStatus.tsx"; @@ -103,6 +104,7 @@ const taskIconsMap: { [TaskType.create_archive]: Archive, [TaskType.extract_archive]: ArchiveArrow, [TaskType.relocate]: StorageOutlined, + [TaskType.import]: ArrowImport, }; const TaskCard = ({ loading, showProgress, onLoad, task }: TaskCardProps) => { diff --git a/src/component/Pages/Tasks/TaskProgress.tsx b/src/component/Pages/Tasks/TaskProgress.tsx index af37666..b1bda52 100644 --- a/src/component/Pages/Tasks/TaskProgress.tsx +++ b/src/component/Pages/Tasks/TaskProgress.tsx @@ -1,14 +1,9 @@ -import { - NodeTypes, - TaskResponse, - TaskStatus, - TaskType, -} from "../../../api/workflow.ts"; -import { useEffect, useMemo, useState } from "react"; import { Box, Stepper, useMediaQuery, useTheme } from "@mui/material"; +import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; -import TaskProgressStep from "./TaskProgressStep.tsx"; +import { NodeTypes, TaskResponse, TaskStatus, TaskType } from "../../../api/workflow.ts"; import PieceProgress from "./PieceProgress.tsx"; +import TaskProgressStep from "./TaskProgressStep.tsx"; export interface TaskProgressProps { task: TaskResponse; @@ -78,6 +73,18 @@ const stepOptions: { completedStep, ], ], + [TaskType.import]: [ + // Master + [ + queueingStep, + { + title: "setting.importingFiles", + state: "", + description: "setting.importingFilesDes", + supportProgress: true, + }, + ], + ], [TaskType.relocate]: [ // Master [ @@ -188,9 +195,7 @@ const TaskProgress = ({ task }: TaskProgressProps) => { const { t } = useTranslation(); const [activeStep, setActiveStep] = useState(0); const steps = useMemo((): StepModel[] => { - return ( - stepOptions[task.type]?.[task.node?.type == NodeTypes.slave ? 1 : 0] ?? [] - ); + return stepOptions[task.type]?.[task.node?.type == NodeTypes.slave ? 1 : 0] ?? []; }, [task.id, task.node?.type]); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("md")); @@ -216,10 +221,7 @@ const TaskProgress = ({ task }: TaskProgressProps) => { return ( - + {steps.map((step, index) => ( { value={ ); + case TaskType.import: + return ( + p.id == summary?.props.dst_policy_id)?.name ?? "Unknown" + : "", + }} + components={[ + , + ]} + /> + ); default: return (