Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions app/MindWork AI Studio/Assistants/I18N/allTexts.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,27 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T527187983"] = "C
-- Install Pandoc
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANAGEPANDOCDEPENDENCY::T986578435"] = "Install Pandoc"

-- Version
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T1573770551"] = "Version"

-- A new version of the terms is available. Please review it again.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T1711766303"] = "A new version of the terms is available. Please review it again."

-- This mandatory info has not been accepted yet.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T1870532312"] = "This mandatory info has not been accepted yet."

-- Accepted version
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T203086476"] = "Accepted version"

-- Last accepted version
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T3407978086"] = "Last accepted version"

-- Accepted at (UTC)
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T3511160492"] = "Accepted at (UTC)"

-- Please review this text again. The content was changed.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MANDATORYINFODISPLAY::T941885055"] = "Please review this text again. The content was changed."

-- Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::MOTIVATION::T1057189794"] = "Given that my employer's workplace uses both Windows and Linux, I wanted a cross-platform solution that would work seamlessly across all major operating systems, including macOS. Additionally, I wanted to demonstrate that it is possible to create modern, efficient, cross-platform applications without resorting to Electron bloatware. The combination of .NET and Rust with Tauri proved to be an excellent technology stack for building such robust applications."

Expand Down Expand Up @@ -5695,6 +5716,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1137744461"] = "ID mismatch: the
-- This is a private AI Studio installation. It runs without an enterprise configuration.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1209549230"] = "This is a private AI Studio installation. It runs without an enterprise configuration."

-- Unknown configuration plugin
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1290340974"] = "Unknown configuration plugin"

-- This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1388816916"] = "This library is used to read PDF files. This is necessary, e.g., for using PDFs as a data source for a chat."

Expand Down Expand Up @@ -5725,6 +5749,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1629800076"] = "Building on .NET
-- AI Studio creates a log file at startup, in which events during startup are recorded. After startup, another log file is created that records all events that occur during the use of the app. This includes any errors that may occur. Depending on when an error occurs (at startup or during use), the contents of these log files can be helpful for troubleshooting. Sensitive information such as passwords is not included in the log files.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1630237140"] = "AI Studio creates a log file at startup, in which events during startup are recorded. After startup, another log file is created that records all events that occur during the use of the app. This includes any errors that may occur. Depending on when an error occurs (at startup or during use), the contents of these log files can be helpful for troubleshooting. Sensitive information such as passwords is not included in the log files."

-- Consent:
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T171952677"] = "Consent:"

-- This library is used to display the differences between two texts. This is necessary, e.g., for the grammar and spelling assistant.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T1772678682"] = "This library is used to display the differences between two texts. This is necessary, e.g., for the grammar and spelling assistant."

Expand Down Expand Up @@ -5944,6 +5971,9 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T788846912"] = "Copies the config
-- installed by AI Studio
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T833849470"] = "installed by AI Studio"

-- Provided by configuration plugin: {0}
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T836298648"] = "Provided by configuration plugin: {0}"

-- We use this library to be able to read PowerPoint files. This allows us to insert content from slides into prompts and take PowerPoint files into account in RAG processes. We thank Nils Kruthoff for his work on this Rust crate.
UI_TEXT_CONTENT["AISTUDIO::PAGES::INFORMATION::T855925638"] = "We use this library to be able to read PowerPoint files. This allows us to insert content from slides into prompts and take PowerPoint files into account in RAG processes. We thank Nils Kruthoff for his work on this Rust crate."

Expand Down
47 changes: 47 additions & 0 deletions app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@inherits MSGComponentBase

<MudStack Spacing="2">
<MudText Typo="Typo.body2">
@T("Version"): @this.Info.VersionText
</MudText>

@if (this.ShowAcceptanceMetadata)
{
@if (this.AcceptanceStatus is MandatoryInfoAcceptanceStatus.MISSING)
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="@true">
@T("This mandatory info has not been accepted yet.")
</MudAlert>
}
else if (this.AcceptanceStatus is MandatoryInfoAcceptanceStatus.VERSION_CHANGED)
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="@true">
@T("A new version of the terms is available. Please review it again.")
<br />
@T("Last accepted version"): @this.Acceptance!.AcceptedVersion
<br />
@T("Accepted at (UTC)"): @this.Acceptance.AcceptedAtUtc.UtcDateTime.ToString("u")
</MudAlert>
}
else if (this.AcceptanceStatus is MandatoryInfoAcceptanceStatus.CONTENT_CHANGED)
{
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined" Dense="@true">
@T("Please review this text again. The content was changed.")
<br />
@T("Last accepted version"): @this.Acceptance!.AcceptedVersion
<br />
@T("Accepted at (UTC)"): @this.Acceptance.AcceptedAtUtc.UtcDateTime.ToString("u")
</MudAlert>
}
else
{
<MudAlert Severity="Severity.Success" Variant="Variant.Outlined" Dense="@true">
@T("Accepted version"): @this.Acceptance!.AcceptedVersion
<br />
@T("Accepted at (UTC)"): @this.Acceptance.AcceptedAtUtc.UtcDateTime.ToString("u")
</MudAlert>
}
}

