Merge pull request #404 from Moonlight-Panel/v2_FileManagerImprovements
Improved file manager. This is the first merge of this branch. More commits are planned
This commit is contained in:
commit
c9fe469f5b
12 changed files with 87 additions and 20 deletions
File diff suppressed because one or more lines are too long
|
@ -39,6 +39,15 @@ public class CoreConfiguration
|
||||||
[Description("Specifies the location of the key .pem file to load")]
|
[Description("Specifies the location of the key .pem file to load")]
|
||||||
[JsonProperty("KeyPath")]
|
[JsonProperty("KeyPath")]
|
||||||
public string KeyPath { get; set; } = "";
|
public string KeyPath { get; set; } = "";
|
||||||
|
|
||||||
|
[Description("Specifies the file upload limit per http request in megabytes")]
|
||||||
|
[JsonProperty("UploadLimit")]
|
||||||
|
public int UploadLimit { get; set; } = 100;
|
||||||
|
|
||||||
|
[Description(
|
||||||
|
"Specifies the maximum message size moonlight can receive via the websocket connection in kilobytes")]
|
||||||
|
[JsonProperty("MessageSizeLimit")]
|
||||||
|
public int MessageSizeLimit { get; set; } = 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DatabaseData
|
public class DatabaseData
|
||||||
|
|
|
@ -64,15 +64,26 @@ public class CoreFeature : MoonlightFeature
|
||||||
|
|
||||||
// Add external services and blazor/asp.net stuff
|
// Add external services and blazor/asp.net stuff
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
builder.Services.AddServerSideBlazor();
|
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddBlazorTable();
|
builder.Services.AddBlazorTable();
|
||||||
|
|
||||||
|
// Configure blazor pipeline in detail
|
||||||
|
builder.Services.AddServerSideBlazor().AddHubOptions(options =>
|
||||||
|
{
|
||||||
|
options.MaximumReceiveMessageSize = ByteSizeValue.FromKiloBytes(config.Http.MessageSizeLimit).Bytes;
|
||||||
|
});
|
||||||
|
|
||||||
// Setup authentication if required
|
// Setup authentication if required
|
||||||
if (config.Authentication.UseDefaultAuthentication)
|
if (config.Authentication.UseDefaultAuthentication)
|
||||||
builder.Services.AddScoped<IAuthenticationProvider, DefaultAuthenticationProvider>();
|
builder.Services.AddScoped<IAuthenticationProvider, DefaultAuthenticationProvider>();
|
||||||
|
|
||||||
|
// Setup http upload limit
|
||||||
|
context.Builder.WebHost.ConfigureKestrel(options =>
|
||||||
|
{
|
||||||
|
options.Limits.MaxRequestBodySize = ByteSizeValue.FromMegaBytes(config.Http.UploadLimit).Bytes;
|
||||||
|
});
|
||||||
|
|
||||||
// Assets
|
// Assets
|
||||||
|
|
||||||
// - Javascript
|
// - Javascript
|
||||||
|
|
|
@ -26,7 +26,6 @@ public class FileManagerFeature : MoonlightFeature
|
||||||
var config = new ConfigService<CoreConfiguration>(PathBuilder.File("storage", "configs", "core.json"));
|
var config = new ConfigService<CoreConfiguration>(PathBuilder.File("storage", "configs", "core.json"));
|
||||||
context.Builder.Services.AddSingleton(new JwtService<FileManagerJwtType>(config.Get().Security.Token));
|
context.Builder.Services.AddSingleton(new JwtService<FileManagerJwtType>(config.Get().Security.Token));
|
||||||
|
|
||||||
context.AddAsset("FileManager", "js/dropzone.js");
|
|
||||||
context.AddAsset("FileManager", "js/filemanager.js");
|
context.AddAsset("FileManager", "js/filemanager.js");
|
||||||
context.AddAsset("FileManager", "editor/ace.css");
|
context.AddAsset("FileManager", "editor/ace.css");
|
||||||
context.AddAsset("FileManager", "editor/ace.js");
|
context.AddAsset("FileManager", "editor/ace.js");
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
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 ArchiveSelectionAction : IFileManagerSelectionAction
|
||||||
|
{
|
||||||
|
public string Name => "Archive";
|
||||||
|
public string Color => "primary";
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
await archiveAccess.Archive(
|
||||||
|
access.CurrentDirectory + fileName,
|
||||||
|
entries.Select(x => access.CurrentDirectory + x.Name).ToArray()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,9 @@ namespace Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
|
||||||
|
|
||||||
public class BaseFileAccess : IDisposable
|
public class BaseFileAccess : IDisposable
|
||||||
{
|
{
|
||||||
private readonly IFileActions Actions;
|
public readonly IFileActions Actions;
|
||||||
|
|
||||||
private string CurrentDirectory = "/";
|
public string CurrentDirectory { get; private set; } = "/";
|
||||||
|
|
||||||
public BaseFileAccess(IFileActions actions)
|
public BaseFileAccess(IFileActions actions)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
|
||||||
|
|
||||||
|
public interface IArchiveFileActions
|
||||||
|
{
|
||||||
|
public Task Archive(string path, string[] files);
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
|
|
||||||
|
|
||||||
public interface IFileCompressAccess
|
|
||||||
{
|
|
||||||
public Task Compress(string[] names);
|
|
||||||
public Task Decompress(string name);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
namespace Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
|
|
||||||
|
|
||||||
public interface IFileLaunchAccess
|
|
||||||
{
|
|
||||||
public Task<string> GetLaunchUrl();
|
|
||||||
}
|
|
|
@ -29,9 +29,13 @@ public class FileManagerInteropService
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateUrl(string urlId, string url)
|
public async Task UpdateUrl(string urlId, string url)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await JsRuntime.InvokeVoidAsync("filemanager.updateUrl", urlId, url);
|
await JsRuntime.InvokeVoidAsync("filemanager.updateUrl", urlId, url);
|
||||||
}
|
}
|
||||||
|
catch (TaskCanceledException) { /* ignored */ }
|
||||||
|
}
|
||||||
|
|
||||||
[JSInvokable]
|
[JSInvokable]
|
||||||
public async Task UpdateStatus()
|
public async Task UpdateStatus()
|
||||||
|
|
|
@ -209,6 +209,15 @@
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@if (Entries.Length == 0)
|
||||||
|
{
|
||||||
|
<div class="py-4">
|
||||||
|
<IconAlert Color="primary" Title="No files and folders found" Icon="bx-cloud-upload">
|
||||||
|
Drag and drop files and folders here to start uploading them or click on the upload button on the top
|
||||||
|
</IconAlert>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (EnableContextMenu && ContextMenuTemplate != null)
|
@if (EnableContextMenu && ContextMenuTemplate != null)
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Moonlight.Features.Servers.Exceptions;
|
||||||
|
|
||||||
namespace Moonlight.Features.Servers.Helpers;
|
namespace Moonlight.Features.Servers.Helpers;
|
||||||
|
|
||||||
public class ServerApiFileActions : IFileActions
|
public class ServerApiFileActions : IFileActions, IArchiveFileActions
|
||||||
{
|
{
|
||||||
private readonly string Endpoint;
|
private readonly string Endpoint;
|
||||||
private readonly string Token;
|
private readonly string Token;
|
||||||
|
@ -43,6 +43,11 @@ public class ServerApiFileActions : IFileActions
|
||||||
public async Task WriteFileStream(string path, Stream dataStream) =>
|
public async Task WriteFileStream(string path, Stream dataStream) =>
|
||||||
await ApiClient.PostFile($"writeFileStream?path={path}", dataStream, "upload");
|
await ApiClient.PostFile($"writeFileStream?path={path}", dataStream, "upload");
|
||||||
|
|
||||||
|
public async Task Archive(string path, string[] files)
|
||||||
|
{
|
||||||
|
await ApiClient.Post($"archive?path={path}&provider=tar.gz", files);
|
||||||
|
}
|
||||||
|
|
||||||
public IFileActions Clone() => new ServerApiFileActions(Endpoint, Token, ServerId);
|
public IFileActions Clone() => new ServerApiFileActions(Endpoint, Token, ServerId);
|
||||||
|
|
||||||
public void Dispose() => ApiClient.Dispose();
|
public void Dispose() => ApiClient.Dispose();
|
||||||
|
|
Loading…
Reference in a new issue