From 164b07c629e8b2cf55e5adddfe3ca7213562efdc Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Fri, 14 Nov 2025 13:34:30 +0100 Subject: [PATCH] Improved Pandoc installation checking (#571) --- .../Assistants/I18N/allTexts.lua | 12 ++++++++ .../Chat/ContentBlockComponent.razor.cs | 2 +- .../Components/ReadFileContent.razor.cs | 29 +++++++++++++++++++ .../plugin.lua | 12 ++++++++ .../plugin.lua | 12 ++++++++ app/MindWork AI Studio/Tools/Pandoc.cs | 5 ++-- app/MindWork AI Studio/Tools/PandocExport.cs | 25 ++++++++++++++-- .../wwwroot/changelog/v0.9.53.md | 3 +- 8 files changed, 93 insertions(+), 7 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index e3691ca3..9d9e58a5 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -1666,6 +1666,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider" +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc Installation" + +-- Pandoc may be required for importing files. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc may be required for importing files." + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet" @@ -5368,6 +5374,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T567205144"] = "It seems that Pandoc i -- The latest Pandoc version was not found, installing version {0} instead. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T726914939"] = "The latest Pandoc version was not found, installing version {0} instead." +-- Pandoc is required for Microsoft Word export. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T1473115556"] = "Pandoc is required for Microsoft Word export." + +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T185447014"] = "Pandoc Installation" + -- Error during Microsoft Word export UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T3290596792"] = "Error during Microsoft Word export" diff --git a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs index 13575faa..efa9c31b 100644 --- a/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs +++ b/app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs @@ -138,7 +138,7 @@ public partial class ContentBlockComponent : MSGComponentBase private async Task ExportToWord() { - await PandocExport.ToMicrosoftWord(this.RustService, T("Export Chat to Microsoft Word"), this.Content); + await PandocExport.ToMicrosoftWord(this.RustService, this.DialogService, T("Export Chat to Microsoft Word"), this.Content); } private async Task RegenerateBlock() diff --git a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs index 86bafebe..ff3fa1f6 100644 --- a/app/MindWork AI Studio/Components/ReadFileContent.razor.cs +++ b/app/MindWork AI Studio/Components/ReadFileContent.razor.cs @@ -1,8 +1,11 @@ +using AIStudio.Dialogs; using AIStudio.Tools.Rust; using AIStudio.Tools.Services; using Microsoft.AspNetCore.Components; +using DialogOptions = AIStudio.Dialogs.DialogOptions; + namespace AIStudio.Components; public partial class ReadFileContent : MSGComponentBase @@ -16,6 +19,12 @@ public partial class ReadFileContent : MSGComponentBase [Inject] private RustService RustService { get; init; } = null!; + [Inject] + private IDialogService DialogService { get; init; } = null!; + + [Inject] + private ILogger Logger { get; init; } = null!; + private async Task SelectFile() { var selectedFile = await this.RustService.SelectFile(T("Select file to read its content")); @@ -38,6 +47,26 @@ public partial class ReadFileContent : MSGComponentBase return; } + // Ensure that Pandoc is installed and ready: + var pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showSuccessMessage: false); + if (!pandocState.IsAvailable) + { + var dialogParameters = new DialogParameters + { + { x => x.ShowInitialResultInSnackbar, false }, + }; + + var dialogReference = await this.DialogService.ShowAsync(T("Pandoc Installation"), dialogParameters, DialogOptions.FULLSCREEN); + await dialogReference.Result; + + pandocState = await Pandoc.CheckAvailabilityAsync(this.RustService, showSuccessMessage: true); + if (!pandocState.IsAvailable) + { + this.Logger.LogError("Pandoc is not available after installation attempt."); + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Cancel, T("Pandoc may be required for importing files."))); + } + } + var fileContent = await this.RustService.ReadArbitraryFileData(selectedFile.SelectedFilePath, int.MaxValue); await this.FileContentChanged.InvokeAsync(fileContent); } diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index 234adfca..0c8cef6a 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -1668,6 +1668,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "Hier k -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Anbieter" +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc-Installation" + +-- Pandoc may be required for importing files. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc wird möglicherweise zum Importieren von Dateien benötigt." + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Bilder werden derzeit nicht unterstützt" @@ -5370,6 +5376,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T567205144"] = "Es scheint, dass Pando -- The latest Pandoc version was not found, installing version {0} instead. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T726914939"] = "Die neueste Pandoc-Version wurde nicht gefunden, stattdessen wird Version {0} installiert." +-- Pandoc is required for Microsoft Word export. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T1473115556"] = "Pandoc wird für den Export nach Microsoft Word benötigt." + +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T185447014"] = "Pandoc-Installation" + -- Error during Microsoft Word export UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T3290596792"] = "Fehler beim Exportieren nach Microsoft Word" diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 89343014..e8ff12fe 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -1668,6 +1668,12 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROFILESELECTION::T918741365"] = "You can -- Provider UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::PROVIDERSELECTION::T900237532"] = "Provider" +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T185447014"] = "Pandoc Installation" + +-- Pandoc may be required for importing files. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T2596465560"] = "Pandoc may be required for importing files." + -- Images are not supported yet UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::READFILECONTENT::T298062956"] = "Images are not supported yet" @@ -5370,6 +5376,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T567205144"] = "It seems that Pandoc i -- The latest Pandoc version was not found, installing version {0} instead. UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOC::T726914939"] = "The latest Pandoc version was not found, installing version {0} instead." +-- Pandoc is required for Microsoft Word export. +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T1473115556"] = "Pandoc is required for Microsoft Word export." + +-- Pandoc Installation +UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T185447014"] = "Pandoc Installation" + -- Error during Microsoft Word export UI_TEXT_CONTENT["AISTUDIO::TOOLS::PANDOCEXPORT::T3290596792"] = "Error during Microsoft Word export" diff --git a/app/MindWork AI Studio/Tools/Pandoc.cs b/app/MindWork AI Studio/Tools/Pandoc.cs index 94384df7..c4bdb462 100644 --- a/app/MindWork AI Studio/Tools/Pandoc.cs +++ b/app/MindWork AI Studio/Tools/Pandoc.cs @@ -37,8 +37,9 @@ public static partial class Pandoc /// /// Global rust service to access file system and data dir. /// Controls if snackbars are shown to the user. + /// Controls if a success snackbar is shown to the user. /// True, if pandoc is available and the minimum required version is met, else false. - public static async Task CheckAvailabilityAsync(RustService rustService, bool showMessages = true) + public static async Task CheckAvailabilityAsync(RustService rustService, bool showMessages = true, bool showSuccessMessage = true) { try { @@ -80,7 +81,7 @@ public static partial class Pandoc if (installedVersion >= MINIMUM_REQUIRED_VERSION) { - if (showMessages) + if (showMessages && showSuccessMessage) await MessageBus.INSTANCE.SendSuccess(new(Icons.Material.Filled.CheckCircle, string.Format(TB("Pandoc v{0} is installed."), installedVersionString))); LOG.LogInformation("Pandoc v{0} is installed and matches the required version (v{1})", installedVersionString, MINIMUM_REQUIRED_VERSION.ToString()); diff --git a/app/MindWork AI Studio/Tools/PandocExport.cs b/app/MindWork AI Studio/Tools/PandocExport.cs index 23c660d9..acc4dbd6 100644 --- a/app/MindWork AI Studio/Tools/PandocExport.cs +++ b/app/MindWork AI Studio/Tools/PandocExport.cs @@ -1,8 +1,11 @@ using System.Diagnostics; using AIStudio.Chat; +using AIStudio.Dialogs; using AIStudio.Tools.PluginSystem; using AIStudio.Tools.Services; +using DialogOptions = AIStudio.Dialogs.DialogOptions; + namespace AIStudio.Tools; public static class PandocExport @@ -11,7 +14,7 @@ public static class PandocExport private static string TB(string fallbackEn) => I18N.I.T(fallbackEn, typeof(PandocExport).Namespace, nameof(PandocExport)); - public static async Task ToMicrosoftWord(RustService rustService, string dialogTitle, IContent markdownContent) + public static async Task ToMicrosoftWord(RustService rustService, IDialogService dialogService, string dialogTitle, IContent markdownContent) { var response = await rustService.SaveFile(dialogTitle, new("Microsoft Word", ["docx"])); if (response.UserCancelled) @@ -40,9 +43,25 @@ public static class PandocExport await File.WriteAllTextAsync(tempMarkdownFilePath, markdownText); // Ensure that Pandoc is installed and ready: - var pandocState = await Pandoc.CheckAvailabilityAsync(rustService); + var pandocState = await Pandoc.CheckAvailabilityAsync(rustService, showSuccessMessage: false); if (!pandocState.IsAvailable) - return false; + { + var dialogParameters = new DialogParameters + { + { x => x.ShowInitialResultInSnackbar, false }, + }; + + var dialogReference = await dialogService.ShowAsync(TB("Pandoc Installation"), dialogParameters, DialogOptions.FULLSCREEN); + await dialogReference.Result; + + pandocState = await Pandoc.CheckAvailabilityAsync(rustService, showSuccessMessage: true); + if (!pandocState.IsAvailable) + { + LOGGER.LogError("Pandoc is not available after installation attempt."); + await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Cancel, TB("Pandoc is required for Microsoft Word export."))); + return false; + } + } // Call Pandoc to create the Word file: var pandoc = await PandocProcessBuilder diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.53.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.53.md index 8299e416..419d2172 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.53.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.53.md @@ -4,4 +4,5 @@ - Added the ability to use documents as input for profile fields. - Added the ability to distribute profiles via configuration plugins in enterprise environments. Thanks, Paul (`PaulKoudelka`), for your first contribution. - Added the ability to preset an app-wide default profile using a configuration plugin in enterprise environments. -- Improved profiles by removing their input limits. \ No newline at end of file +- Improved profiles by removing their input limits. +- Improved the file reading component to correctly verify the Pandoc installation and open the installation dialog when needed. \ No newline at end of file