<MudJustifiedMarkdown Value="@this.Info.Markdown" />
</MudStack>
42 changes: 42 additions & 0 deletions app/MindWork AI Studio/Components/MandatoryInfoDisplay.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using AIStudio.Settings.DataModel;

using Microsoft.AspNetCore.Components;

namespace AIStudio.Components;

public partial class MandatoryInfoDisplay
{
private enum MandatoryInfoAcceptanceStatus
{
MISSING,
VERSION_CHANGED,
CONTENT_CHANGED,
ACCEPTED,
}

[Parameter]
public DataMandatoryInfo Info { get; set; } = new();

[Parameter]
public DataMandatoryInfoAcceptance? Acceptance { get; set; }

[Parameter]
public bool ShowAcceptanceMetadata { get; set; }

private MandatoryInfoAcceptanceStatus AcceptanceStatus
{
get
{
if (this.Acceptance is null)
return MandatoryInfoAcceptanceStatus.MISSING;

if (!string.Equals(this.Acceptance.AcceptedVersion, this.Info.VersionText, StringComparison.Ordinal))
return MandatoryInfoAcceptanceStatus.VERSION_CHANGED;

if (!string.Equals(this.Acceptance.AcceptedHash, this.Info.AcceptanceHash, StringComparison.Ordinal))
return MandatoryInfoAcceptanceStatus.CONTENT_CHANGED;

return MandatoryInfoAcceptanceStatus.ACCEPTED;
}
}
}
3 changes: 3 additions & 0 deletions app/MindWork AI Studio/Components/MudJustifiedMarkdown.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="justified-markdown">
<MudMarkdown Value="@this.Value" Props="Markdown.DefaultConfig" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE" />
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Microsoft.AspNetCore.Components;

namespace AIStudio.Components;

public partial class MudJustifiedMarkdown
{
[Parameter]
public string Value { get; set; } = string.Empty;
}
7 changes: 7 additions & 0 deletions app/MindWork AI Studio/Dialogs/DialogOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ public static class DialogOptions
CloseOnEscapeKey = true,
FullWidth = true, MaxWidth = MaxWidth.Medium,
};

public static readonly MudBlazor.DialogOptions BLOCKING_FULLSCREEN = new()
{
BackdropClick = false,
CloseOnEscapeKey = false,
FullWidth = true, MaxWidth = MaxWidth.Medium,
};
}
25 changes: 25 additions & 0 deletions app/MindWork AI Studio/Dialogs/MandatoryInfoDialog.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@inherits MSGComponentBase

<MudDialog>
<DialogContent>
<div class="pt-6" style="max-height: calc(100vh - 11rem); overflow-y: auto; overflow-x: hidden; padding-right: 0.5rem;">
<MandatoryInfoDisplay Info="@this.Info" Acceptance="@this.Acceptance" ShowAcceptanceMetadata="@true" />
</div>
</DialogContent>
<DialogActions>
<MudStack Row="true" Justify="Justify.SpaceBetween" Class="pa-4" Style="width: 100%;">
<MudButton OnClick="@this.Reject"
Variant="Variant.Filled"
Color="Color.Error"
Size="Size.Large">
@this.Info.RejectButtonText
</MudButton>
<MudButton OnClick="@this.Accept"
Variant="Variant.Filled"
Color="Color.Success"
Size="Size.Large">
@this.Info.AcceptButtonText
</MudButton>
</MudStack>
</DialogActions>
</MudDialog>
22 changes: 22 additions & 0 deletions app/MindWork AI Studio/Dialogs/MandatoryInfoDialog.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using AIStudio.Components;
using AIStudio.Settings.DataModel;

using Microsoft.AspNetCore.Components;

namespace AIStudio.Dialogs;

public partial class MandatoryInfoDialog : MSGComponentBase
{
[CascadingParameter]
private IMudDialogInstance MudDialog { get; set; } = null!;

[Parameter]
public DataMandatoryInfo Info { get; set; } = new();

[Parameter]
public DataMandatoryInfoAcceptance? Acceptance { get; set; }

private void Accept() => this.MudDialog.Close(DialogResult.Ok(true));

private void Reject() => this.MudDialog.Close(DialogResult.Ok(false));
}
93 changes: 91 additions & 2 deletions app/MindWork AI Studio/Layout/MainLayout.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, ILan
private UpdateResponse? currentUpdateResponse;
private MudThemeProvider themeProvider = null!;
private bool useDarkMode;
private bool startupCompleted;
private readonly SemaphoreSlim mandatoryInfoDialogSemaphore = new(1, 1);

private IReadOnlyCollection<NavBarItem> navItems = [];

Expand Down Expand Up @@ -91,8 +93,8 @@ protected override async Task OnInitializedAsync()
this.MessageBus.ApplyFilters(this, [],
[
Event.UPDATE_AVAILABLE, Event.CONFIGURATION_CHANGED, Event.COLOR_THEME_CHANGED, Event.SHOW_ERROR,
Event.SHOW_ERROR, Event.SHOW_WARNING, Event.SHOW_SUCCESS, Event.STARTUP_PLUGIN_SYSTEM,
Event.PLUGINS_RELOADED, Event.INSTALL_UPDATE,
Event.SHOW_WARNING, Event.SHOW_SUCCESS, Event.STARTUP_PLUGIN_SYSTEM, Event.PLUGINS_RELOADED,
Event.INSTALL_UPDATE, Event.STARTUP_COMPLETED,
]);

