Right sidebar nav: Library / Reports / Documentation tabs (WebView2)
The body of the launcher is now a 2-column layout: - Left : swappable content area - Right (200px) : sidebar with 3 nav buttons + active-state highlighting Three pages, all under the same window chrome / footer: 1. **Library** (default) — the existing main view (featured version, other versions list, floating "Vérifier les MAJ" button, copyright). 2. **Reports** — embedded WebView2 navigated to a configurable URL. Default http://localhost/ProserveReport/ which matches the local stats tool installed on each customer machine alongside XAMPP. 3. **Documentation** — WebView2 with a configurable URL, falls back to a placeholder explaining where to set it if empty. Implementation - LocalConfig gains ReportUrl + DocumentationUrl (string). - MainViewModel gains LauncherPage enum + CurrentPage state with Navigate{Library,Report,Documentation}Command. ReportUri / DocumentationUri parse the strings to Uri for WebView2.Source. - Theme.xaml: NavButton style (transparent, left-aligned, hover darken, active state highlighted via Tag bool + accent left-border). - InverseBoolToVisibilityConverter added (true → Collapsed) for the documentation placeholder fallback. - Microsoft.Web.WebView2 NuGet (1.0.2792.45). Runtime is pre-installed on Win11 and auto-pushed via Windows Update on Win10. If absent, WebView2 surfaces an error which the user sees inline. - Settings → Avancés → Serveur extended with the two URL fields. - Strings.cs: NavLibrary / NavReport / NavDocumentation, SettingsReportUrl / SettingsDocsUrl, DocsPlaceholder, WebViewLoadError. Sidebar localized in 5 languages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,11 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
|
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
|
||||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||||
|
<!-- WebView2 (Edge Chromium) pour les onglets Report et Documentation.
|
||||||
|
Le runtime est pré-installé sur Win11 et auto-mis-à-jour via Windows
|
||||||
|
Update sur Win10 récent. Si absent, le contrôle affiche une erreur
|
||||||
|
et on aiguille l'user vers https://go.microsoft.com/fwlink/p/?LinkId=2124703 -->
|
||||||
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2792.45" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace PSLauncher.App.Resources;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inverse de <see cref="System.Windows.Controls.BooleanToVisibilityConverter"/> : true → Collapsed, false → Visible.
|
||||||
|
/// Utile pour afficher un placeholder quand un binding bool est false (ex. "DocumentationUrl est vide").
|
||||||
|
/// </summary>
|
||||||
|
public sealed class InverseBoolToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
=> value is bool b && b ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
|
||||||
|
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
=> value is Visibility v && v != Visibility.Visible;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns:res="clr-namespace:PSLauncher.App.Resources">
|
xmlns:res="clr-namespace:PSLauncher.App.Resources">
|
||||||
|
|
||||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
|
||||||
|
<res:InverseBoolToVisibilityConverter x:Key="InverseBoolToVisibility" />
|
||||||
|
|
||||||
<!-- Custom font Pirulen pour les titres de marque -->
|
<!-- Custom font Pirulen pour les titres de marque -->
|
||||||
<FontFamily x:Key="Font.Brand">pack://application:,,,/Resources/#Pirulen</FontFamily>
|
<FontFamily x:Key="Font.Brand">pack://application:,,,/Resources/#Pirulen</FontFamily>
|
||||||
@@ -72,6 +73,47 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
NavButton : item de la sidebar de droite (Library / Report / Documentation).
|
||||||
|
Plein-largeur, alignement à gauche, pas de bordure, surligné quand actif
|
||||||
|
via Tag (bool) qui est lié à IsLibrary/IsReport/IsDocumentation.
|
||||||
|
-->
|
||||||
|
<Style x:Key="NavButton" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource Brush.Text.Secondary}" />
|
||||||
|
<Setter Property="FontSize" Value="13" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
<Setter Property="Padding" Value="20,12" />
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||||
|
<Setter Property="BorderThickness" Value="0" />
|
||||||
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border x:Name="Bd"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
BorderThickness="3,0,0,0"
|
||||||
|
BorderBrush="Transparent"
|
||||||
|
Padding="{TemplateBinding Padding}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter TargetName="Bd" Property="Background" Value="#1A1F2A" />
|
||||||
|
</Trigger>
|
||||||
|
<!-- "Tag" est utilisé comme flag actif (IsLibrary/IsReport/IsDocumentation) -->
|
||||||
|
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag}" Value="True">
|
||||||
|
<Setter TargetName="Bd" Property="Background" Value="#1F2937" />
|
||||||
|
<Setter TargetName="Bd" Property="BorderBrush" Value="{StaticResource Brush.Accent}" />
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource Brush.Text.Primary}" />
|
||||||
|
</DataTrigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style x:Key="PrimaryButton" TargetType="Button">
|
<Style x:Key="PrimaryButton" TargetType="Button">
|
||||||
<Setter Property="Background" Value="{StaticResource Brush.Play}" />
|
<Setter Property="Background" Value="{StaticResource Brush.Play}" />
|
||||||
<Setter Property="Foreground" Value="White" />
|
<Setter Property="Foreground" Value="White" />
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ using PSLauncher.Models;
|
|||||||
|
|
||||||
namespace PSLauncher.App.ViewModels;
|
namespace PSLauncher.App.ViewModels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Onglets affichés dans la sidebar droite du launcher. Chacun correspond à un
|
||||||
|
/// bloc de contenu visible/caché dans la fenêtre principale.
|
||||||
|
/// </summary>
|
||||||
|
public enum LauncherPage { Library, Report, Documentation }
|
||||||
|
|
||||||
public sealed partial class MainViewModel : ObservableObject
|
public sealed partial class MainViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
private readonly IInstallationRegistry _registry;
|
private readonly IInstallationRegistry _registry;
|
||||||
@@ -68,6 +74,34 @@ public sealed partial class MainViewModel : ObservableObject
|
|||||||
|
|
||||||
[ObservableProperty] private double _progressPercent;
|
[ObservableProperty] private double _progressPercent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Onglet actuellement actif dans la sidebar droite. La UI montre le bon bloc
|
||||||
|
/// via les converters IsLibrary / IsReport / IsDocumentation. Default = Library
|
||||||
|
/// pour que le launcher s'ouvre directement sur l'écran principal.
|
||||||
|
/// </summary>
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsLibrary))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsReport))]
|
||||||
|
[NotifyPropertyChangedFor(nameof(IsDocumentation))]
|
||||||
|
private LauncherPage _currentPage = LauncherPage.Library;
|
||||||
|
|
||||||
|
public bool IsLibrary => CurrentPage == LauncherPage.Library;
|
||||||
|
public bool IsReport => CurrentPage == LauncherPage.Report;
|
||||||
|
public bool IsDocumentation => CurrentPage == LauncherPage.Documentation;
|
||||||
|
|
||||||
|
/// <summary>URL résolue pour le panneau Reports. WebView2.Source attend un Uri.</summary>
|
||||||
|
public Uri? ReportUri => TryParseUri(_config.ReportUrl);
|
||||||
|
/// <summary>URL résolue pour le panneau Documentation. Null si non configurée.</summary>
|
||||||
|
public Uri? DocumentationUri => TryParseUri(_config.DocumentationUrl);
|
||||||
|
public bool HasDocumentationUrl => DocumentationUri is not null;
|
||||||
|
|
||||||
|
private static Uri? TryParseUri(string? s)
|
||||||
|
=> !string.IsNullOrWhiteSpace(s) && Uri.TryCreate(s, UriKind.Absolute, out var u) ? u : null;
|
||||||
|
|
||||||
|
[RelayCommand] private void NavigateLibrary() => CurrentPage = LauncherPage.Library;
|
||||||
|
[RelayCommand] private void NavigateReport() => CurrentPage = LauncherPage.Report;
|
||||||
|
[RelayCommand] private void NavigateDocumentation() => CurrentPage = LauncherPage.Documentation;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
[NotifyPropertyChangedFor(nameof(FooterText))]
|
[NotifyPropertyChangedFor(nameof(FooterText))]
|
||||||
[NotifyPropertyChangedFor(nameof(FooterVisibility))]
|
[NotifyPropertyChangedFor(nameof(FooterVisibility))]
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ public sealed partial class SettingsViewModel : ObservableObject
|
|||||||
[ObservableProperty] private string _serverBaseUrl;
|
[ObservableProperty] private string _serverBaseUrl;
|
||||||
[ObservableProperty] private string _installRoot;
|
[ObservableProperty] private string _installRoot;
|
||||||
[ObservableProperty] private string _language;
|
[ObservableProperty] private string _language;
|
||||||
|
[ObservableProperty] private string _reportUrl;
|
||||||
|
[ObservableProperty] private string _documentationUrl;
|
||||||
|
|
||||||
// ----- DB Migration settings -----
|
// ----- DB Migration settings -----
|
||||||
[ObservableProperty] private string _dbHost;
|
[ObservableProperty] private string _dbHost;
|
||||||
@@ -138,6 +140,8 @@ public sealed partial class SettingsViewModel : ObservableObject
|
|||||||
_serverBaseUrl = config.ServerBaseUrl;
|
_serverBaseUrl = config.ServerBaseUrl;
|
||||||
_installRoot = config.InstallRoot;
|
_installRoot = config.InstallRoot;
|
||||||
_language = string.IsNullOrWhiteSpace(config.Language) ? "auto" : config.Language;
|
_language = string.IsNullOrWhiteSpace(config.Language) ? "auto" : config.Language;
|
||||||
|
_reportUrl = config.ReportUrl;
|
||||||
|
_documentationUrl = config.DocumentationUrl;
|
||||||
|
|
||||||
_dbHost = config.Database.Host;
|
_dbHost = config.Database.Host;
|
||||||
_dbPort = config.Database.Port;
|
_dbPort = config.Database.Port;
|
||||||
@@ -252,6 +256,8 @@ public sealed partial class SettingsViewModel : ObservableObject
|
|||||||
_config.ServerBaseUrl = ServerBaseUrl.TrimEnd('/');
|
_config.ServerBaseUrl = ServerBaseUrl.TrimEnd('/');
|
||||||
_config.InstallRoot = InstallRoot;
|
_config.InstallRoot = InstallRoot;
|
||||||
_config.Language = Language ?? "auto";
|
_config.Language = Language ?? "auto";
|
||||||
|
_config.ReportUrl = ReportUrl?.Trim() ?? "";
|
||||||
|
_config.DocumentationUrl = DocumentationUrl?.Trim() ?? "";
|
||||||
|
|
||||||
// DB settings
|
// DB settings
|
||||||
_config.Database.Host = DbHost.Trim();
|
_config.Database.Host = DbHost.Trim();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
xmlns:vm="clr-namespace:PSLauncher.App.ViewModels"
|
xmlns:vm="clr-namespace:PSLauncher.App.ViewModels"
|
||||||
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
xmlns:loc="clr-namespace:PSLauncher.Core.Localization;assembly=PSLauncher.Core"
|
||||||
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
|
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
|
||||||
|
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
||||||
Title="PROSERVE Launcher"
|
Title="PROSERVE Launcher"
|
||||||
Icon="pack://application:,,,/Resources/favicon.ico"
|
Icon="pack://application:,,,/Resources/favicon.ico"
|
||||||
Background="Black"
|
Background="Black"
|
||||||
@@ -315,8 +316,23 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Body : Grid pour pouvoir superposer le bouton flottant "Vérifier les MAJ" -->
|
<!--
|
||||||
|
Body : grid 2 colonnes — content area swap-pable à gauche, sidebar de
|
||||||
|
navigation fixe à droite. Le content area lui-même est un Grid qui
|
||||||
|
superpose plusieurs blocs (Library / Report / Documentation) gérés
|
||||||
|
par leur Visibility liée à CurrentPage.
|
||||||
|
-->
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="200" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- ============== Content area (col 0, swap par CurrentPage) ============== -->
|
||||||
|
<Grid Grid.Column="0">
|
||||||
|
|
||||||
|
<!-- ====================== LIBRARY PAGE ====================== -->
|
||||||
|
<Grid Visibility="{Binding IsLibrary, Converter={StaticResource BoolToVisibility}}">
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel Margin="32,28">
|
<StackPanel Margin="32,28">
|
||||||
|
|
||||||
@@ -548,6 +564,67 @@
|
|||||||
Foreground="White" />
|
Foreground="White" />
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<!-- ====================== END LIBRARY PAGE ====================== -->
|
||||||
|
|
||||||
|
<!-- ====================== REPORT PAGE (WebView2) ====================== -->
|
||||||
|
<Grid Background="{StaticResource Brush.Bg.Window}"
|
||||||
|
Visibility="{Binding IsReport, Converter={StaticResource BoolToVisibility}}">
|
||||||
|
<wv2:WebView2 x:Name="ReportWebView"
|
||||||
|
Source="{Binding ReportUri, Mode=OneWay}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- ====================== DOCUMENTATION PAGE ====================== -->
|
||||||
|
<Grid Background="{StaticResource Brush.Bg.Window}"
|
||||||
|
Visibility="{Binding IsDocumentation, Converter={StaticResource BoolToVisibility}}">
|
||||||
|
<!-- WebView2 si une URL est configurée, sinon un placeholder explicatif -->
|
||||||
|
<wv2:WebView2 x:Name="DocsWebView"
|
||||||
|
Source="{Binding DocumentationUri, Mode=OneWay}"
|
||||||
|
Visibility="{Binding HasDocumentationUrl, Converter={StaticResource BoolToVisibility}}" />
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.DocsPlaceholder}"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||||
|
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||||
|
FontSize="14" TextAlignment="Center" TextWrapping="Wrap"
|
||||||
|
MaxWidth="500"
|
||||||
|
Visibility="{Binding HasDocumentationUrl, Converter={StaticResource InverseBoolToVisibility}}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
<!-- ============== END Content area ============== -->
|
||||||
|
|
||||||
|
<!-- ============== Right sidebar : nav buttons ============== -->
|
||||||
|
<Border Grid.Column="1"
|
||||||
|
Background="#0A0A0E"
|
||||||
|
BorderBrush="{StaticResource Brush.Border}"
|
||||||
|
BorderThickness="1,0,0,0">
|
||||||
|
<StackPanel Orientation="Vertical" Margin="0,16,0,0">
|
||||||
|
<!-- Style des boutons définis dans Theme.xaml (NavButton) -->
|
||||||
|
<Button Style="{StaticResource NavButton}"
|
||||||
|
Command="{Binding NavigateLibraryCommand}"
|
||||||
|
Tag="{Binding IsLibrary}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="📚" FontSize="16" Margin="0,0,12,0" VerticalAlignment="Center" />
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.NavLibrary}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource NavButton}"
|
||||||
|
Command="{Binding NavigateReportCommand}"
|
||||||
|
Tag="{Binding IsReport}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="📊" FontSize="16" Margin="0,0,12,0" VerticalAlignment="Center" />
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.NavReport}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource NavButton}"
|
||||||
|
Command="{Binding NavigateDocumentationCommand}"
|
||||||
|
Tag="{Binding IsDocumentation}">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="📖" FontSize="16" Margin="0,0,12,0" VerticalAlignment="Center" />
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.NavDocumentation}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<!-- Footer : visible uniquement quand busy / status à afficher.
|
<!-- Footer : visible uniquement quand busy / status à afficher.
|
||||||
Le bouton "Vérifier les MAJ" a été déplacé en flottant au-dessus du body. -->
|
Le bouton "Vérifier les MAJ" a été déplacé en flottant au-dessus du body. -->
|
||||||
|
|||||||
@@ -213,6 +213,23 @@
|
|||||||
<TextBlock Text="{Binding ConnectionStatus}"
|
<TextBlock Text="{Binding ConnectionStatus}"
|
||||||
Foreground="{StaticResource Brush.Text.Secondary}"
|
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||||
FontSize="12" Margin="0,8,0,0" TextWrapping="Wrap" />
|
FontSize="12" Margin="0,8,0,0" TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<!-- URLs des onglets latéraux Report / Documentation -->
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.SettingsReportUrl}"
|
||||||
|
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||||
|
FontSize="12" Margin="0,16,0,4" />
|
||||||
|
<TextBox Text="{Binding ReportUrl, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
|
||||||
|
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
|
||||||
|
FontFamily="Consolas" />
|
||||||
|
|
||||||
|
<TextBlock Text="{x:Static loc:Strings.SettingsDocsUrl}"
|
||||||
|
Foreground="{StaticResource Brush.Text.Secondary}"
|
||||||
|
FontSize="12" Margin="0,12,0,4" />
|
||||||
|
<TextBox Text="{Binding DocumentationUrl, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Background="#1A1A20" Foreground="{StaticResource Brush.Text.Primary}"
|
||||||
|
BorderBrush="{StaticResource Brush.Border}" BorderThickness="1" Padding="8"
|
||||||
|
FontFamily="Consolas" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|||||||
@@ -152,6 +152,28 @@ public static class Strings
|
|||||||
"تطبيق الترقيات تلقائياً عند تثبيت نسخة جديدة"
|
"تطبيق الترقيات تلقائياً عند تثبيت نسخة جديدة"
|
||||||
);
|
);
|
||||||
public static string SettingsDbReplay => T("🔁 Rejouer les migrations", "🔁 Replay migrations", "🔁 重新执行迁移", "🔁 เรียกใช้การโยกย้ายอีกครั้ง", "🔁 إعادة تشغيل الترقيات");
|
public static string SettingsDbReplay => T("🔁 Rejouer les migrations", "🔁 Replay migrations", "🔁 重新执行迁移", "🔁 เรียกใช้การโยกย้ายอีกครั้ง", "🔁 إعادة تشغيل الترقيات");
|
||||||
|
// ==================== RIGHT NAV SIDEBAR ====================
|
||||||
|
public static string NavLibrary => T("Bibliothèque", "Library", "库", "ห้องสมุด", "المكتبة");
|
||||||
|
public static string NavReport => T("Statistiques", "Reports", "统计", "รายงาน", "التقارير");
|
||||||
|
public static string NavDocumentation => T("Documentation", "Documentation","文档", "เอกสาร", "التوثيق");
|
||||||
|
|
||||||
|
public static string SettingsReportUrl => T("URL de l'outil de reporting local", "Local reporting tool URL", "本地报告工具 URL", "URL ของเครื่องมือรายงานในเครื่อง", "عنوان أداة التقارير المحلية");
|
||||||
|
public static string SettingsDocsUrl => T("URL de la documentation", "Documentation URL", "文档 URL", "URL ของเอกสาร", "عنوان التوثيق");
|
||||||
|
public static string DocsPlaceholder => T(
|
||||||
|
"Aucune URL de documentation configurée.\n\nVa dans Paramètres → Avancés → Base de données pour pointer vers la documentation locale ou en ligne.",
|
||||||
|
"No documentation URL configured.\n\nGo to Settings → Advanced → Database to point to local or online documentation.",
|
||||||
|
"未配置文档 URL。\n\n前往 设置 → 高级 → 数据库 以指向本地或在线文档。",
|
||||||
|
"ยังไม่ได้กำหนด URL เอกสาร\n\nไปที่ การตั้งค่า → ขั้นสูง → ฐานข้อมูล เพื่อชี้ไปยังเอกสารในเครื่องหรือออนไลน์",
|
||||||
|
"لم يتم تكوين عنوان التوثيق.\n\nاذهب إلى الإعدادات → متقدم → قاعدة البيانات للإشارة إلى التوثيق المحلي أو عبر الإنترنت."
|
||||||
|
);
|
||||||
|
public static string WebViewLoadError(string url, string detail) => T(
|
||||||
|
$"Impossible de charger {url}\n\n{detail}\n\nVérifie que XAMPP est démarré et que l'URL est correcte (Paramètres → Avancés).",
|
||||||
|
$"Could not load {url}\n\n{detail}\n\nCheck that XAMPP is running and the URL is correct (Settings → Advanced).",
|
||||||
|
$"无法加载 {url}\n\n{detail}\n\n请检查 XAMPP 是否正在运行以及 URL 是否正确(设置 → 高级)。",
|
||||||
|
$"ไม่สามารถโหลด {url}\n\n{detail}\n\nตรวจสอบว่า XAMPP กำลังทำงานและ URL ถูกต้อง (ตั้งค่า → ขั้นสูง)",
|
||||||
|
$"تعذر تحميل {url}\n\n{detail}\n\nتأكد من تشغيل XAMPP وأن العنوان صحيح (الإعدادات → متقدم)."
|
||||||
|
);
|
||||||
|
|
||||||
public static string SettingsAdvanced => T(
|
public static string SettingsAdvanced => T(
|
||||||
"▸ PARAMÈTRES AVANCÉS (serveur, installation, base de données, logs)",
|
"▸ PARAMÈTRES AVANCÉS (serveur, installation, base de données, logs)",
|
||||||
"▸ ADVANCED SETTINGS (server, installation, database, logs)",
|
"▸ ADVANCED SETTINGS (server, installation, database, logs)",
|
||||||
|
|||||||
@@ -28,6 +28,21 @@ public sealed class LocalConfig
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool VerifyDownloadHash { get; set; } = true;
|
public bool VerifyDownloadHash { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// URL de l'outil de reporting local (page web embarquée dans le launcher,
|
||||||
|
/// onglet "Report"). Par défaut pointe vers l'install standard ASTERION
|
||||||
|
/// dans XAMPP. Surchargeable dans Settings → Avancés.
|
||||||
|
/// </summary>
|
||||||
|
public string ReportUrl { get; set; } = "http://localhost/ProserveReport/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// URL de la documentation locale (onglet "Documentation"). Vide par défaut :
|
||||||
|
/// l'utilisateur peut pointer vers une URL locale ou web. Si vide, l'onglet
|
||||||
|
/// affiche un placeholder avec les liens vers les fichiers .pptx du dossier
|
||||||
|
/// d'install du launcher.
|
||||||
|
/// </summary>
|
||||||
|
public string DocumentationUrl { get; set; } = string.Empty;
|
||||||
|
|
||||||
public LicenseConfig License { get; set; } = new();
|
public LicenseConfig License { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user