diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0474640 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +**/.vs/ +.git/ +**/bin/ +**/obj \ No newline at end of file diff --git a/README.md b/README.md index cb9e05f..0e13fda 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ This document explorer demo application showcases several Syncfusion Blazor UI c The samples requires the below requirements to run. -* [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) -* [.NET Core SDK 3.1.2](https://dotnet.microsoft.com/download/dotnet-core/3.1) +* [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) +* [.NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) ### Run @@ -21,4 +21,4 @@ The samples requires the below requirements to run. ### https://blazor.syncfusion.com/showcase/documentexplorer -Check all the showcase samples from here. \ No newline at end of file +Check all the showcase samples from here. diff --git a/server-side/App.razor b/server-side/App.razor deleted file mode 100644 index 6f67a6e..0000000 --- a/server-side/App.razor +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

Sorry, there's nothing at this address.

-
-
-
diff --git a/server-side/Components/App.razor b/server-side/Components/App.razor new file mode 100644 index 0000000..97d4e69 --- /dev/null +++ b/server-side/Components/App.razor @@ -0,0 +1,56 @@ + + + + + + + Blazor Document Explorer Showcase example | Syncfusion Demos + + + + + + + + + + + + + + + + + + + + + + + + @**@ + + @**@ + +
+ + An error has occurred. This application may no longer respond until reloaded. + + + An unhandled exception has occurred. See browser dev tools for details. + + Reload + 🗙 +
+ + + + diff --git a/server-side/Components/Routes.razor b/server-side/Components/Routes.razor new file mode 100644 index 0000000..4d9c4db --- /dev/null +++ b/server-side/Components/Routes.razor @@ -0,0 +1,6 @@ + + + + + + diff --git a/server-side/Components/_Imports.razor b/server-side/Components/_Imports.razor new file mode 100644 index 0000000..0b67cc5 --- /dev/null +++ b/server-side/Components/_Imports.razor @@ -0,0 +1,20 @@ +@using System.Net.Http +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.JSInterop +@using DocumentExplorer +@using DocumentExplorer.Models +@using DocumentExplorer.Shared +@using Newtonsoft.Json +@using Newtonsoft.Json.Linq +@using Syncfusion.Blazor +@using Syncfusion.Blazor.Navigations +@using Microsoft.AspNetCore.WebUtilities +@using System.Text +@using IO = System.IO +@inject IJSRuntime JSRuntime +@inject HttpClient Http +@inject NavigationManager NavigationManager; diff --git a/server-side/Controllers/DocumentEditorController.cs b/server-side/Controllers/DocumentEditorController.cs index 79f85cd..c1333dc 100644 --- a/server-side/Controllers/DocumentEditorController.cs +++ b/server-side/Controllers/DocumentEditorController.cs @@ -12,13 +12,15 @@ using Syncfusion.DocIORenderer; using Syncfusion.Pdf; using Syncfusion.Blazor.PdfViewer; using DocumentExplorer.Models; +using SkiaSharp; +using System.Text.Json; namespace DocumentExplorer.Controllers { [Route("api/[controller]")] [ApiController] public class DocumentEditorController : ControllerBase - { + { private string basePath; private string baseLocation; IWebHostEnvironment _hostingEnvironment; @@ -30,19 +32,16 @@ namespace DocumentExplorer.Controllers } [Route("Import")] - public string[] Import([FromBody] FileManagerDirectoryContent args) + public string Import([FromBody] FileManagerDirectoryContent args) { string fileLocation = this.baseLocation + args.Path.Replace("/", "\\"); - List returnArray = new List(); using (FileStream fs = new FileStream(fileLocation, FileMode.Open, FileAccess.Read)) { WordDocument document = WordDocument.Load(fs, GetImportFormatType(Path.GetExtension(fileLocation).ToLower())); - string json = Newtonsoft.Json.JsonConvert.SerializeObject(document); + string json = JsonSerializer.Serialize(document); document.Dispose(); - returnArray.Add(json); - return ConvertToImages(fs, returnArray, GetDocIOFormatType(Path.GetExtension(args.Path).ToLower())).ToArray(); - } - + return json; + } } private List ConvertToImages(FileStream fs, List returnStrings, Syncfusion.DocIO.FormatType type) { @@ -66,8 +65,20 @@ namespace DocumentExplorer.Controllers pdfExportImage.Load(outputStream); //Exports the PDF document pages into images - Bitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, pdfExportImage.PageCount-1); - foreach (Bitmap bitmap in bitmapimage) + SKBitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, pdfExportImage.PageCount - 1); + Bitmap[] bitmapImages = new Bitmap[bitmapimage.Length]; + + for (int i = 0; i < bitmapimage.Length; i++) + { + using (SKImage skImage = SKImage.FromBitmap(bitmapimage[i])) + using (SKData skData = skImage.Encode(SKEncodedImageFormat.Png, 100)) + using (System.IO.MemoryStream stream = new System.IO.MemoryStream(skData.ToArray())) + { + bitmapImages[i] = new Bitmap(stream); + } + } + + foreach (Bitmap bitmap in bitmapImages) { using (MemoryStream ms = new MemoryStream()) { @@ -91,7 +102,7 @@ namespace DocumentExplorer.Controllers } } - + private ImportFormatType GetImportFormatType(string format) { if (string.IsNullOrEmpty(format)) diff --git a/server-side/Controllers/FileManagerController.cs b/server-side/Controllers/FileManagerController.cs index 85df4e9..94ab4bd 100644 --- a/server-side/Controllers/FileManagerController.cs +++ b/server-side/Controllers/FileManagerController.cs @@ -22,50 +22,114 @@ namespace DocumentExplorer.Controllers { private PhysicalFileProvider operation; private string basePath; + string root = "wwwroot\\Files"; + string rootPath; + string virtualConnection; public FileManagerController(IWebHostEnvironment hostingEnvironment) { this.basePath = hostingEnvironment.ContentRootPath; this.operation = new PhysicalFileProvider(); - this.operation.RootFolder(this.basePath + "\\wwwroot\\Files"); // Data\\Files denotes in which files and folders are available. + if (basePath.EndsWith("\\")) + this.rootPath = this.basePath + this.root; + else + this.rootPath = this.basePath + "\\" + this.root; + this.operation.RootFolder(rootPath); } // Processing the File Manager operations [Route("FileOperations")] public object FileOperations([FromBody] FileManagerCustomContent args) { + + args.RootType = HttpContext.Request.Headers["RootType"]; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + if (args.Path == "/Files/") + { + args.Path = "/"; + } + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + + if (basePath.EndsWith("\\")) + { + virtualConnection = this.basePath + "wwwroot\\VirtualConnections"; + } + else + { + virtualConnection = this.basePath + "\\wwwroot\\VirtualConnections"; + } + DateTime currentTime = DateTime.Now; + DateTime deletionThreshold = currentTime.AddHours(-24); + DirectoryInfo virtualDirectoryInfo = new DirectoryInfo(virtualConnection); + + if (Directory.Exists(virtualConnection) && virtualDirectoryInfo.LastWriteTime <= deletionThreshold) + { + Directory.Delete(virtualConnection, true); + } + if (!Directory.Exists(virtualConnection)) + { + //Create virtual root directory + Directory.CreateDirectory(virtualConnection); + } + string userID = virtualConnection + "\\" + connectionId + "\\Files"; + string virtualUser = virtualConnection + "\\" + connectionId + "\\User"; + string virtualTrash = virtualConnection + "\\" + connectionId + "\\Trash"; + if (!Directory.Exists(userID)) + { + Directory.CreateDirectory(userID); + Directory.CreateDirectory(virtualUser); + Directory.CreateDirectory(virtualTrash); + CopyFolder(rootPath, userID); + CopyFolder(this.basePath + "\\wwwroot\\User", virtualUser); + CopyFolder(this.basePath + "\\wwwroot\\Trash", virtualTrash); + } + + //Set user directory as root + this.operation.RootFolder(userID); + + if (args.Action == "delete" || args.Action == "rename") + { + if ((args.TargetPath == null) && (args.Path == "")) + { + FileManagerResponse response = new FileManagerResponse(); + response.Error = new ErrorDetails { Code = "401", Message = "Restricted to modify the root folder." }; + return this.operation.ToCamelCase(response); + } + } + switch (args.Action) { // Add your custom action here case "read": - if ((args.RootType != null) && ((args.RootType == "Recent") /*|| (args.RootType == "Starred")*/)) + if ((args.RootType != null) && ((args.RootType == "Recent"))) { FileManagerResponse result1 = this.operation.Search(args.Path, "*", args.ShowHiddenItems, false); - result1 = FilterRecentFiles(result1); - return AddStarDetails(result1); - } - else if ((args.RootType != null) && (args.RootType == "Starred")) - { - return FilterStarred(this.operation.Search(args.Path, "*", args.ShowHiddenItems, false)); + return FilterRecentFiles(result1); } else { - return AddStarDetails(this.operation.GetFiles(args.Path, args.ShowHiddenItems)); + return this.operation.ToCamelCase(this.operation.GetFiles(args.Path, args.ShowHiddenItems)); } case "delete": + +#if Publish + FileManagerResponse deleteResponse = new FileManagerResponse(); + deleteResponse.Error = new ErrorDetails() { Code = "401", Message = "Restricted to perform this action" }; + return this.operation.ToCamelCase(deleteResponse); +#else FileManagerDirectoryContent[] items1 = args.Data; string[] names1 = args.Names; - for (var i = 0; i < items1.Length; i++) - { - names1[i] = ((items1[i].FilterPath + items1[i].Name).Substring(1)); - RemoveStarred(names1[i]); - } - return this.operation.ToCamelCase(MoveToTrash(args.Data)); + return this.operation.ToCamelCase(MoveToTrash(args.Data, connectionId, virtualConnection, virtualUser)); +#endif case "copy": case "move": FileManagerResponse response = new FileManagerResponse(); response.Error = new ErrorDetails() { Code = "401", Message = "Restricted to perform this action" }; return this.operation.ToCamelCase(response); case "details": - if ((args.RootType != null) && ((args.RootType == "Recent") || (args.RootType == "Starred"))) + if ((args.RootType != null) && ((args.RootType == "Recent"))) { FileManagerDirectoryContent[] items = args.Data; string[] names = args.Names; @@ -87,16 +151,11 @@ namespace DocumentExplorer.Controllers if ((args.RootType != null) && ((args.RootType == "Recent"))) { FileManagerResponse result1 = this.operation.Search(args.Path, args.SearchString, args.ShowHiddenItems, args.CaseSensitive); - result1 = FilterRecentFiles(result1); - return AddStarDetails(result1); - } - else if ((args.RootType != null) && (args.RootType == "Starred")) - { - return FilterStarred(this.operation.Search(args.Path, args.SearchString, args.ShowHiddenItems, args.CaseSensitive)); + return FilterRecentFiles(result1); } else { - return AddStarDetails(this.operation.Search(args.Path, args.SearchString, args.ShowHiddenItems, args.CaseSensitive)); + return this.operation.ToCamelCase(this.operation.Search(args.Path, args.SearchString, args.ShowHiddenItems, args.CaseSensitive)); } case "rename": // Path - Current path of the renamed file; Name - Old file name; NewName - New file name @@ -121,13 +180,13 @@ namespace DocumentExplorer.Controllers result.Files = allFiles; return result; } - public FileManagerResponse MoveToTrash(FileManagerDirectoryContent[] dataArray) + public FileManagerResponse MoveToTrash(FileManagerDirectoryContent[] dataArray, string userId, String virtualConnection, string virtualUser) { - string jsonPath = this.basePath + "\\wwwroot\\User\\trash.json"; + string jsonPath = virtualUser + "\\trash.json"; string jsonData = System.IO.File.ReadAllText(jsonPath); List DeletedFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); PhysicalFileProvider trashOperation = new PhysicalFileProvider(); - string root = this.basePath + "\\wwwroot"; + string root = virtualConnection + "\\" + userId; trashOperation.RootFolder(root); List deletedFiles = new List(); foreach (FileManagerDirectoryContent data in dataArray) @@ -158,59 +217,6 @@ namespace DocumentExplorer.Controllers System.IO.File.WriteAllText(jsonPath, jsonData); return new FileManagerResponse() { Files = deletedFiles }; } - public string AddStarDetails(FileManagerResponse value) - { - string jsonPath = this.basePath + "\\wwwroot\\User\\star.json"; - string jsonData = System.IO.File.ReadAllText(jsonPath); - List starredFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); - FileResponse readResponse = new FileResponse(); - readResponse.CWD = value.CWD; - readResponse.Files = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(value.Files)); - foreach (FileManagerCustomContent file in readResponse.Files) - { - file.FilterPath = file.FilterPath.Replace(Path.DirectorySeparatorChar, '/'); - file.Starred = starredFiles.Contains(file.FilterPath + file.Name); - } - readResponse.Details = value.Details; - readResponse.Error = value.Error; - return JsonConvert.SerializeObject(readResponse, new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }); - } - public string FilterStarred(FileManagerResponse value) - { - string jsonPath = this.basePath + "\\wwwroot\\User\\star.json"; - string jsonData = System.IO.File.ReadAllText(jsonPath); - List starredFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); - FileResponse readResponse = new FileResponse(); - readResponse.CWD = value.CWD; - List files = new List(); - List allFiles = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(value.Files)); - foreach (FileManagerCustomContent file in allFiles) - { - file.FilterPath = file.FilterPath.Replace(Path.DirectorySeparatorChar, '/'); - if (starredFiles.Contains(file.FilterPath + file.Name)) - { - file.Starred = true; - files.Add(file); - } - } - readResponse.Files = files; - readResponse.Details = value.Details; - readResponse.Error = value.Error; - return JsonConvert.SerializeObject(readResponse, new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy() } }); - } - public void RemoveStarred(string filePath) - { - string jsonPath = this.basePath + "\\wwwroot\\User\\star.json"; - string jsonData = System.IO.File.ReadAllText(jsonPath); - List starredFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); - string path = filePath.Replace(Path.DirectorySeparatorChar, '/'); - if (starredFiles.Contains(path)) - { - starredFiles.Remove(path); - } - jsonData = JsonConvert.SerializeObject(starredFiles); - System.IO.File.WriteAllText(jsonPath, jsonData); - } [Route("Upload")] public IActionResult Upload(string path, IList uploadFiles, string action) { @@ -220,9 +226,21 @@ namespace DocumentExplorer.Controllers Response.ContentType = "application/json; charset=utf-8"; Response.StatusCode = 403; Response.HttpContext.Features.Get().ReasonPhrase = "The upload functionality is restricted in this online demo. To test this demo application with upload functionality, please download the source code from the GitHub location (https://github.com/syncfusion/blazor-showcase-document-explorer) and run it."; + return Content("The upload functionality is restricted in this online demo. To test this demo application with upload functionality, please download the source code from the GitHub location (https://github.com/syncfusion/blazor-showcase-document-explorer) and run it."); #else + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } FileManagerResponse uploadResponse; - uploadResponse = operation.Upload(path, uploadFiles, action, null); + PhysicalFileProvider uploadOperation = new PhysicalFileProvider(); + string basePath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId; + string userID = this.basePath + "wwwroot\\VirtualConnections\\" + connectionId + "\\Files"; + uploadOperation.RootFolder(userID); + uploadResponse = operation.Upload(path, uploadFiles, action, basePath, null); if (uploadResponse.Error != null) { Response.Clear(); @@ -230,8 +248,8 @@ namespace DocumentExplorer.Controllers Response.StatusCode = Convert.ToInt32(uploadResponse.Error.Code); Response.HttpContext.Features.Get().ReasonPhrase = uploadResponse.Error.Message; } -#endif return Content(""); +#endif } [Route("Download")] @@ -250,7 +268,15 @@ namespace DocumentExplorer.Controllers [Route("ToggleStarred")] public IActionResult ToggleStarred([FromBody] FileManagerCustomContent args) { - string jsonPath = this.basePath + "\\wwwroot\\User\\star.json"; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + string basePath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId +"\\User"; + string jsonPath = basePath + "\\star.json"; StreamReader reader = new StreamReader(jsonPath); string jsonData = reader.ReadToEnd(); reader.Dispose(); @@ -275,6 +301,26 @@ namespace DocumentExplorer.Controllers return this.operation.GetImage(args.Path, args.Id, false, null, null); } + private void CopyFolder(string source, string destination) + { + if (!Directory.Exists(destination)) + { + Directory.CreateDirectory(destination); + } + + foreach (var file in Directory.EnumerateFiles(source)) + { + var dest = Path.Combine(destination, Path.GetFileName(file)); + System.IO.File.Copy(file, dest); + } + + foreach (var folder in Directory.EnumerateDirectories(source)) + { + var dest = Path.Combine(destination, Path.GetFileName(folder)); + CopyFolder(folder, dest); + } + } + public class FileManagerCustomContent : FileManagerDirectoryContent { public string RootType { get; set; } diff --git a/server-side/Controllers/PresentationController.cs b/server-side/Controllers/PresentationController.cs index 15d2601..4692c86 100644 --- a/server-side/Controllers/PresentationController.cs +++ b/server-side/Controllers/PresentationController.cs @@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Mvc; using DocumentExplorer.Models.FileManager; using Syncfusion.Pdf; using Syncfusion.Presentation; -using Syncfusion.PresentationToPdfConverter; +using Syncfusion.PresentationRenderer; namespace DocumentExplorer.Controllers { diff --git a/server-side/Controllers/PreviewController.cs b/server-side/Controllers/PreviewController.cs index ca705b9..a02365f 100644 --- a/server-side/Controllers/PreviewController.cs +++ b/server-side/Controllers/PreviewController.cs @@ -15,6 +15,8 @@ using Syncfusion.Blazor.PdfViewer; using Syncfusion.Presentation; using Syncfusion.PresentationRenderer; using DocumentExplorer.Models; +using SkiaSharp; +using Microsoft.AspNetCore.Http; namespace DocumentExplorer.Controllers { @@ -28,13 +30,21 @@ namespace DocumentExplorer.Controllers { basePath = hostingEnvironment.ContentRootPath; operation = new PhysicalFileProvider(); - operation.RootFolder(this.basePath + "\\wwwroot\\Files"); // Data\\Files denotes in which files and folders are available. + operation.RootFolder(this.basePath + "\\wwwroot\\VirtualConnections\\"); // Data\\Files denotes in which files and folders are available. } [Route("GetPreview")] public string GetPreview([FromBody] FileManagerDirectoryContent args) { - string baseFolder = this.basePath + "\\wwwroot\\Files"; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + string baseFolder = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId + "\\Files"; + this.operation.RootFolder(baseFolder); try { String fullPath = baseFolder + args.Path; @@ -49,9 +59,20 @@ namespace DocumentExplorer.Controllers //Loads the PDF document pdfExportImage.Load(fileStream); //Exports the PDF document pages into images - Bitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, 0); - imageStream = new MemoryStream(); - bitmapimage[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); + SkiaSharp.SKBitmap[] skBitmaps = pdfExportImage.ExportAsImage(0, 0); + System.Drawing.Bitmap[] bitmapImages = new System.Drawing.Bitmap[skBitmaps.Length]; + + for (int i = 0; i < skBitmaps.Length; i++) + { + using (SKImage skImage = SKImage.FromBitmap(skBitmaps[i])) + using (SKData skData = skImage.Encode(SKEncodedImageFormat.Png, 100)) + using (System.IO.MemoryStream stream = new System.IO.MemoryStream(skData.ToArray())) + { + bitmapImages[i] = new System.Drawing.Bitmap(stream); + } + } + imageStream = new MemoryStream(); + bitmapImages[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); imageStream.Position = 0; pdfExportImage.Dispose(); fileStream.Close(); @@ -87,9 +108,21 @@ namespace DocumentExplorer.Controllers //Loads the PDF document pdfExportImage.Load(outputStream); //Exports the PDF document pages into images - Bitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, 0); + SKBitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, 0); + Bitmap[] bitmapImages = new Bitmap[bitmapimage.Length]; + + for (int i = 0; i < bitmapimage.Length; i++) + { + using (SKImage skImage = SKImage.FromBitmap(bitmapimage[i])) + using (SKData skData = skImage.Encode(SKEncodedImageFormat.Png, 100)) + using (System.IO.MemoryStream stream = new System.IO.MemoryStream(skData.ToArray())) + { + bitmapImages[i] = new Bitmap(stream); + } + } + imageStream = new MemoryStream(); - bitmapimage[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); + bitmapImages[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); imageStream.Position = 0; fileStream.Close(); diff --git a/server-side/Controllers/SharedFilesController.cs b/server-side/Controllers/SharedFilesController.cs index d3f1b95..687499a 100644 --- a/server-side/Controllers/SharedFilesController.cs +++ b/server-side/Controllers/SharedFilesController.cs @@ -22,6 +22,7 @@ using Syncfusion.PresentationRenderer; using System.Drawing; using Microsoft.AspNetCore.Cors; using DocumentExplorer.Models; +using SkiaSharp; namespace DocumentExplorer.Controllers { @@ -42,6 +43,10 @@ namespace DocumentExplorer.Controllers [Route("FileOperations")] public object FileOperations([FromBody] FileManagerFilterContent args) { + if (args.Path == "/Files/") + { + args.Path = "/"; + } switch (args.Action) { // Add your custom action here @@ -106,9 +111,20 @@ namespace DocumentExplorer.Controllers //Loads the PDF document pdfExportImage.Load(fileStream); //Exports the PDF document pages into images - Bitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, 0); + SkiaSharp.SKBitmap[] skBitmaps = pdfExportImage.ExportAsImage(0, 0); + System.Drawing.Bitmap[] bitmapImages = new System.Drawing.Bitmap[skBitmaps.Length]; + + for (int i = 0; i < skBitmaps.Length; i++) + { + using (SKImage skImage = SKImage.FromBitmap(skBitmaps[i])) + using (SKData skData = skImage.Encode(SKEncodedImageFormat.Png, 100)) + using (System.IO.MemoryStream stream = new System.IO.MemoryStream(skData.ToArray())) + { + bitmapImages[i] = new System.Drawing.Bitmap(stream); + } + } imageStream = new MemoryStream(); - bitmapimage[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); + bitmapImages[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); imageStream.Position = 0; pdfExportImage.Dispose(); fileStream.Close(); @@ -137,9 +153,20 @@ namespace DocumentExplorer.Controllers //Loads the PDF document pdfExportImage.Load(outputStream); //Exports the PDF document pages into images - Bitmap[] bitmapimage = pdfExportImage.ExportAsImage(0, 0); + SkiaSharp.SKBitmap[] skBitmaps = pdfExportImage.ExportAsImage(0, 0); + System.Drawing.Bitmap[] bitmapImages = new System.Drawing.Bitmap[skBitmaps.Length]; + + for (int i = 0; i < skBitmaps.Length; i++) + { + using (SKImage skImage = SKImage.FromBitmap(skBitmaps[i])) + using (SKData skData = skImage.Encode(SKEncodedImageFormat.Png, 100)) + using (System.IO.MemoryStream stream = new System.IO.MemoryStream(skData.ToArray())) + { + bitmapImages[i] = new System.Drawing.Bitmap(stream); + } + } imageStream = new MemoryStream(); - bitmapimage[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); + bitmapImages[0].Save(imageStream, System.Drawing.Imaging.ImageFormat.Png); imageStream.Position = 0; fileStream.Close(); diff --git a/server-side/Controllers/TrashController.cs b/server-side/Controllers/TrashController.cs index fd32eb3..642294a 100644 --- a/server-side/Controllers/TrashController.cs +++ b/server-side/Controllers/TrashController.cs @@ -22,11 +22,10 @@ namespace DocumentExplorer.Controllers private string basePath; private string baseLocation; - public TrashController(IWebHostEnvironment hostingEnvironment) { this.basePath = hostingEnvironment.ContentRootPath; - this.baseLocation = this.basePath + "\\wwwroot"; + this.baseLocation = this.basePath + "\\wwwroot\\VirtualConnections\\"; this.operation = new PhysicalFileProvider(); } @@ -34,6 +33,10 @@ namespace DocumentExplorer.Controllers [Route("FileOperations")] public object FileOperations([FromBody] ReadArgs args) { + if (args.Path == "/Files/") + { + args.Path = "/"; + } try { switch (args.Action) @@ -72,9 +75,16 @@ namespace DocumentExplorer.Controllers public FileManagerResponse GetFiles() { + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } FileManagerResponse readResponse = new FileManagerResponse(); FileManagerDirectoryContent cwd = new FileManagerDirectoryContent(); - String fullPath = (this.baseLocation + "/Trash"); + String fullPath = (this.baseLocation + connectionId + "/Trash"); DirectoryInfo directory = new DirectoryInfo(fullPath); cwd.Name = "Trash"; cwd.Size = 0; @@ -86,7 +96,7 @@ namespace DocumentExplorer.Controllers cwd.FilterPath = "/"; cwd.Permission = null; readResponse.CWD = cwd; - string jsonPath = this.basePath + "\\wwwroot\\User\\trash.json"; + string jsonPath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId +"\\User\\trash.json"; string jsonData = System.IO.File.ReadAllText(jsonPath); List DeletedFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); List files = new List(); @@ -99,7 +109,14 @@ namespace DocumentExplorer.Controllers } public FileManagerResponse GetDetails(FileManagerDirectoryContent[] files) { - this.operation.RootFolder(this.baseLocation + "\\Trash"); + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + this.operation.RootFolder(this.baseLocation + connectionId + "\\Trash"); FileManagerResponse response; string[] names = new string[files.Length]; string responseName = ""; @@ -117,8 +134,15 @@ namespace DocumentExplorer.Controllers } public FileManagerResponse DeleteFiles(FileManagerDirectoryContent[] files) { - this.operation.RootFolder(this.baseLocation); - string jsonPath = this.basePath + "\\wwwroot\\User\\trash.json"; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + this.operation.RootFolder(this.baseLocation + connectionId); + string jsonPath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId + "\\User\\trash.json"; string jsonData = System.IO.File.ReadAllText(jsonPath); List responseFiles =new List(); List DeletedFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); @@ -126,7 +150,7 @@ namespace DocumentExplorer.Controllers { TrashContents trashFile = DeletedFiles.Find(x => (x.Container.Equals(file.Id))); string trashPath = "/Trash/" + trashFile.Container; - DeleteDirectory(this.baseLocation + trashPath); + DeleteDirectory(this.baseLocation + connectionId + trashPath); responseFiles.Add(trashFile.Data); DeletedFiles.Remove(trashFile); } @@ -137,9 +161,16 @@ namespace DocumentExplorer.Controllers [Route("EmptyTrash")] public IActionResult EmptyTrash() { - string jsonPath = this.basePath + "\\wwwroot\\User\\trash.json"; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + string jsonPath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId + "\\User\\trash.json"; string jsonData =""; - string[] dirs = Directory.GetDirectories(this.baseLocation); + string[] dirs = Directory.GetDirectories(this.baseLocation + connectionId); foreach (string dir in dirs) { DeleteDirectory(dir); @@ -151,8 +182,15 @@ namespace DocumentExplorer.Controllers [Route("Restore")] public IActionResult Restore([FromBody] FileManagerDirectoryContent[] files) { - this.operation.RootFolder(this.baseLocation); - string jsonPath = this.basePath + "\\wwwroot\\User\\trash.json"; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + this.operation.RootFolder(this.baseLocation + connectionId); + string jsonPath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId + "\\User\\trash.json"; string jsonData = System.IO.File.ReadAllText(jsonPath); string responseString = ""; List DeletedFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); @@ -164,7 +202,7 @@ namespace DocumentExplorer.Controllers FileManagerResponse response = this.operation.Move(trashPath, fileLocation, new string[] { trashFile.Name }, new string[] { trashFile.Name }, null, null); if ((response.Error == null)) { - DeleteDirectory(this.baseLocation + trashPath); + DeleteDirectory(this.baseLocation + connectionId + trashPath); DeletedFiles.Remove(trashFile); responseString = "Restored"; } @@ -180,8 +218,15 @@ namespace DocumentExplorer.Controllers public FileManagerResponse SearchFiles(string value, bool caseSensitive) { - this.operation.RootFolder(this.baseLocation); - string jsonPath = this.basePath + "\\wwwroot\\User\\trash.json"; + string connectionId = HttpContext.Session.GetString("ConnectionId"); + + if (string.IsNullOrEmpty(connectionId)) + { + connectionId = Guid.NewGuid().ToString(); // Generate a new unique identifier + HttpContext.Session.SetString("ConnectionId", connectionId); // Store it in session + } + this.operation.RootFolder(this.baseLocation + connectionId); + string jsonPath = this.basePath + "\\wwwroot\\VirtualConnections\\" + connectionId + "\\User\\trash.json"; string jsonData = System.IO.File.ReadAllText(jsonPath); List DeletedFiles = JsonConvert.DeserializeObject>(jsonData) ?? new List(); List searchFiles = DeletedFiles.FindAll(x => new Regex(WildcardToRegex(value), (caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase)).IsMatch(x.Name)); diff --git a/server-side/Data/PhysicalFileProvider.cs b/server-side/Data/PhysicalFileProvider.cs index b40e9af..2f5e72d 100644 --- a/server-side/Data/PhysicalFileProvider.cs +++ b/server-side/Data/PhysicalFileProvider.cs @@ -617,13 +617,21 @@ namespace DocumentExplorer.Data // Moves file(s) or folder(s). public virtual FileManagerResponse Move(string path, string targetPath, string[] names, string[] renameFiles, FileManagerDirectoryContent targetData, params FileManagerDirectoryContent[] data) - { + { FileManagerResponse moveResponse = new FileManagerResponse(); try { + string validatePath; + validatePath = Path.Combine(contentRootPath + path); + if (Path.GetFullPath(validatePath) != GetFilePath(validatePath)) + { + throw new UnauthorizedAccessException("Access denied for Directory-traversal"); + } string result = String.Empty; if (renameFiles == null) + { renameFiles = new string[0]; + } string physicalPath = GetPath(path); for (int i = 0; i < names.Length; i++) { @@ -641,6 +649,7 @@ namespace DocumentExplorer.Data accessMessage = PathPermission.Message; throw new UnauthorizedAccessException("'" + this.getFileNameFromPath(this.rootName + targetPath) + "' is not accessible. You need permission to perform the writeContents action."); } + List existFiles = new List(); List missingFiles = new List(); List movedFiles = new List(); @@ -654,20 +663,38 @@ namespace DocumentExplorer.Data path = tempPath + names[i].Substring(0, name + 1); names[i] = names[i].Substring(name + 1); } - else path = tempPath; + else + { + path = tempPath; + } string itemPath = Path.Combine(contentRootPath + path, names[i]); + if (Path.GetFullPath(itemPath) != GetFilePath(itemPath) + names[i]) + { + throw new UnauthorizedAccessException("Access denied for Directory-traversal"); + } if (Directory.Exists(itemPath) || File.Exists(itemPath)) { if ((File.GetAttributes(itemPath) & FileAttributes.Directory) == FileAttributes.Directory) { string directoryName = names[i]; string oldPath = Path.Combine(contentRootPath + path, directoryName); + if (Path.GetFullPath(oldPath) != GetFilePath(oldPath) + directoryName) + { + throw new UnauthorizedAccessException("Access denied for Directory-traversal"); + } string newPath = Path.Combine(contentRootPath + targetPath, directoryName); + if (Path.GetFullPath(newPath) != GetFilePath(newPath) + directoryName) + { + throw new UnauthorizedAccessException("Access denied for Directory-traversal"); + } bool exist = Directory.Exists(newPath); if (exist) { int index = -1; - if (renameFiles.Length > 0) index = Array.FindIndex(renameFiles, row => row.Contains(directoryName)); + if (renameFiles.Length > 0) + { + index = Array.FindIndex(renameFiles, row => row.Contains(directoryName)); + } if ((newPath == oldPath) || (index != -1)) { newPath = DirectoryRename(newPath); @@ -683,7 +710,10 @@ namespace DocumentExplorer.Data detail.PreviousName = names[i]; movedFiles.Add(detail); } - else existFiles.Add(fullName); + else + { + existFiles.Add(fullName); + } } else { @@ -694,7 +724,6 @@ namespace DocumentExplorer.Data { result = DeleteDirectory(oldPath); if (result != String.Empty) { break; } - } FileManagerDirectoryContent detail = GetFileDetails(newPath); detail.PreviousName = names[i]; @@ -705,7 +734,15 @@ namespace DocumentExplorer.Data { string fileName = names[i]; string oldPath = Path.Combine(contentRootPath + path, fileName); + if (Path.GetFullPath(oldPath) != GetFilePath(oldPath) + fileName) + { + throw new UnauthorizedAccessException("Access denied for Directory-traversal"); + } string newPath = Path.Combine(contentRootPath + targetPath, fileName); + if (Path.GetFullPath(newPath) != GetFilePath(newPath) + fileName) + { + throw new UnauthorizedAccessException("Access denied for Directory-traversal"); + } bool fileExist = File.Exists(newPath); try { @@ -714,24 +751,35 @@ namespace DocumentExplorer.Data { int index = -1; if (renameFiles.Length > 0) + { index = Array.FindIndex(renameFiles, row => row.Contains(fileName)); + } if ((newPath == oldPath) || (index != -1)) { newPath = FileRename(newPath, fileName); File.Copy(oldPath, newPath); bool isExist = File.Exists(oldPath); - if (isExist) File.Delete(oldPath); + if (isExist) + { + File.Delete(oldPath); + } FileManagerDirectoryContent detail = GetFileDetails(newPath); detail.PreviousName = names[i]; movedFiles.Add(detail); } - else existFiles.Add(fullName); + else + { + existFiles.Add(fullName); + } } else { File.Copy(oldPath, newPath); bool isExist = File.Exists(oldPath); - if (isExist) File.Delete(oldPath); + if (isExist) + { + File.Delete(oldPath); + } FileManagerDirectoryContent detail = GetFileDetails(newPath); detail.PreviousName = names[i]; movedFiles.Add(detail); @@ -742,13 +790,20 @@ namespace DocumentExplorer.Data { if (e.GetType().Name == "UnauthorizedAccessException") { - result = newPath; break; + result = newPath; + break; + } + else + { + throw e; } - else throw e; } } } - else missingFiles.Add(names[i]); + else + { + missingFiles.Add(names[i]); + } } moveResponse.Files = movedFiles; if (result != String.Empty) @@ -768,11 +823,17 @@ namespace DocumentExplorer.Data er.Message = "File Already Exists"; moveResponse.Error = er; } - if (missingFiles.Count == 0) return moveResponse; + if (missingFiles.Count == 0) + { + return moveResponse; + } else { string namelist = missingFiles[0]; - for (int k = 1; k < missingFiles.Count; k++) { namelist = namelist + ", " + missingFiles[k]; } + for (int k = 1; k < missingFiles.Count; k++) + { + namelist = namelist + ", " + missingFiles[k]; + } throw new FileNotFoundException(namelist + " not found in given location."); } } @@ -783,7 +844,7 @@ namespace DocumentExplorer.Data Message = e.Message.ToString(), Code = e.Message.ToString().Contains("is not accessible. You need permission") ? "401" : "417", FileExists = moveResponse.Error?.FileExists - }; + }; if ((er.Code == "401") && !string.IsNullOrEmpty(accessMessage)) { er.Message = accessMessage; } moveResponse.Error = er; return moveResponse; @@ -908,7 +969,7 @@ namespace DocumentExplorer.Data } // Uploads the file(s) to the files system. - public virtual FileManagerResponse Upload(string path, IList uploadFiles, string action, params FileManagerDirectoryContent[] data) + public virtual FileManagerResponse Upload(string path, IList uploadFiles, string action,string basePath, params FileManagerDirectoryContent[] data) { FileManagerResponse uploadResponse = new FileManagerResponse(); try @@ -925,7 +986,7 @@ namespace DocumentExplorer.Data if (uploadFiles != null) { string name = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"'); - string fullName = Path.Combine((this.contentRootPath + path), name); + string fullName = Path.Combine((basePath + "\\Files\\"), name); if (action == "save") { if (!System.IO.File.Exists(fullName)) diff --git a/server-side/DocumentExplorer.csproj b/server-side/DocumentExplorer.csproj index a48e744..679dd06 100644 --- a/server-side/DocumentExplorer.csproj +++ b/server-side/DocumentExplorer.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + net8.0 DocumentExplorer Debug;Release;Publish @@ -10,14 +10,41 @@ TRACE;Publish + + False + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server-side/DocumentExplorer.sln b/server-side/DocumentExplorer.sln deleted file mode 100644 index 047c082..0000000 --- a/server-side/DocumentExplorer.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29521.150 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocumentExplorer", "DocumentExplorer.csproj", "{097B67E7-41B9-479E-B1D3-8B8939534FCF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Publish|Any CPU = Publish|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {097B67E7-41B9-479E-B1D3-8B8939534FCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {097B67E7-41B9-479E-B1D3-8B8939534FCF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {097B67E7-41B9-479E-B1D3-8B8939534FCF}.Publish|Any CPU.ActiveCfg = Publish|Any CPU - {097B67E7-41B9-479E-B1D3-8B8939534FCF}.Publish|Any CPU.Build.0 = Publish|Any CPU - {097B67E7-41B9-479E-B1D3-8B8939534FCF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {097B67E7-41B9-479E-B1D3-8B8939534FCF}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {EB60F3A9-EB50-4F29-8AEF-414D8B206DC7} - EndGlobalSection -EndGlobal diff --git a/server-side/Models/FileManager/IFileProvider.cs b/server-side/Models/FileManager/IFileProvider.cs index cc60e7f..7abb7f3 100644 --- a/server-side/Models/FileManager/IFileProvider.cs +++ b/server-side/Models/FileManager/IFileProvider.cs @@ -34,7 +34,7 @@ namespace DocumentExplorer.Models.FileManager #if EJ2_DNX FileManagerResponse Upload(string path, IList uploadFiles, string action, params FileManagerDirectoryContent[] data); #else - FileManagerResponse Upload(string path, IList uploadFiles, string action, params FileManagerDirectoryContent[] data); + FileManagerResponse Upload(string path, IList uploadFiles, string action, string basePath, params FileManagerDirectoryContent[] data); #endif FileStreamResult GetImage(string path, string id, bool allowCompress, ImageSize size, params FileManagerDirectoryContent[] data); diff --git a/server-side/NuGet.config b/server-side/NuGet.config new file mode 100644 index 0000000..6ccf965 --- /dev/null +++ b/server-side/NuGet.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server-side/Pages/BottomToolbar.razor b/server-side/Pages/BottomToolbar.razor deleted file mode 100644 index cf3aec3..0000000 --- a/server-side/Pages/BottomToolbar.razor +++ /dev/null @@ -1,154 +0,0 @@ -@*@page "/bottomToolbar"*@ - -@using Syncfusion.Blazor.Navigations -@using Syncfusion.Blazor.Inputs - - - - - -@code{ - public int TotalPages { get; set; } = 0; - private bool NxtShowIcon { get; set; } - private bool PrevShowIcon { get; set; } - public int CurrentPageNumber { get; set; } = 1; - private string PrevItemDisable { get; set; } = ""; - private string NxtItemDisable { get; set; } = ""; - private string PreviousPageID { get; set; } = ""; - public bool ZoomInDisable { get; set; } - public bool ZoomOutDisable { get; set; } - public bool PreviousPageDisable { get; set; } = true; - public bool NextPageDisable { get; set; } - - public void Refresh() - { - StateHasChanged(); - } - - public async void Goto(Syncfusion.Blazor.Inputs.ChangeEventArgs args) - { - if (args.IsInteracted) - { - int page; - int.TryParse(args.Value.ToString(), out page); - await GotoPage.InvokeAsync(page); - } - } - - private async void ToolbarClick(ClickEventArgs args) - { - switch (args.Item.Id) - { - case "ShowHidePages": - await ShowHidePane.InvokeAsync(true); - break; - case "PreviousPage": - if (CurrentPageNumber > 1) - { - PreviousPageDisable = false; - NextPageDisable = false; - CurrentPageNumber--; - await GotoPage.InvokeAsync(CurrentPageNumber); - if (CurrentPageNumber == 1) - { - PreviousPageDisable = true; - } - } - break; - case "NextPage": - if (CurrentPageNumber < TotalPages) - { - NextPageDisable = false; - PreviousPageDisable = false; - CurrentPageNumber++; - await GotoPage.InvokeAsync(CurrentPageNumber); - if (CurrentPageNumber == TotalPages) - { - NextPageDisable = true; - } - } - break; - case "ZoomIn": - await ToolBarAction.InvokeAsync("ZoomIn"); - break; - case "ZoomOut": - await ToolBarAction.InvokeAsync("ZoomOut"); - break; - case "FullScreen": - await ToolBarAction.InvokeAsync("FullScreen"); - break; - case "Print": - await ToolBarAction.InvokeAsync("Print"); - break; - } - } - - [Parameter] - public EventCallback ShowHidePane { get; set; } - [Parameter] - public EventCallback GotoPage { get; set; } - [Parameter] - public EventCallback ToolBarAction { get; set; } -} diff --git a/server-side/Pages/ImageEditor.razor b/server-side/Pages/ImageEditor.razor new file mode 100644 index 0000000..ac4316b --- /dev/null +++ b/server-side/Pages/ImageEditor.razor @@ -0,0 +1,34 @@ +@page "/image-viewer" +@using Syncfusion.Blazor +@using Syncfusion.Blazor.ImageEditor + +
+ +
+
+ + + +
+@code { + SfImageEditor _imageEditor; + TopToolbar _topToolbar; + Index _indexDetails; + private void created() + { + var data = QueryHelpers.ParseQuery(NavigationManager.ToAbsoluteUri(NavigationManager.Uri).Query); + if (data.TryGetValue("fileName", out var fileName)) + { + _topToolbar.RootName = fileName.ToString(); + } + if (data.TryGetValue("imageUrl", out var imageUrl)) + { + string imageUrlString = imageUrl.ToString(); // Convert to string explicitly + _imageEditor.OpenAsync(imageUrlString); + } + } + private void BackClickHandler() + { + NavigationManager.NavigateTo(NavigationManager.BaseUri); + } +} diff --git a/server-side/Pages/Index.razor b/server-side/Pages/Index.razor index 9a9a28f..bab7ae2 100644 --- a/server-side/Pages/Index.razor +++ b/server-side/Pages/Index.razor @@ -5,15 +5,15 @@ @using Syncfusion.Blazor.Popups @using System.Text -
-
-
-
- - - -
+
+
+
+ + + +
+
@*Header Section*@ @@ -51,7 +51,7 @@ @*Content section*@
@*sidebar content*@ - @*user icon for resolution < 600px*@ @@ -100,7 +100,7 @@
@*file manager*@ - + - +
@@ -151,14 +151,16 @@ - +
@code { - - private SfFileManager _fileManager; + public string _currentImageUrl { get; set; } + public string _imageFileName { get; set; } + private SfFileManager _fileManager; private SfTreeView _treeObj; private SfSidebar _sidebar; private SfDialog _dialog; + public bool SidebarToggle = false; private bool ShowThumbnail = true; private bool _isThumbNailChange = false; private string[] _selectedTreeItem = new string[] { "1" }; @@ -175,15 +177,13 @@ private bool _isUnSupported = false; private string OverlayStyle { get; set; } = "overlayShow"; private string _fileName = ""; - private int _mapId = 0; - private int starid = 1; + private List _optionsData = new List() { new OptionsDataModel(){Name= "All Files", Id= "1", Select= true, Icon= "sf-icon-Allfiles"}, new OptionsDataModel(){Name= "Recent Files", Id= "2", Select= false, Icon= "sf-icon-RecentFiles" }, new OptionsDataModel(){Name= "Shared With Me", Select= false, Id= "3", Icon= "e-icons e-shared" }, - new OptionsDataModel(){Name= "Starred", Select= false, Id= "4", Icon= "sf-icon-Starred" }, - new OptionsDataModel(){Name= "Trash", Select= false, Id= "5", Icon= "sf-icon-Delete" }, - new OptionsDataModel(){Name= "About", Select= false, Id= "6", Icon= "sf-icon-About" } + new OptionsDataModel(){Name= "Trash", Select= false, Id= "4", Icon= "sf-icon-Delete" }, + new OptionsDataModel(){Name= "About", Select= false, Id= "5", Icon= "sf-icon-About" } }; private class OptionsDataModel { @@ -194,19 +194,27 @@ } private string Field { get; set; } = null; private string Path { get; set; } - private string[] SelectedItems { get; set; } + //private string[] SelectedItems { get; set; } private bool _treeSelectFlag = false; private string _treeNode = "1"; - private string[] _toolItems = new string[] { "Upload", "Delete", "Download", "Rename", "SortBy", "Refresh", "Selection", "View", "Details" }; - private string[] _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Star", "Rename", "|", "Details" }; + private string[] _toolItems = new string[] { + #if !Publish + "Upload", + #endif + "Delete", "Download", "Rename", "SortBy", "Refresh", "Selection", "View", "Details" }; + private string[] _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; private string[] _folderMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; - private string[] _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", "Upload", "|", "Details", "SelectAll" }; + private string[] _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", + #if !Publish + "Upload", + #endif + "|", "Details", "SelectAll" }; + private bool isImageOpen = false; protected override void OnInitialized() { _fileOverlayDisplay = "e-file-show-overlay"; Path = "/"; - SelectedItems = new string[] { }; if (QueryHelpers.ParseQuery(NavigationManager.ToAbsoluteUri(NavigationManager.Uri).Query).TryGetValue("path", out var pathparam)) { string tempPath = pathparam.First(); @@ -227,7 +235,6 @@ if (QueryHelpers.ParseQuery(NavigationManager.ToAbsoluteUri(NavigationManager.Uri).Query).TryGetValue("preview", out var param)) { SelectedFilename = param.First(); - SelectedItems = new string[] { SelectedFilename }; } } protected override void OnAfterRender(bool firstRender) @@ -235,7 +242,7 @@ OverlayStyle = "overlayHide"; if (!firstRender) { - if (_fileManager.IsRendered && SelectedPath != null & SelectedFilename != null) + if (_fileManager.EnableRtl && SelectedPath != null & SelectedFilename != null) { SelectedPath = SelectedFilename = null; _fileOverlayDisplay = "e-file-hide-overlay"; @@ -250,28 +257,31 @@ { _isUnSupported = false; } - public void Refresh() + public async void Refresh() { - _fileManager.Refresh(); + await _fileManager.RefreshFilesAsync(); } - private void TreeSelect(NodeSelectEventArgs args) + private async void TreeSelect(NodeSelectEventArgs args) { - _fileManager.ClearSelection(); - //To avoid file resfreshing if the selection change invloves shared Trash as showThumbNail change triggers which refreshFiles. + _selectedTreeItem[0] = _treeNode = args.NodeData.Id; + //To avoid file refreshing if the selection change involves shared Trash as showThumbNail change triggers which refreshFiles. _isThumbNailChange = (_treeNode == "5") || (args.NodeData.Id == "5"); ShowThumbnail = args.NodeData.Id != "5"; - //To avoid manual resfreshing if the selection change invloves shared files/Trash as ajax setting change triggered which refresh. - bool flag = (_treeNode == "3") || (_treeNode == "5") || (args.NodeData.Id == "3") || (args.NodeData.Id == "5"); - _selectedTreeItem[0] = _treeNode = args.NodeData.Id; + //To avoid manual refreshing if the selection change involves shared files/Trash as ajax setting change triggered which refresh. + bool flag = false; if (_treeSelectFlag) { _treeSelectFlag = false; return; } switch (_treeNode) { //Recent Files case "2": _toolItems = new string[] { "Download", "Rename", "SortBy", "Refresh", "Selection", "View", "Details" }; - _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Star", "Rename", "|", "Details" }; + _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; _folderMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; - _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", "Upload", "|", "Details", "SelectAll" }; + _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", + #if !Publish + "Upload", + #endif + "|", "Details", "SelectAll" }; Field = "Recent"; break; //Shared With Me @@ -282,16 +292,8 @@ _layoutMenu = new string[] { "SortBy", "|", "View", "|", "Refresh", "|", "Details", "|", "SelectAll" }; Field = "Shared"; break; - //Starred - case "4": - _toolItems = new string[] { "Delete", "Download", "Rename", "SortBy", "Refresh", "Selection", "View" }; - _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Star", "Rename", "|", "Details" }; - _folderMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; - _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", "Upload", "|", "SelectAll" }; - Field = "Starred"; - break; //Trash - case "5": + case "4": _toolItems = new string[] { "Delete", "SortBy", "Refresh", "Selection", "View", "Details" }; _fileMenu = new string[] { "Delete", "|", "Details", "|", "Restore", "EmptyTrash", "|", "SelectAll" }; _folderMenu = new string[] { "Download", "|", "Details", "|", "Restore", "EmptyTrash", "|", "SelectAll" }; @@ -299,15 +301,23 @@ Field = "Trash"; break; //About page - case "6": + case "5": NavigationManager.NavigateTo(NavigationManager.BaseUri + "about"); break; //All Files default: - _toolItems = new string[] { "Upload", "Delete", "Download", "Rename", "SortBy", "Refresh", "Selection", "View", "Details" }; - _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Star", "Rename", "|", "Details" }; + _toolItems = new string[] { + #if !Publish + "Upload", + #endif + "Delete", "Download", "Rename", "SortBy", "Refresh", "Selection", "View", "Details" }; + _fileMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; _folderMenu = new string[] { "Open", "|", "Delete", "Download", "Rename", "|", "Details" }; - _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", "Upload", "|", "Details", "SelectAll" }; + _layoutMenu = new string[] { "SortBy", "View", "Refresh", "|", "NewFolder", + #if !Publish + "Upload", + #endif + "|", "Details", "SelectAll" }; Field = "AllFiles"; break; } @@ -315,28 +325,37 @@ { //Reset the path to make the filter work from route path Path = "/"; - _fileManager.RefreshFiles(); + _fileManager.Path = "/"; + await _fileManager.RefreshFilesAsync(); } } private void BeforeSend(BeforeSendEventArgs args) { - if (_isThumbNailChange) { _isThumbNailChange = false; args.Cancel = true; return; } + if (_isThumbNailChange) + { + _isThumbNailChange = false; + } + if (args.Action != "Upload") { - string AjaxSettingsString = JsonConvert.SerializeObject(args.AjaxSettings); - Dictionary AjaxSettings = JsonConvert.DeserializeObject>(AjaxSettingsString); - string dataString = AjaxSettings["data"]; - Dictionary data = JsonConvert.DeserializeObject>(dataString); - data.Add("RootType", Field); - string modifiedDataString = JsonConvert.SerializeObject(data); - AjaxSettings["data"] = modifiedDataString; - string returnString = JsonConvert.SerializeObject(AjaxSettings); - args.AjaxSettings = JsonConvert.DeserializeObject(returnString); + if (args.HttpClientInstance.DefaultRequestHeaders.Contains("RootType")) + { + args.HttpClientInstance.DefaultRequestHeaders.Remove("RootType"); + } + //Pass the user token through FileManager HTTP client instance. + args.HttpClientInstance.DefaultRequestHeaders.Add("RootType", Field); + } + } + private async Task UploadClick(ToolbarClickEventArgs args) + { + if (args.Item.Text == "Upload" && (!args.Cancel)) + { + await JSRuntime.InvokeVoidAsync("alert", "This is an security purpose alert message."); } } private void HamburgerClick() { - _sidebar.Toggle(); + SidebarToggle = !SidebarToggle; } private void ToolbarClick(Syncfusion.Blazor.Navigations.ClickEventArgs args) { @@ -350,9 +369,9 @@ break; } } - private void NewClick() + private async void NewClick() { - _fileManager.CreateFolder(); + await _fileManager.CreateFolderAsync(); } private void SidebarOpen() { @@ -366,37 +385,46 @@ } private void PopupBefore(BeforePopupOpenCloseEventArgs args) { - _dialogCount++; - _popupVisibility = "e-hide-popup"; + if (args.PopupName == "Image Preview") + { + args.Cancel = true; + } + else + { + _dialogCount++; + _popupVisibility = "e-hide-popup"; + } + } + private void ImageLoadBefore(BeforeImageLoadEventArgs args) + { + if (isImageOpen) + { + string uri = NavigationManager.BaseUri; + _currentImageUrl = args.ImageUrl; + _imageFileName = args.FileDetails.Name; + Dictionary imageUrl = new Dictionary { { "imageUrl", _currentImageUrl }, { "fileName", _imageFileName } }; + NavigationManager.NavigateTo(QueryHelpers.AddQueryString(uri + "image-viewer/", imageUrl)); + isImageOpen = false; + } } private async void PopupOpened(PopupOpenCloseEventArgs args) { - await JSRuntime.InvokeVoidAsync("setDialogDrag", args.Element.ID); + // await JSRuntime.InvokeVoidAsync("setDialogDrag", args.Element.ID); } private void PopupClosed() { _dialogCount--; } - private async void MenuOpen(MenuOpenEventArgs args) + private async void MenuOpen(MenuOpenEventArgs args) { if ((Field != "Shared") && (Field != "Trash")) { - if (args.IsSubMenu && (args.MenuType == "Layout")) { return; } - foreach (MenuItemModel menu in args.Items) - { - if (menu.Text == "Star") - { - menu.IconCss = "sf-icon-Starred"; - } - } - MenuTargetId = _mapId.ToString(); _mapId++; - await args.Target.SetAttribute("data-mapId", MenuTargetId); MenuTargetData = JsonConvert.SerializeObject(args.FileDetails); } else if (Field == "Trash" && !args.IsSubMenu) { - foreach (MenuItemModel menu in args.Items) + foreach (Syncfusion.Blazor.FileManager.MenuItemModel menu in args.Items) { switch (menu.Text) { @@ -411,30 +439,11 @@ } } } - private async void MenuClick(MenuClickEventArgs args) + private async void MenuClick(MenuClickEventArgs args) { - if (args.Item.Id == _fileManager.ID + "_cm_star") - { - Dictionary[] fileDetails = JsonConvert.DeserializeObject[]>(MenuTargetData); - bool isGrid = (_fileManager.View == ViewType.Details); - string toggle = await JSRuntime.InvokeAsync("toggleStar", MenuTargetId, isGrid); - if (toggle == "Add") - { - ToggleStarred(fileDetails[0]["filterPath"] + fileDetails[0]["name"], true); - } - else if (toggle == "Remove") - { - ToggleStarred(fileDetails[0]["filterPath"] + fileDetails[0]["name"], false); - if (this.Field == "Starred") - { - await _fileManager.ClearSelection(); - await _fileManager.RefreshFiles(); - } - } - } if (args.Item.Id == _fileManager.ID + "_cm_restore") { - List files = await _fileManager.GetSelectedFiles(); + List files = _fileManager.GetSelectedFiles(); if (files.Count != 0) { Restore(args.FileDetails); } } if (args.Item.Id == _fileManager.ID + "_cm_restoreall") @@ -444,24 +453,34 @@ } private void ToolbarCreate(ToolbarCreateEventArgs args) { - List items = args.Items; - foreach (Syncfusion.Blazor.FileManager.ItemModel item in items) + List items = args.Items; + foreach (Syncfusion.Blazor.FileManager.ToolBarItemModel item in items) { if (item.Id == _fileManager.ID + "_tb_newfolder") { item.CssClass = "e-FM-newfolder"; } + +#if !Publish if (item.Id == _fileManager.ID + "_tb_upload") { item.CssClass = "e-FM-upload"; } + +#endif } } - private void FileOpen(FileOpenEventArgs args) + + private async void FileOpen(FileOpenEventArgs args) { + if (args.FileDetails.Type == ".jpg" || args.FileDetails.Type == ".png" || args.FileDetails.Type == ".dib" || args.FileDetails.Type == ".jpeg" + || args.FileDetails.Type == ".jpe" || args.FileDetails.Type == ".jfif" || args.FileDetails.Type == ".gif" || args.FileDetails.Type == ".tif" + || args.FileDetails.Type == ".tiff" || args.FileDetails.Type == ".ico") + isImageOpen = true; if (Field == "Trash") { args.Cancel = true; return; } string dataString = JsonConvert.SerializeObject(args.FileDetails); Dictionary fileDetails = JsonConvert.DeserializeObject>(dataString); - if (fileDetails["isFile"]) + if (fileDetails["IsFile"]) { - string filePath = (Field == "Shared" ? "SharedFiles" : "Files") + (fileDetails["filterPath"]); - Dictionary query = new Dictionary { { "preview", fileDetails["name"] }, { "path", filePath } }; + string filePath = (Field == "Shared" ? "SharedFiles" : "Files") + (fileDetails["FilterPath"]); + Dictionary query = new Dictionary { { "preview", fileDetails["Name"] }, { "path", filePath } }; + Dictionary imageUrl = new Dictionary { { "imageUrl", _currentImageUrl } }; string uri = NavigationManager.BaseUri; - switch (fileDetails["type"]) + switch (fileDetails["Type"]) { case Constants.Zip: NavigationManager.NavigateTo(QueryHelpers.AddQueryString(uri + "zip-viewer/", query)); @@ -488,9 +507,10 @@ case Constants.Tiff: case Constants.Png: case Constants.Ico: + break; default: - _fileName = fileDetails["name"]; + _fileName = fileDetails["Name"]; _isUnSupported = true; break; } @@ -501,15 +521,14 @@ { _treeSelectFlag = true; _selectedTreeItem = new string[] { "1" }; - _treeObj.DataBind(); args.Cancel = true; - string newPath = (fileDetails["filterPath"] + fileDetails["name"] + "/"); - Path = newPath.Replace('\\', '/'); - _fileManager.RefreshFiles(); } + string newPath = (fileDetails["FilterPath"] + fileDetails["Name"] + "/"); + Path = newPath.Replace('\\', '/'); + await _fileManager.RefreshFilesAsync(); } } - private async void FileLoad(FileLoadEventArgs args) + private async void FileLoad(FileLoadEventArgs args) { string dataString = JsonConvert.SerializeObject(args.FileDetails); Dictionary fileDetails = JsonConvert.DeserializeObject>(dataString); @@ -518,16 +537,18 @@ || fileDetails["type"] == Constants.Doc || fileDetails["type"] == Constants.Rtf || fileDetails["type"] == Constants.Txt || fileDetails["type"] == Constants.Pdf)) { string url = GetImageUrl(fileDetails); - DOM ele = args.Element; - string val = Convert.ToString((await ele.GetAttribute("data-uid"))); - await ele.AddClass(new string[] { "e-file-preview-image" }); - await JSRuntime.InvokeVoidAsync("setSpinnerPreview", val); + @* DOM ele = args.Element; *@ + @* string val = Convert.ToString((await ele.GetAttribute("data-uid"))); + await ele.AddClass(new string[] { "e-file-preview-image" }); *@ + @* await JSRuntime.InvokeVoidAsync("setSpinnerPreview", val); *@ string anm = fileDetails["name"]; string previewImage = await JSRuntime.InvokeAsync("getLocalCacheImage", anm); if (previewImage != null) { - await JSRuntime.InvokeVoidAsync("setPreview", val, previewImage); - } else { + @* await JSRuntime.InvokeVoidAsync("setPreview", val, previewImage); *@ + } + else + { HttpRequestMessage docrequest = new HttpRequestMessage(HttpMethod.Post, NavigationManager.BaseUri + "api/Preview/GetPreview"); docrequest.Content = new StringContent(JsonConvert.SerializeObject(new { Path = (fileDetails["filterPath"] + fileDetails["name"]) }), Encoding.UTF8, "application/json"); HttpResponseMessage docresponse = await Http.SendAsync(docrequest); @@ -538,7 +559,7 @@ { string name = fileDetails["name"]; await JSRuntime.InvokeVoidAsync("setLocalCacheImage", name, output); - await JSRuntime.InvokeVoidAsync("setPreview", val, output); + @* await JSRuntime.InvokeVoidAsync("setPreview", val, output); *@ } else { @@ -562,33 +583,11 @@ iconCss = "e-fe-pptx"; break; } - await JSRuntime.InvokeVoidAsync("revertToIconPreview", val, iconCss); + @* await JSRuntime.InvokeVoidAsync("revertToIconPreview", val, iconCss); *@ } } } } - // Adding Star - if ((args.Module == "LargeIconsView" || args.Module == "DetailsView") && (Field != "Shared") && (Field != "Trash") && (fileDetails["starred"])) - { - - DOM ele = args.Element; - string val = starid.ToString(); - starid++; - await ele.AddClass(new string[] { "e-file-star" }); - await ele.SetAttribute("data-starid", val); - bool isGrid = args.Module == "DetailsView"; - await JSRuntime.InvokeVoidAsync("showStar", val, isGrid); - - } - } - private async void ToggleStarred(string filePath, bool isStarred) - { - string url = NavigationManager.BaseUri + "api/FileManager/ToggleStarred"; - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url); - request.Content = new StringContent(JsonConvert.SerializeObject(new { Path = filePath, Starred = isStarred }), Encoding.UTF8, "application/json"); - HttpResponseMessage response = await Http.SendAsync(request); - string output = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) { } } private async void Restore(object files) { @@ -598,8 +597,8 @@ HttpResponseMessage response = await Http.SendAsync(request); if (response.IsSuccessStatusCode) { - await _fileManager.ClearSelection(); - await _fileManager.RefreshFiles(); + await _fileManager.ClearSelectionAsync(); + await _fileManager.RefreshFilesAsync(); } } private async void EmptyTrash() @@ -609,8 +608,8 @@ HttpResponseMessage response = await Http.SendAsync(request); if (response.IsSuccessStatusCode) { - await _fileManager.ClearSelection(); - await _fileManager.RefreshFiles(); + await _fileManager.ClearSelectionAsync(); + await _fileManager.RefreshFilesAsync(); } } private string GetImageUrl(Dictionary data) diff --git a/server-side/Pages/PdfViewer.razor b/server-side/Pages/PdfViewer.razor index ba26492..993e72b 100644 --- a/server-side/Pages/PdfViewer.razor +++ b/server-side/Pages/PdfViewer.razor @@ -17,13 +17,11 @@
-
- +
+ - -
@@ -39,10 +37,8 @@ private string ThumbnailStyle { get; set; } = "thumbnailShow"; private string DeMarginStyle { get; set; } = "e-word-right-layout"; private int Zoom { get; set; } - private bool _isThumbnailVisible = true; private SfPdfViewerServer _viewer; private TopToolbar _topToolbar; - private BottomToolbar _bottomToolbar; protected override void OnInitialized() { @@ -81,18 +77,16 @@ protected async void OnDocumentLoaded(LoadEventArgs args) { - await _viewer.OpenThumbnailPane(); - _bottomToolbar.TotalPages = await _viewer.GetPageCount(); DocumentName = ""; OverlayStyle = "overlayHide"; StateHasChanged(); } - private void BackClickHandler() + private async void BackClickHandler() { if (_viewer != null) { - _viewer.Unload(); + await _viewer.UnloadAsync(); } if (SubPath != null) { @@ -107,80 +101,12 @@ } } - private async void ToogleBottomToolBarVisibility() - { - await JSRuntime.InvokeVoidAsync("toggleBottomToolbarVisibility", "PdfView", _isThumbnailVisible); - } - - private async void ShowHideThumbnail() - { - await _viewer.OpenThumbnailPane(); - _isThumbnailVisible = !_isThumbnailVisible; - ToogleBottomToolBarVisibility(); - } - private async void Goto(int args) { - await _viewer.GoToPage(args); + await _viewer.GoToPageAsync(args); } - - private async void FileToolBar(string action) - { - switch (action) - { - case "PreviousPage": - await _viewer.GoToPreviousPage(); - break; - case "NextPage": - await _viewer.GoToNextPage(); - break; - case "ZoomIn": - await _viewer.ZoomIn(); - Zoom = await _viewer.GetZoomPercentage(); - if (_viewer.ZoomValue >= 400) - { - _bottomToolbar.ZoomInDisable = true; - } - _bottomToolbar.ZoomOutDisable = false; - StateHasChanged(); - break; - case "ZoomOut": - await _viewer.ZoomOut(); - Zoom = await _viewer.GetZoomPercentage(); - if (_viewer.ZoomValue <= 10) - { - _bottomToolbar.ZoomOutDisable = true; - } - _bottomToolbar.ZoomInDisable = false; - StateHasChanged(); - break; - case "FullScreen": - await JSRuntime.InvokeVoidAsync("fullScreen", "PdfView_pageViewContainer"); - break; - case "Print": - await _viewer.Print(); - break; - } - } - private void OnPageChanged(PageChangeEventArgs args) { - _bottomToolbar.CurrentPageNumber = (int)args.CurrentPageNumber; - if (args.CurrentPageNumber == _bottomToolbar.TotalPages) - { - _bottomToolbar.NextPageDisable = true; - _bottomToolbar.PreviousPageDisable = false; - } - if (args.CurrentPageNumber < _bottomToolbar.TotalPages && args.CurrentPageNumber != 1) - { - _bottomToolbar.NextPageDisable = false; - _bottomToolbar.PreviousPageDisable = false; - } - if (args.CurrentPageNumber == 1) - { - _bottomToolbar.PreviousPageDisable = true; - _bottomToolbar.NextPageDisable = false; - } StateHasChanged(); } } diff --git a/server-side/Pages/PresentationViewer.razor b/server-side/Pages/PresentationViewer.razor index 41db4f8..bb08f80 100644 --- a/server-side/Pages/PresentationViewer.razor +++ b/server-side/Pages/PresentationViewer.razor @@ -17,12 +17,11 @@
-
- +
+ -
@@ -34,10 +33,8 @@ private string SubPath { get; set; } private string Path { get; set; } private int Zoom { get; set; } - private bool _isThumbnailVisible = true; private SfPdfViewerServer _viewer; private TopToolbar _topToolbar; - private BottomToolbar _bottomToolbar; protected override void OnInitialized() { @@ -87,25 +84,23 @@ { Newtonsoft.Json.Linq.JArray jArray = (Newtonsoft.Json.Linq.JArray)JsonConvert.DeserializeObject(output); string sfdt = ((JValue)jArray[0]).Value.ToString(); - await _viewer.Load(sfdt, null); + await _viewer.LoadAsync(sfdt, null); } } } protected async void OnDocumentLoaded(LoadEventArgs args) { - await _viewer.OpenThumbnailPane(); - _bottomToolbar.TotalPages = await _viewer.GetPageCount(); DocumentName = ""; OverlayStyle = "overlayHide"; StateHasChanged(); } - private void BackClickHandler() + private async void BackClickHandler() { if (_viewer != null) { - _viewer.Unload(); + await _viewer.UnloadAsync(); } if (SubPath != null) { @@ -120,80 +115,13 @@ } } - private async void ToogleBottomToolBarVisibility() - { - await JSRuntime.InvokeVoidAsync("toggleBottomToolbarVisibility", "PptView", _isThumbnailVisible); - } - - private async void ShowHideThumbnail(bool args) - { - await _viewer.OpenThumbnailPane(); - _isThumbnailVisible = !_isThumbnailVisible; - ToogleBottomToolBarVisibility(); - } - private async void Goto(int args) { - await _viewer.GoToPage(args); - } - - private async void FileToolBar(string action) - { - switch (action) - { - case "PreviousPage": - await _viewer.GoToPreviousPage(); - break; - case "NextPage": - await _viewer.GoToNextPage(); - break; - case "ZoomIn": - await _viewer.ZoomIn(); - Zoom = await _viewer.GetZoomPercentage(); - if (_viewer.ZoomValue >= 400) - { - _bottomToolbar.ZoomInDisable = true; - } - _bottomToolbar.ZoomOutDisable = false; - StateHasChanged(); - break; - case "ZoomOut": - await _viewer.ZoomOut(); - Zoom = await _viewer.GetZoomPercentage(); - if (_viewer.ZoomValue <= 10) - { - _bottomToolbar.ZoomOutDisable = true; - } - _bottomToolbar.ZoomInDisable = false; - StateHasChanged(); - break; - case "FullScreen": - await JSRuntime.InvokeVoidAsync("fullScreen", "PptView_pageViewContainer"); - break; - case "Print": - await _viewer.Print(); - break; - } + await _viewer.GoToPageAsync(args); } private void OnPageChanged(PageChangeEventArgs args) { - _bottomToolbar.CurrentPageNumber = (int)args.CurrentPageNumber; - if (args.CurrentPageNumber == _bottomToolbar.TotalPages) - { - _bottomToolbar.NextPageDisable = true; - _bottomToolbar.PreviousPageDisable = false; - } - if (args.CurrentPageNumber < _bottomToolbar.TotalPages && args.CurrentPageNumber != 1) - { - _bottomToolbar.NextPageDisable = false; - _bottomToolbar.PreviousPageDisable = false; - } - if (args.CurrentPageNumber == 1) - { - _bottomToolbar.PreviousPageDisable = true; - _bottomToolbar.NextPageDisable = false; - } StateHasChanged(); } } \ No newline at end of file diff --git a/server-side/Pages/Thumbnail.razor b/server-side/Pages/Thumbnail.razor deleted file mode 100644 index df825c2..0000000 --- a/server-side/Pages/Thumbnail.razor +++ /dev/null @@ -1,69 +0,0 @@ -@*@page "/thumbnail"*@ - -@using DocumentExplorer.Models - -
-
- @foreach (var item in ThumbnailImages) - { - -
-
- -
-
@item.PageNumber
-
-
- } -
-
- -@code{ - private List ThumbnailImages { get; set; } - private int _previousImageIndex = 1; - private int _selectedPage = 1; - public bool ShowThumbnail { get; set; } = true; - protected override void OnInitialized() - { - ThumbnailImages = new List(); - } - private string UpdateSelectionClass(int pageNumber) - { - if (pageNumber == _selectedPage) - { - return "e-de-thumbnail-active-selection"; - } - else - { - return ""; - } - } - public void RenderThumbnail(string[] images) - { - ThumbnailImages = new List(); - for (int i = 1; i <= images.Length; i++) - { - ThumbnailImages.Add(new ThumbnailImage(i, images[(i - 1)])); - } - StateHasChanged(); - } - public void GotoPage(int pageNumber) - { - _previousImageIndex = pageNumber; - _selectedPage = pageNumber; - } - private async void Select(int pageNumber) - { - _selectedPage = pageNumber; - _previousImageIndex = pageNumber; - StateHasChanged(); - await GotoSelectedThumbnailPage.InvokeAsync(pageNumber); - } - public void SelectFirstPage() - { - _selectedPage = 1; - StateHasChanged(); - } - [Parameter] - public EventCallback GotoSelectedThumbnailPage { get; set; } -} \ No newline at end of file diff --git a/server-side/Pages/TopToolbar.razor b/server-side/Pages/TopToolbar.razor index c17ab7c..8a96537 100644 --- a/server-side/Pages/TopToolbar.razor +++ b/server-side/Pages/TopToolbar.razor @@ -24,8 +24,8 @@ -@code{ - public string RootName{get; set;} +@code { + public string RootName { get; set; } private async void CallBackClick() { @@ -34,4 +34,4 @@ [Parameter] public EventCallback BackClick { get; set; } -} +} \ No newline at end of file diff --git a/server-side/Pages/WordViewer.razor b/server-side/Pages/WordViewer.razor index 9bbc12b..f005daf 100644 --- a/server-side/Pages/WordViewer.razor +++ b/server-side/Pages/WordViewer.razor @@ -16,15 +16,11 @@
-
-
- -
-
- - - - +
+
+ + +
@@ -36,17 +32,12 @@ private string FileName { get; set; } private string SubPath { get; set; } private string Path { get; set; } - private string Deheight { get; set; } = "height:300px;"; private string ThumbnailStyle { get; set; } = "thumbnailShow"; - private string DeMarginStyle { get; set; } = "e-word-right-layout"; private double ZoomFactor { get; set; } = 1; - private SfDocumentEditor _documenteditor; + private SfDocumentEditorContainer _documenteditorcontainer; private TopToolbar _topToolbar; - private BottomToolbar _bottomToolbar; - private Thumbnail _thumbnail; protected override async void OnInitialized() { - Deheight = await JSRuntime.InvokeAsync("getDocumentEditorHeight"); if (QueryHelpers.ParseQuery(NavigationManager.ToAbsoluteUri(NavigationManager.Uri).Query).TryGetValue("path", out var pathparam)) { Path = pathparam.First(); @@ -63,11 +54,6 @@ } } - private async void ToogleBottomToolBarVisibility() - { - await JSRuntime.InvokeVoidAsync("toggleBottomToolbarVisibility", "DocEdit_viewerContainer"); - } - #region TopToolBar Interaction private void BackClickHandler() { @@ -85,68 +71,10 @@ } #endregion - #region BottomToolbar - private async void ShowHideThumbnail() - { - OverlayStyle = "overlayShow"; - UpdateThumbnailView(); - await _documenteditor.Resize(); - ToogleBottomToolBarVisibility(); - OverlayStyle = "overlayHide"; - StateHasChanged(); - } - private void UpdateThumbnailView() - { - _thumbnail.ShowThumbnail = !_thumbnail.ShowThumbnail; - if (_thumbnail.ShowThumbnail) - { - ThumbnailStyle = "thumbnailShow"; - DeMarginStyle = "e-word-right-layout"; - } - else - { - ThumbnailStyle = "thumbnailHide"; - DeMarginStyle = "e-word-layout"; - } - StateHasChanged(); - } - private async void GotoAction(int pageNum) - { - _thumbnail.GotoPage(pageNum); - await _documenteditor.ScrollToPage(pageNum); - } - private async void FileToolBar(string action) - { - switch (action) - { - case "ZoomIn": - ZoomFactor += 0.1; - break; - case "ZoomOut": - ZoomFactor -= 0.1; - break; - case "FullScreen": - await JSRuntime.InvokeVoidAsync("fullScreen", "DocEdit"); - break; - case "Print": - await _documenteditor.Print(); - break; - } - } - #endregion - - #region Thumbnailpane Interaction - private void GotoSlectedPage(int args) - { - _documenteditor.ScrollToPage(args); - _bottomToolbar.CurrentPageNumber = args; - } - #endregion - #region DocumentEditor Event private async void AfterCreated() { - await _documenteditor.Resize(); + await _documenteditorcontainer.ResizeAsync(); HttpResponseMessage docresponse; if (SubPath != null) { @@ -171,52 +99,11 @@ docresponse = await Http.SendAsync(docrequest); } string output = await docresponse.Content.ReadAsStringAsync(); - if (docresponse.IsSuccessStatusCode) - { - List images = new List(); - Newtonsoft.Json.Linq.JArray jArray = (Newtonsoft.Json.Linq.JArray)JsonConvert.DeserializeObject(output); - string sfdt = ((JValue)jArray[0]).Value.ToString(); - jArray.RemoveAt(0); - foreach (JValue item in jArray) - { - images.Add(item.Value.ToString()); - } - _thumbnail.RenderThumbnail(images.ToArray()); - await _documenteditor.Open(sfdt); - } - await _documenteditor.Resize(); - _thumbnail.SelectFirstPage(); - _bottomToolbar.TotalPages = await _documenteditor.GetPageCount(); - _bottomToolbar.Refresh(); + await _documenteditorcontainer.DocumentEditor.OpenAsync(output); + await _documenteditorcontainer.ResizeAsync(); DocumentName = ""; OverlayStyle = "overlayHide"; StateHasChanged(); } - private void ViewChange(ViewChangeEventArgs args) - { - int pageNo = (int)args.StartPage; - _bottomToolbar.CurrentPageNumber = pageNo; - _thumbnail.GotoPage((int)args.StartPage); - if (pageNo == _bottomToolbar.TotalPages) - { - _bottomToolbar.NextPageDisable = true; - _bottomToolbar.PreviousPageDisable = false; - } - if (pageNo < _bottomToolbar.TotalPages && pageNo != 1) - { - _bottomToolbar.NextPageDisable = false; - _bottomToolbar.PreviousPageDisable = false; - } - if (pageNo == 1) - { - _bottomToolbar.PreviousPageDisable = true; - _bottomToolbar.NextPageDisable = false; - } - } - private void ZoomChange() - { - _bottomToolbar.ZoomOutDisable = (_documenteditor.ZoomFactor <= 0.5); - _bottomToolbar.ZoomInDisable = (_documenteditor.ZoomFactor >= 5); - } #endregion } diff --git a/server-side/Pages/ZipViewer.razor b/server-side/Pages/ZipViewer.razor index eab5663..e55cc29 100644 --- a/server-side/Pages/ZipViewer.razor +++ b/server-side/Pages/ZipViewer.razor @@ -11,22 +11,20 @@
- + - + - - - @*Default column for file name*@ - - @*Default column for file size*@ + @* + + - + *@
@@ -40,7 +38,7 @@ private string SubPath { get; set; } private string Path { get; set; } public string OverlayStyle { get; set; } = "overlayHide"; - private SfFileManager _zipManager; +private SfFileManager _zipManager; private TopToolbar _topToolbar; private string SpinnerTarget { get; set; } = "#zipContainer"; public bool isRootNameChange = true; @@ -76,7 +74,7 @@ HttpResponseMessage response = await Http.SendAsync(request); if (response.IsSuccessStatusCode) { - _zipManager.Refresh(); + await _zipManager.RefreshFilesAsync(); } } private void BackClickHandler() @@ -106,10 +104,10 @@ string modifiedDataString = JsonConvert.SerializeObject(data); AjaxSettings["data"] = modifiedDataString; string returnString = JsonConvert.SerializeObject(AjaxSettings); - args.AjaxSettings = JsonConvert.DeserializeObject(returnString); + //args.AjaxSettings = JsonConvert.DeserializeObject(returnString); } } - private void FileOpen(FileOpenEventArgs args) + private void FileOpen(Syncfusion.Blazor.FileManager.FileOpenEventArgs args) { string dataString = JsonConvert.SerializeObject(args.FileDetails); Dictionary fileDetails = JsonConvert.DeserializeObject>(dataString); diff --git a/server-side/Pages/_Host.cshtml b/server-side/Pages/_Host.cshtml deleted file mode 100644 index 69440a7..0000000 --- a/server-side/Pages/_Host.cshtml +++ /dev/null @@ -1,45 +0,0 @@ -@page "/" -@namespace DocumentExplorer.Pages -@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -@{ - Layout = null; -} - - - - - - - Blazor Document Explorer Showcase example | Syncfusion Demos - - - - - - - - - - @* - - *@ - - - @**@ - - @**@ - -
- - An error has occurred. This application may no longer respond until reloaded. - - - An unhandled exception has occurred. See browser dev tools for details. - - Reload - 🗙 -
- - - - diff --git a/server-side/Program.cs b/server-side/Program.cs index 3471ffc..b2ea67d 100644 --- a/server-side/Program.cs +++ b/server-side/Program.cs @@ -1,28 +1,71 @@ +using DocumentExplorer.Components; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; +using Syncfusion.Blazor; +using Microsoft.Net.Http.Headers; +using Newtonsoft.Json.Serialization; +using System.IO; +using Syncfusion.Licensing; -namespace DocumentExplorer -{ - public class Program +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); +builder.Services.AddServerSideBlazor().AddHubOptions(o => { o.MaximumReceiveMessageSize = 102400000; }); +builder.Services.AddSyncfusionBlazor(); +builder.Services.AddMemoryCache(); +builder.Services.AddHttpClient(); +builder.Services.AddSession(); +builder.Services.AddDistributedMemoryCache(); +builder.Services.AddCors(options => { - public static void Main(string[] args) + options.AddPolicy("AllowAllOrigins", builder => { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + }); + }); +builder.Services.AddControllers().AddNewtonsoftJson(options => + { + options.SerializerSettings.ContractResolver = new DefaultContractResolver(); + }); +if (File.Exists(Directory.GetCurrentDirectory() + "/SyncfusionLicense.txt")) +{ + string licenseKey = System.IO.File.ReadAllText(Directory.GetCurrentDirectory() + "/SyncfusionLicense.txt"); + SyncfusionLicenseProvider.RegisterLicense(licenseKey); } +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error", createScopeForErrors: true); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); +} + +app.UseHttpsRedirection(); +app.UseSession(); +app.UseStaticFiles(); +app.UseAntiforgery(); + +app.MapRazorComponents() + .AddInteractiveServerRenderMode(); +app.MapControllers(); + +app.MapDefaultControllerRoute(); +//app.MapBlazorHub(); +app.UseCors(); + +app.Run(); diff --git a/server-side/Properties/launchSettings.json b/server-side/Properties/launchSettings.json index cdbdf5a..d365dbd 100644 --- a/server-side/Properties/launchSettings.json +++ b/server-side/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:60851/", + "applicationUrl": "http://localhost:6085/", "sslPort": 0 } }, @@ -21,7 +21,7 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:60851/" + "applicationUrl": "http://localhost:6085/" } } } diff --git a/server-side/Startup.cs b/server-side/Startup.cs deleted file mode 100644 index 56d7feb..0000000 --- a/server-side/Startup.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Syncfusion.Blazor; -using Microsoft.Net.Http.Headers; -using Newtonsoft.Json.Serialization; -using System.IO; -using Syncfusion.Licensing; - -namespace DocumentExplorer -{ - public class Startup - { - public Startup(IConfiguration configuration, IWebHostEnvironment env) - { - Configuration = configuration; - if (File.Exists(env.ContentRootPath + "/SyncfusionLicense.txt")) - { - string licenseKey = System.IO.File.ReadAllText(env.ContentRootPath + "/SyncfusionLicense.txt"); - SyncfusionLicenseProvider.RegisterLicense(licenseKey); - } - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - services.AddServerSideBlazor().AddHubOptions(o => { o.MaximumReceiveMessageSize = 102400000; }); - services.AddSyncfusionBlazor(); - services.AddHttpClient(); - services.AddCors(options => - { - options.AddPolicy("AllowAllOrigins", builder => - { - builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader(); - }); - }); - services.AddControllers().AddNewtonsoftJson(options => - { - options.SerializerSettings.ContractResolver = new DefaultContractResolver(); - }); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Error"); - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - app.UseCors(); - app.UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute(); - endpoints.MapControllers(); - endpoints.MapBlazorHub(); - endpoints.MapFallbackToPage("/_Host"); - }); - } - } -} diff --git a/server-side/_Imports.razor b/server-side/_Imports.razor index d8571bd..0c198c3 100644 --- a/server-side/_Imports.razor +++ b/server-side/_Imports.razor @@ -4,6 +4,7 @@ @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode @using Microsoft.JSInterop @using DocumentExplorer @using DocumentExplorer.Models @@ -15,7 +16,6 @@ @using Microsoft.AspNetCore.WebUtilities @using System.Text @using IO = System.IO - @inject IJSRuntime JSRuntime @inject HttpClient Http @inject NavigationManager NavigationManager; diff --git a/server-side/web.config b/server-side/web.config deleted file mode 100644 index 7d231aa..0000000 --- a/server-side/web.config +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/server-side/wwwroot/Script/JsInteropHelper.js b/server-side/wwwroot/Script/JsInteropHelper.js index 2d21756..ac27f03 100644 --- a/server-side/wwwroot/Script/JsInteropHelper.js +++ b/server-side/wwwroot/Script/JsInteropHelper.js @@ -35,65 +35,6 @@ window.revertToIconPreview = (val, iconClass) => { image.parentElement.insertBefore(iconDiv, image); image.remove(); }; -window.setDialogDrag = (val) => { - var dialog = document.getElementById(val).ej2_instances[0]; - dialog.allowDragging = false; -} -window.showStar = (val, isGrid) => { - var element = document.querySelector("[data-starid='" + val + "']"); - if ((element === null) || (element.querySelector('.star') !== null)) { return; } - var rowDiv = document.createElement('span'); - rowDiv.className += 'star sf-icon-Starred'; - if (isGrid) { - element.querySelector('.e-fe-text').appendChild(rowDiv); - } - else { - if (!element.querySelector('.e-list-icon')) { - rowDiv.className += ' img'; - element.querySelector('.e-text-content').prepend(rowDiv); - } - else { - element.querySelector('.e-list-icon').appendChild(rowDiv); - } - } -}; - -window.toggleStar = (val, isGrid) => { - var element = document.querySelector("[data-mapId='" + val + "']"); - if ((element === null)) { return "Not Found"; } - var rowDiv = document.createElement('span'); - rowDiv.className += 'star sf-icon-Starred'; - if (isGrid) { - var containerEle = ej.base.closest(element, '.e-row'); - if (containerEle.querySelector('.star') === null) { - containerEle.querySelector('.e-fe-text').appendChild(rowDiv); - ej.base.addClass([containerEle], ['e-file-star']); - return "Add"; - } else { - ej.base.removeClass([containerEle], ['e-file-star']); - ej.base.remove(containerEle.querySelector('.star')); - return "Remove"; - } - } - else { - var containerEle = ej.base.closest(element, '.e-large-icon'); - if (containerEle.querySelector('.star') === null) { - if (!containerEle.querySelector('.e-list-icon')) { - rowDiv.className += ' img'; - containerEle.querySelector('.e-text-content').prepend(rowDiv); - } - else { - containerEle.querySelector('.e-list-icon').appendChild(rowDiv); - } - ej.base.addClass([containerEle], ['e-file-star']); - return "Add"; - } else { - ej.base.removeClass([containerEle], ['e-file-star']); - ej.base.remove(containerEle.querySelector('.star')); - return "Remove"; - } - } -}; window.toggleZipFileManagerVisibility = (id, val) => { var element = document.getElementById(id); if (val) { diff --git a/server-side/wwwroot/Script/blazor-document-explorer.min.js b/server-side/wwwroot/Script/blazor-document-explorer.min.js deleted file mode 100644 index 8ba1cba..0000000 --- a/server-side/wwwroot/Script/blazor-document-explorer.min.js +++ /dev/null @@ -1,42 +0,0 @@ -/*! - * filename: blazor-document-explorer.min.js - * version : 18.2.44 - * Copyright Syncfusion Inc. 2001 - 2020. All rights reserved. - * Use of this code is subject to the terms of our license. - * A copy of the current license can be obtained at any time by e-mailing - * licensing@syncfusion.com. Any infringement will be prosecuted under - * applicable laws. - */!function(e){var t={};function i(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)i.d(n,o,function(t){return e[t]}.bind(null,o));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=1)}([function(e,t){t.copy=function(e,t,i,n){var o=e||{},r=arguments.length;n&&(r-=1);for(var s=function(e){if(!a[e])return"continue";var t=a[e];Object.keys(t).forEach(function(e){var i,r=o[e],s=t[e];n&&(isObject(s)||Array.isArray(s))?isObject(s)?(i=r||{},o[e]=s({},i,s,n)):(i=r||[],o[e]=s([],i,s,n)):o[e]=s})},a=arguments,l=1;l "+o+""+i.innerHTML+"