소스 검색

Merge pull request #408 from Moonlight-Panel/v2_FileManagerImprovements

Adding some more file manager improvements to the main branch
Masu Baumgartner 1 년 전
부모
커밋
3f0cdff262

+ 1 - 1
Moonlight/Core/UI/Components/Partials/SoftErrorHandler.razor

@@ -7,7 +7,7 @@
 
 @inherits ErrorBoundaryBase
 
-@if (Crashed || CurrentException != null)
+@if (Crashed || Exception != null)
 {
     if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development" || (IdentityService.IsLoggedIn && IdentityService.CurrentUser.Permissions >= 9000))
     {

+ 3 - 0
Moonlight/Features/FileManager/FileManagerFeature.cs

@@ -54,9 +54,12 @@ public class FileManagerFeature : MoonlightFeature
         await pluginService.RegisterImplementation<IFileManagerContextAction>(new RenameContextAction());
         await pluginService.RegisterImplementation<IFileManagerContextAction>(new MoveContextAction());
         await pluginService.RegisterImplementation<IFileManagerContextAction>(new DownloadContextAction());
+        await pluginService.RegisterImplementation<IFileManagerContextAction>(new ArchiveContextAction());
+        await pluginService.RegisterImplementation<IFileManagerContextAction>(new ExtractContextAction());
         await pluginService.RegisterImplementation<IFileManagerContextAction>(new DeleteContextAction());
 
         await pluginService.RegisterImplementation<IFileManagerSelectionAction>(new MoveSelectionAction());
+        await pluginService.RegisterImplementation<IFileManagerSelectionAction>(new ArchiveSelectionAction());
         await pluginService.RegisterImplementation<IFileManagerSelectionAction>(new DeleteSelectionAction());
 
         await pluginService.RegisterImplementation<IFileManagerCreateAction>(new CreateFileAction());

+ 59 - 0
Moonlight/Features/FileManager/Implementations/ArchiveContextAction.cs

@@ -0,0 +1,59 @@
+using MoonCore.Exceptions;
+using MoonCore.Helpers;
+using MoonCoreUI.Services;
+using Moonlight.Features.FileManager.Interfaces;
+using Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
+
+namespace Moonlight.Features.FileManager.Implementations;
+
+public class ArchiveContextAction : IFileManagerContextAction
+{
+    public string Name => "Archive";
+    public string Icon => "bxs-archive-in";
+    public string Color => "warning";
+    public Func<FileEntry, bool> Filter => _ => true;
+
+    public async Task Execute(BaseFileAccess access, UI.Components.FileManager fileManager, FileEntry entry,
+        IServiceProvider provider)
+    {
+        var archiveAccess = access.Actions as IArchiveFileActions;
+
+        if (archiveAccess == null)
+            throw new DisplayException("This file access does not support archiving");
+
+        var alertService = provider.GetRequiredService<AlertService>();
+
+        var fileName = await alertService.Text("Enter the archive file name", "",
+            Formatter.FormatDate(DateTime.UtcNow) + ".tar.gz");
+
+        if (string.IsNullOrEmpty(fileName) || fileName.Contains("..")) // => canceled
+            return;
+
+        var toastService = provider.GetRequiredService<ToastService>();
+
+        await toastService.CreateProgress("fileManagerArchive", "Archiving... Please be patient");
+
+        try
+        {
+            await archiveAccess.Archive(
+                access.CurrentDirectory + fileName,
+                new[] { access.CurrentDirectory + entry.Name }
+            );
+            
+            await toastService.Success("Successfully created archive");
+        }
+        catch (Exception e)
+        {
+            Logger.Warn($"An error occured while archiving item ({entry.Name}):");
+            Logger.Warn(e);
+
+            await toastService.Danger("An unknown error occured while creating archive");
+        }
+        finally
+        {
+            await toastService.RemoveProgress("fileManagerArchive");
+        }
+
+        await fileManager.View.Refresh();
+    }
+}

+ 26 - 9
Moonlight/Features/FileManager/Implementations/ArchiveSelectionAction.cs

@@ -14,10 +14,7 @@ public class ArchiveSelectionAction : IFileManagerSelectionAction
     public async Task Execute(BaseFileAccess access, UI.Components.FileManager fileManager, FileEntry[] entries,
         IServiceProvider provider)
     {
-        if (!access.Actions.GetType().IsAssignableFrom(typeof(IArchiveFileActions)))
-            throw new DisplayException("This file access does not support archiving");
-
-        var archiveAccess = access as IArchiveFileActions;
+        var archiveAccess = access.Actions as IArchiveFileActions;
 
         if (archiveAccess == null)
             throw new DisplayException("This file access does not support archiving");
@@ -29,10 +26,30 @@ public class ArchiveSelectionAction : IFileManagerSelectionAction
 
         if (string.IsNullOrEmpty(fileName) || fileName.Contains("..")) // => canceled
             return;
-
-        await archiveAccess.Archive(
-            access.CurrentDirectory + fileName,
-            entries.Select(x => access.CurrentDirectory + x.Name).ToArray()
-        );
+        
+        var toastService = provider.GetRequiredService<ToastService>();
+
+        await toastService.CreateProgress("fileManagerArchive", "Archiving... Please be patient");
+        
+        try
+        {
+            await archiveAccess.Archive(
+                access.CurrentDirectory + fileName,
+                entries.Select(x => access.CurrentDirectory + x.Name).ToArray()
+            );
+            
+            await toastService.Success("Successfully created archive");
+        }
+        catch (Exception e)
+        {
+            Logger.Warn($"An error occured while archiving items ({entries.Length}):");
+            Logger.Warn(e);
+
+            await toastService.Danger("An unknown error occured while creating archive");
+        }
+        finally
+        {
+            await toastService.RemoveProgress("fileManagerArchive");
+        }
     }
 }

+ 52 - 0
Moonlight/Features/FileManager/Implementations/ExtractContextAction.cs

@@ -0,0 +1,52 @@
+using MoonCore.Exceptions;
+using MoonCore.Helpers;
+using MoonCoreUI.Services;
+using Moonlight.Features.FileManager.Interfaces;
+using Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
+
+namespace Moonlight.Features.FileManager.Implementations;
+
+public class ExtractContextAction : IFileManagerContextAction
+{
+    public string Name => "Extract";
+    public string Icon => "bxs-archive-out";
+    public string Color => "warning";
+    public Func<FileEntry, bool> Filter => entry => entry.IsFile && entry.Name.EndsWith(".tar.gz");
+    public async Task Execute(BaseFileAccess access, UI.Components.FileManager fileManager, FileEntry entry, IServiceProvider provider)
+    {
+        var archiveAccess = access.Actions as IArchiveFileActions;
+
+        if (archiveAccess == null)
+            throw new DisplayException("This file access does not support archiving");
+
+        await fileManager.OpenFolderSelect("Select where you want to extract the content of the archive", async destination =>
+        {
+            var toastService = provider.GetRequiredService<ToastService>();
+
+            await toastService.CreateProgress("fileManagerExtract", "Extracting... Please be patient");
+
+            try
+            {
+                await archiveAccess.Extract(
+                    access.CurrentDirectory + entry.Name,
+                    destination
+                );
+            
+                await toastService.Success("Successfully extracted archive");
+            }
+            catch (Exception e)
+            {
+                Logger.Warn($"An error occured while extracting archive ({entry.Name}):");
+                Logger.Warn(e);
+
+                await toastService.Danger("An unknown error occured while extracting archive");
+            }
+            finally
+            {
+                await toastService.RemoveProgress("fileManagerExtract");
+            }
+
+            await fileManager.View.Refresh();
+        });
+    }
+}

+ 1 - 0
Moonlight/Features/FileManager/Models/Abstractions/FileAccess/IArchiveFileActions.cs

@@ -3,4 +3,5 @@ namespace Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
 public interface IArchiveFileActions
 {
     public Task Archive(string path, string[] files);
+    public Task Extract(string path, string destination);
 }

+ 2 - 1
Moonlight/Features/FileManager/UI/Components/FileManager.razor

@@ -95,7 +95,8 @@ else
                   OnEntryClicked="OnEntryClicked"
                   OnNavigateUpClicked="OnNavigateUpClicked"
                   OnSelectionChanged="OnSelectionChanged"
-                  EnableContextMenu="true">
+                  EnableContextMenu="true"
+                  ShowUploadPrompt="true">
             <ContextMenuTemplate>
                 @foreach (var action in ContextActions)
                 {

+ 2 - 1
Moonlight/Features/FileManager/UI/Components/FileView.razor

@@ -210,7 +210,7 @@
         </tbody>
     </table>
     
-    @if (Entries.Length == 0)
+    @if (Entries.Length == 0 && ShowUploadPrompt)
     {
         <div class="py-4">
             <IconAlert Color="primary" Title="No files and folders found" Icon="bx-cloud-upload">
@@ -240,6 +240,7 @@
     [Parameter] public bool ShowDate { get; set; } = true;
     [Parameter] public bool ShowSelect { get; set; } = true;
     [Parameter] public bool ShowNavigateUp { get; set; } = true;
+    [Parameter] public bool ShowUploadPrompt { get; set; } = false;
 
     [Parameter] public RenderFragment<FileEntry>? ContextMenuTemplate { get; set; }
     [Parameter] public bool EnableContextMenu { get; set; } = false;

+ 5 - 0
Moonlight/Features/Servers/Helpers/ServerApiFileActions.cs

@@ -47,6 +47,11 @@ public class ServerApiFileActions : IFileActions, IArchiveFileActions
     {
         await ApiClient.Post($"archive?path={path}&provider=tar.gz", files);
     }
+
+    public async Task Extract(string path, string destination)
+    {
+        await ApiClient.Post($"extract?path={path}&destination={destination}&provider=tar.gz");
+    }
     
     public IFileActions Clone() => new ServerApiFileActions(Endpoint, Token, ServerId);