diff --git a/app/MindWork AI Studio/Components/CodeTabs.razor b/app/MindWork AI Studio/Components/CodeTabs.razor index de1f8cbf..7223cecb 100644 --- a/app/MindWork AI Studio/Components/CodeTabs.razor +++ b/app/MindWork AI Studio/Components/CodeTabs.razor @@ -1,4 +1,4 @@ - + @foreach (var block in blocks) { diff --git a/app/MindWork AI Studio/Dialogs/PandocDialog.razor b/app/MindWork AI Studio/Dialogs/PandocDialog.razor index 67bd306c..54989d8b 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDialog.razor +++ b/app/MindWork AI Studio/Dialogs/PandocDialog.razor @@ -33,39 +33,44 @@ - + Pandoc is distributed under the - GNU General Public License v2 (GPL) - - . + GNU General Public License v2 (GPL). By clicking "Accept GPL and Install", you agree to the terms of the GPL license
and Pandoc will be installed automatically for you.
- Accept GPL and Install + + Accept GPL and Install
- + If you prefer to install Pandoc yourself, please follow one of these two guides. Installers are only available for Windows and Mac. - + Accept the terms of the GPL license and download the latest installer with the download button below. + Eventually you need to allow the download of the installer in the download window. - pandoc-3.7.0-windows-x86_64.msi - pandoc-3.7.0.1-x86_64-macOS.pkg - pandoc-3.7.0.1-arm64-macOS.pkg + pandoc-@(PANDOC_VERSION)-windows-x86_64.msi + pandoc-@(PANDOC_VERSION)-x86_64-macOS.pkg + pandoc-@(PANDOC_VERSION)-arm64-macOS.pkg Execute the installer and follow the instructions. + + Pandoc is distributed under the GNU General Public License v2 (GPL). + By clicking "Accept GPL and download installer", you agree to the terms of the GPL license.
+
+ + Accept GPL and download installer +
@@ -81,36 +86,31 @@ - Open the folder and copy the full path to the pandoc.exe file into you + Open the folder and copy the full path to the pandoc.exe file into your clipboard. - C:\Users\%USERNAME%\pandoc\pandoc-3.7.0-windows-x86_64\pandoc-3.7.0 - /usr/local/bin/pandoc/pandoc-3.7.0-x86_64-macOS/pandoc-3.7.0 - /usr/local/bin/pandoc/pandoc-3.7.0-linux-amd64/pandoc-3.7.0 + C:\Users\%USERNAME%\pandoc\pandoc-@(PANDOC_VERSION) + /usr/local/bin/pandoc/pandoc-@(PANDOC_VERSION) + /usr/local/bin/pandoc/pandoc-@(PANDOC_VERSION) Add the copied path to your systems environment variables and check the installation - by typing - pandoc --version + by typing
pandoc --version into your command line interface. - > pandoc.exe --version
> pandoc.exe 3.7.0
- > pandoc --version
> pandoc.exe 3.7.0
- > pandoc --version
> pandoc.exe 3.7.0
+ > pandoc.exe --version
> pandoc.exe @(PANDOC_VERSION)
+ > pandoc --version
> pandoc.exe @(PANDOC_VERSION)
+ > pandoc --version
> pandoc.exe @(PANDOC_VERSION)
- Pandoc is distributed under the - GNU General Public License v2 (GPL) - - . - By clicking "Accept GPL and Download", you agree to the terms of the GPL license. + Pandoc is distributed under the GNU General Public License v2 (GPL). + By clicking "Accept GPL and archive", you agree to the terms of the GPL license.
- - Accept GPL and Download + + Accept GPL and download archive
@@ -122,8 +122,7 @@ } else { - + @if (showSkeleton) { - + + Pandoc ist auf Ihrem System nicht verfügbar - Proceed - to installation + Proceed to installation } diff --git a/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs b/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs index 66551338..19a2fcaa 100644 --- a/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs +++ b/app/MindWork AI Studio/Dialogs/PandocDialog.razor.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Components; +using AIStudio.Tools.Services; +using Microsoft.AspNetCore.Components; namespace AIStudio.Dialogs; @@ -7,10 +8,17 @@ public partial class PandocDialog : ComponentBase [Inject] private HttpClient HttpClient { get; set; } = null!; + [Inject] + private RustService RustService { get; init; } = null!; + + [Inject] + protected IJSRuntime JsRuntime { get; init; } = null!; + [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; private static readonly string LICENCE_URI = "https://raw.githubusercontent.com/jgm/pandoc/master/COPYRIGHT"; + private static string PANDOC_VERSION = "1.0.0"; private bool isPandocAvailable; private bool showSkeleton; @@ -25,6 +33,7 @@ public partial class PandocDialog : ComponentBase await base.OnInitializedAsync(); this.showSkeleton = true; await this.CheckPandocAvailabilityAsync(); + PANDOC_VERSION = await Pandoc.FetchLatestVersionAsync(); } #endregion @@ -33,13 +42,36 @@ public partial class PandocDialog : ComponentBase private async Task CheckPandocAvailabilityAsync() { - this.isPandocAvailable = await Pandoc.CheckAvailabilityAsync(); + this.isPandocAvailable = await Pandoc.CheckAvailabilityAsync(false); this.showSkeleton = false; await this.InvokeAsync(this.StateHasChanged); } + private async Task InstallPandocAsync() => await Pandoc.InstallAsync(this.RustService); + private void ProceedToInstallation() => this.showInstallPage = true; - + + private async Task GetInstaller() + { + var uri = await Pandoc.GenerateInstallerUriAsync(); + var filename = this.FilenameFromUri(uri); + await this.JsRuntime.InvokeVoidAsync("triggerDownload", uri, filename); + + } + + private async Task GetArchive() + { + var uri = await Pandoc.GenerateUriAsync(); + var filename = this.FilenameFromUri(uri); + await this.JsRuntime.InvokeVoidAsync("triggerDownload", uri, filename); + } + + private string FilenameFromUri(string uri) + { + var index = uri.LastIndexOf('/'); + return uri[(index + 1)..]; + } + private async Task OnExpandedChanged(bool newVal) { if (newVal) @@ -53,8 +85,7 @@ public partial class PandocDialog : ComponentBase } catch (Exception ex) { - Console.WriteLine($"Fehler beim Laden des Lizenztexts: {ex.Message}"); - this.licenseText = "Fehler beim Laden des Lizenztexts."; + this.licenseText = "Error loading license text, please consider following the links to the GPL."; } finally { diff --git a/app/MindWork AI Studio/Tools/Pandoc.cs b/app/MindWork AI Studio/Tools/Pandoc.cs index d89a430a..f48e5ea9 100644 --- a/app/MindWork AI Studio/Tools/Pandoc.cs +++ b/app/MindWork AI Studio/Tools/Pandoc.cs @@ -10,7 +10,7 @@ namespace AIStudio.Tools; public static partial class Pandoc { private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger("PluginFactory"); - private static readonly string DOWNLOAD_URL = "https://github.com/jgm/pandoc/releases/download/"; + private static readonly string DOWNLOAD_URL = "https://github.com/jgm/pandoc/releases/download"; private static readonly string LATEST_URL = "https://github.com/jgm/pandoc/releases/latest"; private static readonly Version MINIMUM_REQUIRED_VERSION = new (3, 6); private static readonly Version FALLBACK_VERSION = new (3, 6, 4); @@ -20,7 +20,7 @@ public static partial class Pandoc /// Checks if pandoc is available on the system and can be started as a process /// /// True, if pandoc is available and the minimum required version is met, else False. - public static async Task CheckAvailabilityAsync() + public static async Task CheckAvailabilityAsync(bool showMessages = true) { try { @@ -35,7 +35,8 @@ public static partial class Pandoc using var process = Process.Start(startInfo); if (process == null) { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Help, "The pandoc process could not be started.")); + if (showMessages) + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Help, "The pandoc process could not be started.")); LOG.LogInformation("The pandoc process was not started, it was null"); return false; } @@ -44,7 +45,8 @@ public static partial class Pandoc await process.WaitForExitAsync(); if (process.ExitCode != 0) { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, $"The pandoc process exited unexpectedly.")); + if (showMessages) + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Error, $"The pandoc process exited unexpectedly.")); LOG.LogError("The pandoc process was exited with code {ProcessExitCode}", process.ExitCode); return false; } @@ -52,7 +54,8 @@ public static partial class Pandoc var versionMatch = PandocRegex().Match(output); if (!versionMatch.Success) { - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"pandoc --version returned an invalid format.")); + if (showMessages) + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"pandoc --version returned an invalid format.")); LOG.LogError("pandoc --version returned an invalid format:\n {Output}", output); return false; } @@ -63,18 +66,21 @@ public static partial class Pandoc if (installedVersion >= MINIMUM_REQUIRED_VERSION) { - await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, $"Pandoc {installedVersion.ToString()} is installed.")); + if (showMessages) + await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, $"Pandoc {installedVersion.ToString()} is installed.")); return true; } - await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Build, $"Pandoc {installedVersion.ToString()} is installed, but it doesn't match the required version ({MINIMUM_REQUIRED_VERSION.ToString()}).")); + if (showMessages) + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Build, $"Pandoc {installedVersion.ToString()} is installed, but it doesn't match the required version ({MINIMUM_REQUIRED_VERSION.ToString()}).")); LOG.LogInformation("Pandoc {Installed} is installed, but it does not match the required version ({Requirement})", installedVersion.ToString(), MINIMUM_REQUIRED_VERSION.ToString()); return false; } catch (Exception e) { - await MessageBus.INSTANCE.SendError(new (@Icons.Material.Filled.AppsOutage, "Pandoc is not installed.")); + if (showMessages) + await MessageBus.INSTANCE.SendError(new (@Icons.Material.Filled.AppsOutage, "Pandoc is not installed.")); LOG.LogError("Pandoc is not installed and threw an exception:\n {Message}", e.Message); return false; } @@ -177,7 +183,7 @@ public static partial class Pandoc } // win arm not available - private static async Task GenerateUriAsync() + public static async Task GenerateUriAsync() { var version = await FetchLatestVersionAsync(); var baseUri = $"{DOWNLOAD_URL}/{version}/pandoc-{version}-"; @@ -191,6 +197,25 @@ public static partial class Pandoc _ => string.Empty, }; } + + public static async Task GenerateInstallerUriAsync() + { + var version = await FetchLatestVersionAsync(); + var baseUri = $"{DOWNLOAD_URL}/{version}/pandoc-{version}-"; + + switch (CPU_ARCHITECTURE) + { + case "win-x64": + return $"{baseUri}windows-x86_64.msi"; + case "osx-x64": + return $"{baseUri}x86_64-macOS.pkg"; + case "osx-arm64": + return $"{baseUri}arm64-macOS.pkg\n"; + default: + await MessageBus.INSTANCE.SendError(new (Icons.Material.Filled.Terminal, $"Installers are not available on {CPU_ARCHITECTURE} systems.")); + return string.Empty; + } + } /// /// Returns the name of the pandoc executable based on the running operating system @@ -200,6 +225,6 @@ public static partial class Pandoc [GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+)")] private static partial Regex PandocRegex(); - [GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+\.[0-9]+)")] + [GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+\.[0-9]+(?:\.[0-9]+)?)")] private static partial Regex VersionRegex(); } \ No newline at end of file diff --git a/app/MindWork AI Studio/wwwroot/app.js b/app/MindWork AI Studio/wwwroot/app.js index aa6b8e2b..bf1eb31c 100644 --- a/app/MindWork AI Studio/wwwroot/app.js +++ b/app/MindWork AI Studio/wwwroot/app.js @@ -25,4 +25,14 @@ window.clearDiv = function (divName) { window.scrollToBottom = function(element) { element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'nearest' }); +} + +window.triggerDownload = function(url, filename) { + const a = document.createElement('a'); + a.href = url; + a.setAttribute('download', filename); + a.style.display = 'none'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); } \ No newline at end of file