// Set the snackbar for the update service:
Expand Down Expand Up @@ -174,6 +176,8 @@ await this.InvokeAsync(async () =>
await this.UpdateThemeConfiguration();
this.LoadNavItems();
this.StateHasChanged();
if (this.startupCompleted)
_ = this.EnsureMandatoryInfosAcceptedAsync();
break;

case Event.COLOR_THEME_CHANGED:
Expand Down Expand Up @@ -261,6 +265,13 @@ await this.InvokeAsync(async () =>
this.LoadNavItems();

await this.InvokeAsync(this.StateHasChanged);
if (this.startupCompleted)
_ = this.EnsureMandatoryInfosAcceptedAsync();
break;

case Event.STARTUP_COMPLETED:
this.startupCompleted = true;
_ = this.EnsureMandatoryInfosAcceptedAsync();
break;
}
});
Expand Down Expand Up @@ -368,12 +379,90 @@ private async Task UpdateThemeConfiguration()
await this.MessageBus.SendMessage<bool>(this, Event.COLOR_THEME_CHANGED);
this.StateHasChanged();
}

private async Task EnsureMandatoryInfosAcceptedAsync()
{
if (!await this.mandatoryInfoDialogSemaphore.WaitAsync(0))
return;

try
{
while (true)
{
var pendingInfos = this.GetPendingMandatoryInfos().ToList();
if (pendingInfos.Count == 0)
return;

foreach (var info in pendingInfos)
{
var wasAccepted = await this.ShowMandatoryInfoDialog(info);
if (!wasAccepted)
{
await this.RustService.ExitApplication();
return;
}

await this.StoreMandatoryInfoAcceptance(info);
}
}
}
finally
{
this.mandatoryInfoDialogSemaphore.Release();
}
}

private IEnumerable<DataMandatoryInfo> GetPendingMandatoryInfos()
{
return PluginFactory.GetMandatoryInfos()
.Where(info =>
{
var acceptance = this.SettingsManager.ConfigurationData.MandatoryInformation.FindAcceptance(info.Id);
return acceptance is null || !string.Equals(acceptance.AcceptedHash, info.AcceptanceHash, StringComparison.Ordinal);
});
}

private async Task<bool> ShowMandatoryInfoDialog(DataMandatoryInfo info)
{
var acceptance = this.SettingsManager.ConfigurationData.MandatoryInformation.FindAcceptance(info.Id);
var dialogParameters = new DialogParameters<MandatoryInfoDialog>
{
{ x => x.Info, info },
{ x => x.Acceptance, acceptance },
};

var dialogReference = await this.DialogService.ShowAsync<MandatoryInfoDialog>(info.Title, dialogParameters, DialogOptions.BLOCKING_FULLSCREEN);
var dialogResult = await dialogReference.Result;
return dialogResult is { Canceled: false, Data: true };
}

private async Task StoreMandatoryInfoAcceptance(DataMandatoryInfo info)
{
var acceptances = this.SettingsManager.ConfigurationData.MandatoryInformation.Acceptances;
var acceptance = new DataMandatoryInfoAcceptance
{
InfoId = info.Id,
AcceptedVersion = info.VersionText,
AcceptedHash = info.AcceptanceHash,
AcceptedAtUtc = DateTimeOffset.UtcNow,
EnterpriseConfigurationPluginId = info.EnterpriseConfigurationPluginId,
};

var existingIndex = acceptances.FindIndex(item => item.InfoId == info.Id);
if (existingIndex >= 0)
acceptances[existingIndex] = acceptance;
else
acceptances.Add(acceptance);

await this.SettingsManager.StoreSettings();
}

#region Implementation of IDisposable

public void Dispose()
{
this.MessageBus.Unregister(this);
this.mandatoryInfoDialogSemaphore.Dispose();
}

#endregion
Expand Down
12 changes: 12 additions & 0 deletions app/MindWork AI Studio/Pages/Information.razor
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,18 @@
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.EventNote" HeaderText="@T("Changelog")">
<Changelog/>
</ExpansionPanel>

@foreach (var mandatoryInfoPanel in this.mandatoryInfoPanels)
{
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Gavel" HeaderText="@mandatoryInfoPanel.HeaderText">
<MudText Typo="Typo.body2" Class="mb-3">
@string.Format(T("Provided by configuration plugin: {0}"), mandatoryInfoPanel.PluginName)
</MudText>
<MandatoryInfoDisplay Info="@mandatoryInfoPanel.Info"
Acceptance="@mandatoryInfoPanel.Acceptance"
ShowAcceptanceMetadata="@true"/>
</ExpansionPanel>
}

<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Book" HeaderText="@T("Logbook")">
<MudText Typo="Typo.h4">
Expand Down
Loading