201 lines
7.2 KiB
Text
201 lines
7.2 KiB
Text
|
|
@page "/settings"
|
||
|
|
@inject IDbContextFactory<AppDbContext> ContextFactory
|
||
|
|
@inject IOllamaService OllamaService
|
||
|
|
@inject OllamaSettings OllamaConfig
|
||
|
|
@inject NavigationManager Navigation
|
||
|
|
@inject IJSRuntime JSRuntime
|
||
|
|
@inject IProjectService ProjectService
|
||
|
|
|
||
|
|
<PageTitle>Einstellungen - Author Buddy</PageTitle>
|
||
|
|
|
||
|
|
<div class="settings-page">
|
||
|
|
|
||
|
|
<div class="settings-section">
|
||
|
|
<h3 class="settings-section-title">Modelle</h3>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="ragModel">RAG-Modell (Faktenabfrage):</label>
|
||
|
|
<select id="ragModel" @bind="ragModel">
|
||
|
|
@if (availableModels.Count == 0)
|
||
|
|
{
|
||
|
|
<option value="">Keine Modelle gefunden</option>
|
||
|
|
}
|
||
|
|
@foreach (var m in availableModels)
|
||
|
|
{
|
||
|
|
<option value="@m.Model1">@m.Model1</option>
|
||
|
|
}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="styleModel">Stil-Modell (Lektorat):</label>
|
||
|
|
<select id="styleModel" @bind="styleModel">
|
||
|
|
@if (availableModels.Count == 0)
|
||
|
|
{
|
||
|
|
<option value="">Keine Modelle gefunden</option>
|
||
|
|
}
|
||
|
|
@foreach (var m in availableModels)
|
||
|
|
{
|
||
|
|
<option value="@m.Model1">@m.Model1</option>
|
||
|
|
}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="spellingModel">Rechtschreibprüfungs-Modell:</label>
|
||
|
|
<select id="spellingModel" @bind="spellingModel">
|
||
|
|
@if (availableModels.Count == 0)
|
||
|
|
{
|
||
|
|
<option value="">Keine Modelle gefunden</option>
|
||
|
|
}
|
||
|
|
@foreach (var m in availableModels)
|
||
|
|
{
|
||
|
|
<option value="@m.Model1">@m.Model1</option>
|
||
|
|
}
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="settings-section">
|
||
|
|
<h3 class="settings-section-title">Ollama Server</h3>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="ollamaUrl">Server-URL:</label>
|
||
|
|
<input id="ollamaUrl" @bind="ollamaUrl" placeholder="http://localhost:11434" />
|
||
|
|
<div class="form-hint">Adresse des Ollama-Servers (z. B. http://192.168.1.100:11434)</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="settings-section">
|
||
|
|
<h3 class="settings-section-title">Design</h3>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="themeSelect">Theme:</label>
|
||
|
|
<select id="themeSelect" @bind="selectedTheme">
|
||
|
|
<option value="light">Hell</option>
|
||
|
|
<option value="dark">Dunkel</option>
|
||
|
|
<option value="w95">W95 (Retro)</option>
|
||
|
|
</select>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="settings-section">
|
||
|
|
<h3 class="settings-section-title">Neues Projekt</h3>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="projectName">Projektname:</label>
|
||
|
|
<input id="projectName" @bind="newProjectName" placeholder="Projektname" />
|
||
|
|
<div class="form-hint">Der Projektordner wird in "Dokumente\AuthorBuddy\" erstellt.</div>
|
||
|
|
</div>
|
||
|
|
<button @onclick="CreateProject" disabled="@(string.IsNullOrWhiteSpace(newProjectName))">Projekt erstellen</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="form-actions">
|
||
|
|
<button class="primary" @onclick="SaveSettings">Speichern</button>
|
||
|
|
<button @onclick='() => Navigation.NavigateTo("/")'>Abbrechen</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@if (!string.IsNullOrEmpty(statusMessage))
|
||
|
|
{
|
||
|
|
<div class="settings-status">@statusMessage</div>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@code {
|
||
|
|
private string ragModel = "llama3.2";
|
||
|
|
private string styleModel = "llama3.2";
|
||
|
|
private string spellingModel = "phi3:mini";
|
||
|
|
private string selectedTheme = "light";
|
||
|
|
private string ollamaUrl = "http://localhost:11434";
|
||
|
|
private string newProjectName = string.Empty;
|
||
|
|
private string statusMessage = string.Empty;
|
||
|
|
private List<Ollama.Model> availableModels = new();
|
||
|
|
|
||
|
|
protected override async Task OnInitializedAsync()
|
||
|
|
{
|
||
|
|
await using var context = await ContextFactory.CreateDbContextAsync();
|
||
|
|
|
||
|
|
ragModel = await GetSettingAsync(context, "ollama_rag_model") ?? "llama3.2";
|
||
|
|
styleModel = await GetSettingAsync(context, "ollama_style_model") ?? "llama3.2";
|
||
|
|
spellingModel = await GetSettingAsync(context, "ollama_spelling_model") ?? "phi3:mini";
|
||
|
|
selectedTheme = await GetSettingAsync(context, "theme") ?? "light";
|
||
|
|
ollamaUrl = await GetSettingAsync(context, "ollama_url") ?? "http://localhost:11434";
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var models = await OllamaService.GetLocalModelsAsync();
|
||
|
|
availableModels = models.ToList();
|
||
|
|
}
|
||
|
|
catch
|
||
|
|
{
|
||
|
|
availableModels = new();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static async Task<string?> GetSettingAsync(AppDbContext context, string key)
|
||
|
|
{
|
||
|
|
var setting = await context.Settings.FindAsync(key);
|
||
|
|
return setting?.Value;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static async Task SaveSettingAsync(AppDbContext context, string key, string value)
|
||
|
|
{
|
||
|
|
var existing = await context.Settings.FindAsync(key);
|
||
|
|
if (existing != null)
|
||
|
|
{
|
||
|
|
existing.Value = value;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
context.Settings.Add(new SettingEntity { Key = key, Value = value });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task SaveSettings()
|
||
|
|
{
|
||
|
|
await using var context = await ContextFactory.CreateDbContextAsync();
|
||
|
|
|
||
|
|
await SaveSettingAsync(context, "ollama_rag_model", ragModel);
|
||
|
|
await SaveSettingAsync(context, "ollama_style_model", styleModel);
|
||
|
|
await SaveSettingAsync(context, "ollama_spelling_model", spellingModel);
|
||
|
|
await SaveSettingAsync(context, "theme", selectedTheme);
|
||
|
|
await SaveSettingAsync(context, "ollama_url", ollamaUrl);
|
||
|
|
|
||
|
|
await context.SaveChangesAsync();
|
||
|
|
|
||
|
|
OllamaConfig.OllamaUrl = ollamaUrl;
|
||
|
|
OllamaConfig.ChatModel = ragModel;
|
||
|
|
OllamaConfig.SpellingModel = spellingModel;
|
||
|
|
await OllamaService.ReconfigureAsync(ollamaUrl);
|
||
|
|
|
||
|
|
statusMessage = "Einstellungen gespeichert.";
|
||
|
|
await ApplyTheme(selectedTheme);
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task CreateProject()
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(newProjectName)) return;
|
||
|
|
|
||
|
|
try
|
||
|
|
{
|
||
|
|
string rootPath = Path.Combine(
|
||
|
|
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
|
||
|
|
"AuthorBuddy",
|
||
|
|
newProjectName);
|
||
|
|
|
||
|
|
await ProjectService.CreateNewProjectAsync(newProjectName, rootPath);
|
||
|
|
statusMessage = $"Projekt '{newProjectName}' erstellt unter: {rootPath}";
|
||
|
|
newProjectName = string.Empty;
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
statusMessage = $"Fehler beim Erstellen: {ex.Message}";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task ApplyTheme(string theme)
|
||
|
|
{
|
||
|
|
await JSRuntime.InvokeVoidAsync("eval",
|
||
|
|
$"document.getElementById('theme-css')?.remove(); " +
|
||
|
|
$"var link = document.createElement('link'); " +
|
||
|
|
$"link.id = 'theme-css'; " +
|
||
|
|
$"link.rel = 'stylesheet'; " +
|
||
|
|
$"link.href = 'css/themes/{theme}.css'; " +
|
||
|
|
$"document.head.appendChild(link);");
|
||
|
|
}
|
||
|
|
}
|