Added CMS_ALIAS and redesign
Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled

This commit is contained in:
Matt Batchelder
2026-02-25 07:36:24 -05:00
parent 5a0199a598
commit 28e79459ac
14 changed files with 578 additions and 246 deletions

Submodule .template-cache/2dc03e2b2b45fef3 updated: af33306def...a6ab3c254b

View File

@@ -2,8 +2,183 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="OTSSignsOrchestrator.Desktop.App"
RequestedThemeVariant="Dark">
<Application.Resources>
<ResourceDictionary>
<!-- ═══ Brand Palette ═══ -->
<Color x:Key="Accent">#D93A00</Color>
<Color x:Key="AccentHover">#E54B14</Color>
<Color x:Key="AccentPressed">#BF3300</Color>
<Color x:Key="AccentSubtle">#2A1A14</Color>
<Color x:Key="BgDeep">#0C0C14</Color>
<Color x:Key="BgBase">#11111B</Color>
<Color x:Key="Surface">#181825</Color>
<Color x:Key="SurfaceRaised">#1E1E2E</Color>
<Color x:Key="SurfaceOverlay">#232336</Color>
<Color x:Key="BorderSubtle">#2A2A40</Color>
<Color x:Key="TextPrimary">#CDD6F4</Color>
<Color x:Key="TextSecondary">#A6ADC8</Color>
<Color x:Key="TextMuted">#6C7086</Color>
<Color x:Key="Green">#4ADE80</Color>
<Color x:Key="Blue">#60A5FA</Color>
<Color x:Key="Purple">#C084FC</Color>
<Color x:Key="Pink">#F472B6</Color>
<Color x:Key="Amber">#FBBF24</Color>
<Color x:Key="Teal">#2DD4BF</Color>
<Color x:Key="Red">#F87171</Color>
<!-- ═══ Brushes ═══ -->
<SolidColorBrush x:Key="AccentBrush" Color="{StaticResource Accent}" />
<SolidColorBrush x:Key="AccentHoverBrush" Color="{StaticResource AccentHover}" />
<SolidColorBrush x:Key="AccentSubtleBrush" Color="{StaticResource AccentSubtle}" />
<SolidColorBrush x:Key="BgDeepBrush" Color="{StaticResource BgDeep}" />
<SolidColorBrush x:Key="BgBaseBrush" Color="{StaticResource BgBase}" />
<SolidColorBrush x:Key="SurfaceBrush" Color="{StaticResource Surface}" />
<SolidColorBrush x:Key="SurfaceRaisedBrush" Color="{StaticResource SurfaceRaised}" />
<SolidColorBrush x:Key="BorderSubtleBrush" Color="{StaticResource BorderSubtle}" />
<SolidColorBrush x:Key="TextPrimaryBrush" Color="{StaticResource TextPrimary}" />
<SolidColorBrush x:Key="TextSecondaryBrush" Color="{StaticResource TextSecondary}" />
<SolidColorBrush x:Key="TextMutedBrush" Color="{StaticResource TextMuted}" />
</ResourceDictionary>
</Application.Resources>
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" />
<!-- ═══ Global Typography ═══ -->
<Style Selector="Window">
<Setter Property="FontFamily" Value="Inter, Segoe UI, Helvetica Neue, sans-serif" />
<Setter Property="Background" Value="{StaticResource BgBaseBrush}" />
</Style>
<!-- ═══ Buttons — base ═══ -->
<Style Selector="Button">
<Setter Property="CornerRadius" Value="6" />
<Setter Property="Padding" Value="14,7" />
<Setter Property="FontSize" Value="13" />
</Style>
<!-- Accent button -->
<Style Selector="Button.accent">
<Setter Property="Background" Value="{StaticResource AccentBrush}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontWeight" Value="SemiBold" />
</Style>
<Style Selector="Button.accent:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="{StaticResource AccentHoverBrush}" />
<Setter Property="Foreground" Value="White" />
</Style>
<!-- Danger button -->
<Style Selector="Button.danger">
<Setter Property="Background" Value="#7F1D1D" />
<Setter Property="Foreground" Value="#FCA5A5" />
</Style>
<Style Selector="Button.danger:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="#991B1B" />
<Setter Property="Foreground" Value="#FCA5A5" />
</Style>
<!-- ═══ TextBox ═══ -->
<Style Selector="TextBox">
<Setter Property="CornerRadius" Value="6" />
</Style>
<!-- ═══ ComboBox ═══ -->
<Style Selector="ComboBox">
<Setter Property="CornerRadius" Value="6" />
</Style>
<!-- ═══ Card border ═══ -->
<Style Selector="Border.card">
<Setter Property="Background" Value="{StaticResource SurfaceRaisedBrush}" />
<Setter Property="CornerRadius" Value="10" />
<Setter Property="Padding" Value="20" />
<Setter Property="BorderBrush" Value="{StaticResource BorderSubtleBrush}" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<!-- ═══ Toolbar border ═══ -->
<Style Selector="Border.toolbar">
<Setter Property="Background" Value="{StaticResource SurfaceRaisedBrush}" />
<Setter Property="CornerRadius" Value="10" />
<Setter Property="Padding" Value="14,10" />
<Setter Property="BorderBrush" Value="{StaticResource BorderSubtleBrush}" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<!-- ═══ Sidebar ListBox ═══ -->
<Style Selector="ListBox.sidebar">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="8,0" />
</Style>
<Style Selector="ListBox.sidebar ListBoxItem">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Margin" Value="0,1" />
<Setter Property="Padding" Value="14,10" />
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}" />
</Style>
<Style Selector="ListBox.sidebar ListBoxItem:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="#1E1E30" />
</Style>
<Style Selector="ListBox.sidebar ListBoxItem:selected /template/ ContentPresenter">
<Setter Property="Background" Value="{StaticResource AccentSubtleBrush}" />
</Style>
<Style Selector="ListBox.sidebar ListBoxItem:selected">
<Setter Property="Foreground" Value="#F0F0F8" />
</Style>
<!-- ═══ DataGrid ═══ -->
<Style Selector="DataGrid">
<Setter Property="CornerRadius" Value="8" />
<Setter Property="BorderBrush" Value="{StaticResource BorderSubtleBrush}" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<!-- ═══ Page header ═══ -->
<Style Selector="TextBlock.pageTitle">
<Setter Property="FontSize" Value="22" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}" />
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
<Style Selector="TextBlock.pageSubtitle">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="{StaticResource TextMutedBrush}" />
<Setter Property="Margin" Value="0,0,0,16" />
</Style>
<Style Selector="TextBlock.sectionTitle">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
<!-- ═══ Separator ═══ -->
<Style Selector="Separator">
<Setter Property="Background" Value="{StaticResource BorderSubtleBrush}" />
<Setter Property="Height" Value="1" />
</Style>
<!-- ═══ Expander ═══ -->
<Style Selector="Expander">
<Setter Property="CornerRadius" Value="8" />
</Style>
<!-- ═══ TabControl ═══ -->
<Style Selector="TabControl">
<Setter Property="Background" Value="Transparent" />
</Style>
<!-- ═══ Status label ═══ -->
<Style Selector="TextBlock.status">
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="{StaticResource TextMutedBrush}" />
</Style>
</Application.Styles>
</Application>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@@ -37,6 +37,10 @@
<ProjectReference Include="..\OTSSignsOrchestrator.Core\OTSSignsOrchestrator.Core.csproj" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@@ -5,95 +5,110 @@
x:DataType="vm:CreateInstanceViewModel">
<ScrollViewer>
<Grid ColumnDefinitions="1*,16,1*" Margin="16,12">
<Grid ColumnDefinitions="1*,20,1*" Margin="0,0,8,16">
<!-- ══ LEFT COLUMN — inputs ══ -->
<StackPanel Grid.Column="0" Spacing="8">
<TextBlock Text="Create New Instance" FontSize="20" FontWeight="Bold" Margin="0,0,0,12" />
<StackPanel Grid.Column="0" Spacing="10">
<TextBlock Text="Create New Instance" Classes="pageTitle" />
<TextBlock Text="Deploy a new CMS stack to a Docker Swarm host" Classes="pageSubtitle" />
<!-- SSH Host -->
<TextBlock Text="Deploy to SSH Host" FontSize="12" />
<ComboBox ItemsSource="{Binding AvailableHosts}"
SelectedItem="{Binding SelectedSshHost}"
PlaceholderText="Select SSH Host..."
HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Separator Margin="0,8" />
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="Target Host" FontSize="13" FontWeight="SemiBold"
Foreground="{StaticResource AccentBrush}" />
<ComboBox ItemsSource="{Binding AvailableHosts}"
SelectedItem="{Binding SelectedSshHost}"
PlaceholderText="Select SSH Host..."
HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Border>
<!-- Core fields -->
<TextBlock Text="Customer Name" FontSize="12" />
<TextBox Text="{Binding CustomerName}" Watermark="e.g. Acme Corp" />
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="Customer Details" FontSize="13" FontWeight="SemiBold"
Foreground="#60A5FA" />
<TextBlock Text="Abbreviation (3 letters)" FontSize="12" />
<TextBox Text="{Binding CustomerAbbrev}"
Watermark="e.g. acm"
MaxLength="3" />
<TextBlock Text="Customer Name" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding CustomerName}" Watermark="e.g. Acme Corp" />
<Separator Margin="0,12" />
<TextBlock Text="Abbreviation (3 letters)" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding CustomerAbbrev}"
Watermark="e.g. acm"
MaxLength="3" />
</StackPanel>
</Border>
<!-- Pangolin / Newt (optional) -->
<Expander Header="Pangolin / Newt credentials (optional)">
<StackPanel Spacing="8" Margin="0,8,0,0">
<TextBlock Text="Newt ID" FontSize="12" />
<TextBox Text="{Binding NewtId}" Watermark="(from Pangolin dashboard)" />
<Border Classes="card" Margin="0,8,0,0">
<StackPanel Spacing="8">
<TextBlock Text="Newt ID" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NewtId}" Watermark="(from Pangolin dashboard)" />
<TextBlock Text="Newt Secret" FontSize="12" />
<TextBox Text="{Binding NewtSecret}" PasswordChar="●" Watermark="(from Pangolin dashboard)" />
</StackPanel>
<TextBlock Text="Newt Secret" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NewtSecret}" PasswordChar="●" Watermark="(from Pangolin dashboard)" />
</StackPanel>
</Border>
</Expander>
<!-- NFS volume settings (per-instance, defaults from global settings) -->
<!-- NFS volume settings -->
<Expander Header="NFS volume settings">
<StackPanel Spacing="8" Margin="0,8,0,0">
<TextBlock Text="NFS Server" FontSize="12" />
<TextBox Text="{Binding NfsServer}" Watermark="e.g. 192.168.1.100" />
<Border Classes="card" Margin="0,8,0,0">
<StackPanel Spacing="8">
<TextBlock Text="NFS Server" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsServer}" Watermark="e.g. 192.168.1.100" />
<TextBlock Text="Export Path" FontSize="12" />
<TextBox Text="{Binding NfsExport}" Watermark="e.g. /srv/nfs" />
<TextBlock Text="Export Path" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsExport}" Watermark="e.g. /srv/nfs" />
<TextBlock Text="Export Folder (optional)" FontSize="12" />
<TextBox Text="{Binding NfsExportFolder}" Watermark="e.g. ots_cms (leave empty for export root)" />
<TextBlock Text="Export Folder (optional)" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsExportFolder}" Watermark="e.g. ots_cms (leave empty for export root)" />
<TextBlock Text="Extra Mount Options" FontSize="12" />
<TextBox Text="{Binding NfsExtraOptions}" Watermark="Additional options after nfsvers=4,proto=tcp" />
</StackPanel>
<TextBlock Text="Extra Mount Options" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsExtraOptions}" Watermark="Additional options after nfsvers=4,proto=tcp" />
</StackPanel>
</Border>
</Expander>
<Separator Margin="0,12" />
<!-- Deploy button + progress -->
<Button Content="Deploy Instance"
Classes="accent"
Command="{Binding DeployCommand}"
IsEnabled="{Binding !IsBusy}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Padding="12,8" FontWeight="SemiBold" />
Padding="14,10" FontSize="14"
Margin="0,8,0,0" />
<!-- Progress bar -->
<Grid ColumnDefinitions="*,Auto" Margin="0,4,0,0"
IsVisible="{Binding IsBusy}">
<ProgressBar Value="{Binding ProgressPercent}"
Maximum="100" Height="6"
CornerRadius="3" />
CornerRadius="3"
Foreground="{StaticResource AccentBrush}" />
<TextBlock Grid.Column="1" Text="{Binding ProgressStep}"
FontSize="11" Foreground="#a6adc8"
Margin="8,0,0,0" VerticalAlignment="Center" />
FontSize="11" Foreground="{StaticResource TextMutedBrush}"
Margin="10,0,0,0" VerticalAlignment="Center" />
</Grid>
<TextBlock Text="{Binding StatusMessage}" FontSize="12" Foreground="#a6adc8"
<TextBlock Text="{Binding StatusMessage}" Classes="status"
Margin="0,4,0,0" TextWrapping="Wrap" />
<!-- Deploy output -->
<TextBox Text="{Binding DeployOutput}" IsReadOnly="True"
AcceptsReturn="True" MaxHeight="260"
FontFamily="Cascadia Mono, Consolas, monospace" FontSize="11"
IsVisible="{Binding DeployOutput.Length}" />
IsVisible="{Binding DeployOutput.Length}"
CornerRadius="8" />
</StackPanel>
<!-- ══ RIGHT COLUMN — tabbed preview ══ -->
@@ -101,64 +116,60 @@
<!-- Tab 1: Resource preview -->
<TabItem Header="Resource Preview">
<Border Background="#1e1e2e"
CornerRadius="8"
Padding="16,14">
<Border Classes="card" Margin="0,8,0,0">
<StackPanel Spacing="6">
<TextBlock Text="Resource Preview" FontSize="14" FontWeight="SemiBold"
Foreground="#cdd6f4" Margin="0,0,0,8" />
Foreground="{StaticResource AccentBrush}" Margin="0,0,0,10" />
<TextBlock Text="Stack" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewStackName}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#89b4fa" Margin="0,0,0,6" />
<TextBlock Text="Stack" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewStackName}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#60A5FA" Margin="0,0,0,8" />
<TextBlock Text="Services" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewServiceWeb}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#a6e3a1" />
<TextBlock Text="{Binding PreviewServiceCache}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#a6e3a1" />
<TextBlock Text="{Binding PreviewServiceChart}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#a6e3a1" />
<TextBlock Text="{Binding PreviewServiceNewt}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#a6e3a1" Margin="0,0,0,6" />
<TextBlock Text="Services" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewServiceWeb}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#4ADE80" />
<TextBlock Text="{Binding PreviewServiceCache}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#4ADE80" />
<TextBlock Text="{Binding PreviewServiceChart}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#4ADE80" />
<TextBlock Text="{Binding PreviewServiceNewt}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#4ADE80" Margin="0,0,0,8" />
<TextBlock Text="Network" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewNetwork}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#94e2d5" Margin="0,0,0,6" />
<TextBlock Text="Network" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewNetwork}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#2DD4BF" Margin="0,0,0,8" />
<TextBlock Text="NFS Volumes" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewVolCustom}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#f5c2e7" />
<TextBlock Text="{Binding PreviewVolBackup}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#f5c2e7" />
<TextBlock Text="{Binding PreviewVolLibrary}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#f5c2e7" />
<TextBlock Text="{Binding PreviewVolUserscripts}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#f5c2e7" />
<TextBlock Text="{Binding PreviewVolCaCerts}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#f5c2e7" Margin="0,0,0,6" />
<TextBlock Text="NFS Volumes" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewVolCustom}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#F472B6" />
<TextBlock Text="{Binding PreviewVolBackup}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#F472B6" />
<TextBlock Text="{Binding PreviewVolLibrary}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#F472B6" />
<TextBlock Text="{Binding PreviewVolUserscripts}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#F472B6" />
<TextBlock Text="{Binding PreviewVolCaCerts}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#F472B6" Margin="0,0,0,8" />
<TextBlock Text="Docker Secrets" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewSecret}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#fab387" />
<TextBlock Text="{Binding PreviewSecretUser}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#fab387" />
<TextBlock Text="{Binding PreviewSecretHost}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#fab387" />
<TextBlock Text="{Binding PreviewSecretPort}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#fab387" Margin="0,0,0,6" />
<TextBlock Text="Docker Secrets" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewSecret}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#FBBF24" />
<TextBlock Text="{Binding PreviewSecretUser}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#FBBF24" />
<TextBlock Text="{Binding PreviewSecretHost}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#FBBF24" />
<TextBlock Text="{Binding PreviewSecretPort}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#FBBF24" Margin="0,0,0,8" />
<TextBlock Text="MySQL Database" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewMySqlDb}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#cba6f7" />
<TextBlock Text="{Binding PreviewMySqlUser}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#cba6f7" Margin="0,0,0,6" />
<TextBlock Text="MySQL Database" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewMySqlDb}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#C084FC" />
<TextBlock Text="{Binding PreviewMySqlUser}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#C084FC" Margin="0,0,0,8" />
<TextBlock Text="CMS URL" FontSize="11" Foreground="#6c7086" />
<TextBlock Text="{Binding PreviewCmsUrl}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#89dceb" />
<TextBlock Text="CMS URL" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding PreviewCmsUrl}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#2DD4BF" />
</StackPanel>
</Border>
</TabItem>
<!-- Tab 2: Rendered compose YML -->
<TabItem Header="Compose YML">
<Border Background="#1e1e2e"
CornerRadius="8"
Padding="16,14">
<Border Classes="card" Margin="0,8,0,0">
<Grid RowDefinitions="Auto,*,Auto">
<!-- Load button -->
<Button Grid.Row="0"
Content="Load / Refresh YML"
Content="Load / Refresh YML"
Command="{Binding LoadYmlPreviewCommand}"
IsEnabled="{Binding !IsLoadingYml}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Padding="10,6"
Margin="0,0,0,8" />
Padding="10,7"
Margin="0,0,0,10" />
<!-- YML text box -->
<TextBox Grid.Row="1"
@@ -168,18 +179,19 @@
FontFamily="Cascadia Mono, Consolas, monospace"
FontSize="11"
MinHeight="320"
Watermark="Click 'Load / Refresh YML' to preview the rendered compose file…"
CornerRadius="6"
Watermark="Click 'Load / Refresh YML' to preview the rendered compose file..."
TextWrapping="NoWrap" />
<!-- Copy button -->
<Button Grid.Row="2"
Content="Copy to Clipboard"
Content="Copy to Clipboard"
Command="{Binding CopyYmlCommand}"
IsEnabled="{Binding HasPreviewYml}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Padding="10,6"
Margin="0,8,0,0" />
Padding="10,7"
Margin="0,10,0,0" />
</Grid>
</Border>
</TabItem>

View File

@@ -5,29 +5,37 @@
x:DataType="vm:HostsViewModel">
<DockPanel>
<!-- Toolbar -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="0,0,0,12">
<Button Content="Add Host" Command="{Binding NewHostCommand}" />
<Button Content="Edit" Command="{Binding EditSelectedHostCommand}" />
<Button Content="Test Connection" Command="{Binding TestConnectionCommand}" />
<Button Content="Delete" Command="{Binding DeleteHostCommand}" />
<Button Content="Refresh" Command="{Binding LoadHostsCommand}" />
<!-- Page header -->
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,4">
<TextBlock Text="SSH Hosts" Classes="pageTitle" />
<TextBlock Text="Manage remote Docker Swarm manager connections" Classes="pageSubtitle" />
</StackPanel>
<!-- Toolbar -->
<Border DockPanel.Dock="Top" Classes="toolbar" Margin="0,0,0,16">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Add Host" Classes="accent" Command="{Binding NewHostCommand}" />
<Button Content="Edit" Command="{Binding EditSelectedHostCommand}" />
<Button Content="Test Connection" Command="{Binding TestConnectionCommand}" />
<Button Content="Delete" Classes="danger" Command="{Binding DeleteHostCommand}" />
<Border Width="1" Background="{StaticResource BorderSubtleBrush}" Margin="4,2" />
<Button Content="Refresh" Command="{Binding LoadHostsCommand}" />
</StackPanel>
</Border>
<!-- Status -->
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Margin="0,8,0,0"
FontSize="12" Foreground="#a6adc8" />
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Classes="status"
Margin="0,10,0,0" />
<!-- Remote Nodes panel -->
<Border DockPanel.Dock="Bottom" Margin="0,12,0,0" Padding="8"
Background="#1e1e2e" CornerRadius="8"
<Border DockPanel.Dock="Bottom" Classes="card" Margin="0,16,0,0"
MinHeight="120" MaxHeight="300">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="0,0,0,8">
<TextBlock Text="Cluster Nodes" FontSize="14" FontWeight="SemiBold" VerticalAlignment="Center" />
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="10" Margin="0,0,0,10">
<TextBlock Text="Cluster Nodes" Classes="sectionTitle" VerticalAlignment="Center" />
<Button Content="List Nodes" Command="{Binding ListNodesCommand}" />
<TextBlock Text="{Binding NodesStatusMessage}" FontSize="12"
Foreground="#a6adc8" VerticalAlignment="Center" Margin="8,0,0,0" />
<TextBlock Text="{Binding NodesStatusMessage}" Classes="status"
VerticalAlignment="Center" Margin="4,0,0,0" />
</StackPanel>
<DataGrid ItemsSource="{Binding RemoteNodes}"
@@ -50,43 +58,48 @@
</Border>
<!-- Edit panel (shown when editing) -->
<Border DockPanel.Dock="Right" Width="350" IsVisible="{Binding IsEditing}"
Background="#1e1e2e" CornerRadius="8" Padding="16" Margin="12,0,0,0">
<Border DockPanel.Dock="Right" Width="360" IsVisible="{Binding IsEditing}"
Classes="card" Margin="16,0,0,0">
<ScrollViewer>
<StackPanel Spacing="8">
<TextBlock Text="SSH Host" FontSize="16" FontWeight="SemiBold" Margin="0,0,0,8" />
<StackPanel Spacing="10">
<TextBlock Text="SSH Host" FontSize="17" FontWeight="SemiBold"
Foreground="{StaticResource AccentBrush}" Margin="0,0,0,6" />
<TextBlock Text="Label" FontSize="12" />
<TextBlock Text="Label" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding EditLabel}" Watermark="e.g. Production Swarm" />
<TextBlock Text="Host" FontSize="12" />
<TextBlock Text="Host" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding EditHost}" Watermark="hostname or IP" />
<TextBlock Text="Port" FontSize="12" />
<NumericUpDown Value="{Binding EditPort}" Minimum="1" Maximum="65535" />
<TextBlock Text="Port" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<NumericUpDown Value="{Binding EditPort}" Minimum="1" Maximum="65535" CornerRadius="6" />
<TextBlock Text="Username" FontSize="12" />
<TextBlock Text="Username" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding EditUsername}" Watermark="ssh username" />
<CheckBox Content="Use Key Authentication" IsChecked="{Binding EditUseKeyAuth}" />
<CheckBox Content="Use Key Authentication" IsChecked="{Binding EditUseKeyAuth}"
Margin="0,4,0,0" />
<TextBlock Text="Private Key Path" FontSize="12"
Foreground="{StaticResource TextSecondaryBrush}"
IsVisible="{Binding EditUseKeyAuth}" />
<TextBox Text="{Binding EditPrivateKeyPath}" Watermark="~/.ssh/id_rsa"
IsVisible="{Binding EditUseKeyAuth}" />
<TextBlock Text="Key Passphrase (optional)" FontSize="12"
Foreground="{StaticResource TextSecondaryBrush}"
IsVisible="{Binding EditUseKeyAuth}" />
<TextBox Text="{Binding EditKeyPassphrase}" PasswordChar="●"
IsVisible="{Binding EditUseKeyAuth}" />
<TextBlock Text="Password (if not using key)" FontSize="12"
Foreground="{StaticResource TextSecondaryBrush}"
IsVisible="{Binding !EditUseKeyAuth}" />
<TextBox Text="{Binding EditPassword}" PasswordChar="●"
IsVisible="{Binding !EditUseKeyAuth}" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,12,0,0">
<Button Content="Save" Command="{Binding SaveHostCommand}" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,14,0,0">
<Button Content="Save" Classes="accent" Command="{Binding SaveHostCommand}" />
<Button Content="Cancel" Command="{Binding CancelEditCommand}" />
</StackPanel>
</StackPanel>

View File

@@ -5,42 +5,53 @@
x:DataType="vm:InstancesViewModel">
<DockPanel>
<!-- Toolbar -->
<StackPanel DockPanel.Dock="Top" Spacing="8" Margin="0,0,0,12">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Refresh" Command="{Binding LoadInstancesCommand}" />
<Button Content="Inspect" Command="{Binding InspectInstanceCommand}" />
<Button Content="Delete" Command="{Binding DeleteInstanceCommand}" />
<Button Content="Rotate DB Password" Command="{Binding RotateMySqlPasswordCommand}"
IsEnabled="{Binding !IsBusy}"
ToolTip.Tip="Generate a new MySQL password, update the Docker secret, and redeploy the stack." />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBox Text="{Binding FilterText}" Watermark="Filter by name..." Width="250" />
<Button Content="Search" Command="{Binding LoadInstancesCommand}" />
</StackPanel>
<!-- Page header -->
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,4">
<TextBlock Text="Instances" Classes="pageTitle" />
<TextBlock Text="View and manage deployed CMS stacks" Classes="pageSubtitle" />
</StackPanel>
<!-- Toolbar -->
<Border DockPanel.Dock="Top" Classes="toolbar" Margin="0,0,0,16">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Refresh" Command="{Binding LoadInstancesCommand}" />
<Button Content="Inspect" Command="{Binding InspectInstanceCommand}" />
<Button Content="Delete" Classes="danger" Command="{Binding DeleteInstanceCommand}" />
<Border Width="1" Background="{StaticResource BorderSubtleBrush}" Margin="4,2" />
<Button Content="Rotate DB Password" Command="{Binding RotateMySqlPasswordCommand}"
IsEnabled="{Binding !IsBusy}"
ToolTip.Tip="Generate a new MySQL password, update the Docker secret, and redeploy the stack." />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
<TextBox Text="{Binding FilterText}" Watermark="Filter by name..." Width="220" />
<Button Content="Search" Command="{Binding LoadInstancesCommand}" />
</StackPanel>
</Grid>
</Border>
<!-- Status -->
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Margin="0,8,0,0"
FontSize="12" Foreground="#a6adc8" />
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Classes="status"
Margin="0,10,0,0" />
<!-- Services panel (shown when inspecting) -->
<Border DockPanel.Dock="Right" Width="350"
<Border DockPanel.Dock="Right" Width="360"
IsVisible="{Binding SelectedServices.Count}"
Background="#1e1e2e" CornerRadius="8" Padding="12" Margin="12,0,0,0">
Classes="card" Margin="16,0,0,0">
<StackPanel Spacing="4">
<TextBlock Text="Stack Services" FontWeight="SemiBold" Margin="0,0,0,8" />
<TextBlock Text="Stack Services" Classes="sectionTitle"
Foreground="{StaticResource AccentBrush}" Margin="0,0,0,10" />
<ItemsControl ItemsSource="{Binding SelectedServices}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#313244" CornerRadius="4" Padding="8" Margin="0,2">
<StackPanel Spacing="2">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" />
<TextBlock Text="{Binding Image}" FontSize="11" Foreground="#a6adc8" />
<Border Background="#232336" CornerRadius="6" Padding="12,10" Margin="0,3"
BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="1">
<StackPanel Spacing="3">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" FontSize="13" />
<TextBlock Text="{Binding Image}" FontSize="11"
Foreground="{StaticResource TextMutedBrush}" />
<TextBlock Text="{Binding Replicas, StringFormat='Replicas: {0}'}"
FontSize="11" Foreground="#a6adc8" />
FontSize="11" Foreground="{StaticResource TextSecondaryBrush}" />
</StackPanel>
</Border>
</DataTemplate>
@@ -49,8 +60,6 @@
</StackPanel>
</Border>
<!-- Remote stacks panel removed: all live stacks are shown in the main list below -->
<!-- Instance list -->
<DataGrid ItemsSource="{Binding Instances}"
SelectedItem="{Binding SelectedInstance}"

View File

@@ -5,12 +5,22 @@
x:DataType="vm:LogsViewModel">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="0,0,0,12">
<Button Content="Refresh" Command="{Binding LoadLogsCommand}" />
<TextBlock Text="{Binding StatusMessage}" VerticalAlignment="Center"
FontSize="12" Foreground="#a6adc8" Margin="8,0,0,0" />
<!-- Page header -->
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,4">
<TextBlock Text="Activity Logs" Classes="pageTitle" />
<TextBlock Text="Deployment history and operations log" Classes="pageSubtitle" />
</StackPanel>
<!-- Toolbar -->
<Border DockPanel.Dock="Top" Classes="toolbar" Margin="0,0,0,16">
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Refresh" Classes="accent" Command="{Binding LoadLogsCommand}" />
<TextBlock Text="{Binding StatusMessage}" Classes="status"
VerticalAlignment="Center" Margin="4,0,0,0" />
</StackPanel>
</Border>
<!-- Logs grid -->
<DataGrid ItemsSource="{Binding Logs}"
AutoGenerateColumns="False"
IsReadOnly="True"

View File

@@ -5,8 +5,9 @@
x:Class="OTSSignsOrchestrator.Desktop.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
Title="OTS Signs Orchestrator"
Width="1200" Height="800"
WindowStartupLocation="CenterScreen">
Width="1280" Height="850"
WindowStartupLocation="CenterScreen"
ExtendClientAreaToDecorationsHint="False">
<Window.DataTemplates>
<DataTemplate DataType="vm:HostsViewModel">
@@ -30,33 +31,93 @@
</Window.DataTemplates>
<DockPanel>
<!-- Status bar -->
<Border DockPanel.Dock="Bottom" Background="#1e1e2e" Padding="8,4">
<TextBlock Text="{Binding StatusMessage}" FontSize="12" Foreground="#a0a0a0" />
<!-- ═══ Status Bar ═══ -->
<Border DockPanel.Dock="Bottom"
Background="#0C0C14"
BorderBrush="{StaticResource BorderSubtleBrush}"
BorderThickness="0,1,0,0"
Padding="16,6">
<Grid ColumnDefinitions="Auto,*,Auto">
<StackPanel Orientation="Horizontal" Spacing="6" VerticalAlignment="Center">
<Ellipse Width="7" Height="7" Fill="{StaticResource AccentBrush}" />
<TextBlock Text="Ready" FontSize="11" Foreground="{StaticResource TextMutedBrush}" />
</StackPanel>
<TextBlock Grid.Column="1"
Text="{Binding StatusMessage}"
FontSize="11"
Foreground="{StaticResource TextSecondaryBrush}"
Margin="16,0,0,0"
TextTrimming="CharacterEllipsis" />
<TextBlock Grid.Column="2"
Text="OTS Signs Orchestrator"
FontSize="10"
Foreground="#45475A" />
</Grid>
</Border>
<!-- Left nav -->
<Border DockPanel.Dock="Left" Width="180" Background="#181825" Padding="0,8">
<StackPanel Spacing="2">
<TextBlock Text="OTS Signs" FontSize="18" FontWeight="Bold" Foreground="#cdd6f4"
Margin="16,8,16,16" />
<!-- ═══ Sidebar ═══ -->
<Border DockPanel.Dock="Left"
Width="220"
Background="{StaticResource SurfaceBrush}"
BorderBrush="{StaticResource BorderSubtleBrush}"
BorderThickness="0,0,1,0">
<DockPanel>
<!-- Logo + title area -->
<StackPanel DockPanel.Dock="Top"
HorizontalAlignment="Center"
Margin="20,28,20,8">
<Image Source="avares://OTSSignsOrchestrator.Desktop/Assets/OTS-Signs.png"
Width="56" Height="56"
RenderOptions.BitmapInterpolationMode="HighQuality"
HorizontalAlignment="Center"
Margin="0,0,0,14" />
<TextBlock Text="OTS Signs"
FontSize="18" FontWeight="Bold"
Foreground="{StaticResource TextPrimaryBrush}"
HorizontalAlignment="Center" />
<TextBlock Text="Orchestrator"
FontSize="12"
Foreground="{StaticResource TextMutedBrush}"
HorizontalAlignment="Center"
Margin="0,2,0,0" />
</StackPanel>
<!-- Divider -->
<Border DockPanel.Dock="Top"
Height="1"
Background="{StaticResource BorderSubtleBrush}"
Margin="20,16,20,12" />
<!-- Version at bottom -->
<TextBlock DockPanel.Dock="Bottom"
Text="v1.0.0"
FontSize="10"
Foreground="#3B3B50"
HorizontalAlignment="Center"
Margin="0,0,0,12" />
<!-- Navigation -->
<ListBox ItemsSource="{Binding NavItems}"
SelectedItem="{Binding SelectedNav}"
Background="Transparent"
Margin="4,0">
Classes="sidebar">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Padding="12,8" FontSize="14" />
<TextBlock Text="{Binding}"
FontSize="14"
FontWeight="Medium" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DockPanel>
</Border>
<!-- Main content -->
<Border Padding="16">
<!-- ═══ Main Content ═══ -->
<Border Padding="28,24">
<ContentControl Content="{Binding CurrentView}" />
</Border>
</DockPanel>
</Window>

View File

@@ -5,23 +5,34 @@
x:DataType="vm:SecretsViewModel">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="0,0,0,12">
<ComboBox ItemsSource="{Binding AvailableHosts}"
SelectedItem="{Binding SelectedSshHost}"
PlaceholderText="Select SSH Host..."
Width="250">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Content="Load Secrets" Command="{Binding LoadSecretsCommand}" />
<!-- Page header -->
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,4">
<TextBlock Text="Secrets" Classes="pageTitle" />
<TextBlock Text="View Docker secrets on remote hosts" Classes="pageSubtitle" />
</StackPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Margin="0,8,0,0"
FontSize="12" Foreground="#a6adc8" />
<!-- Toolbar -->
<Border DockPanel.Dock="Top" Classes="toolbar" Margin="0,0,0,16">
<StackPanel Orientation="Horizontal" Spacing="10">
<ComboBox ItemsSource="{Binding AvailableHosts}"
SelectedItem="{Binding SelectedSshHost}"
PlaceholderText="Select SSH Host..."
Width="260">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Label}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Content="Load Secrets" Classes="accent" Command="{Binding LoadSecretsCommand}" />
</StackPanel>
</Border>
<!-- Status -->
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Classes="status"
Margin="0,10,0,0" />
<!-- Secrets grid -->
<DataGrid ItemsSource="{Binding Secrets}"
AutoGenerateColumns="False"
IsReadOnly="True"

View File

@@ -5,191 +5,226 @@
x:DataType="vm:SettingsViewModel">
<DockPanel>
<!-- Top toolbar -->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Spacing="8" Margin="0,0,0,12">
<Button Content="Save All Settings"
Command="{Binding SaveCommand}"
IsEnabled="{Binding !IsBusy}"
FontWeight="SemiBold" Padding="16,8" />
<Button Content="Reload" Command="{Binding LoadCommand}" IsEnabled="{Binding !IsBusy}" />
<TextBlock Text="{Binding StatusMessage}" VerticalAlignment="Center"
FontSize="12" Foreground="#a6adc8" Margin="12,0,0,0" />
<!-- Page header -->
<StackPanel DockPanel.Dock="Top" Margin="0,0,0,4">
<TextBlock Text="Settings" Classes="pageTitle" />
<TextBlock Text="Global configuration for deployments and integrations" Classes="pageSubtitle" />
</StackPanel>
<!-- Top toolbar -->
<Border DockPanel.Dock="Top" Classes="toolbar" Margin="0,0,0,16">
<StackPanel Orientation="Horizontal" Spacing="10">
<Button Content="Save All Settings"
Classes="accent"
Command="{Binding SaveCommand}"
IsEnabled="{Binding !IsBusy}"
FontWeight="SemiBold" Padding="20,8" />
<Button Content="Reload" Command="{Binding LoadCommand}" IsEnabled="{Binding !IsBusy}" />
<TextBlock Text="{Binding StatusMessage}" Classes="status"
VerticalAlignment="Center" Margin="6,0,0,0" />
</StackPanel>
</Border>
<!-- Scrollable settings content -->
<ScrollViewer>
<StackPanel Spacing="16" Margin="0,0,16,16" MaxWidth="800">
<StackPanel Spacing="16" Margin="0,0,16,16" MaxWidth="820">
<!-- ═══ Git Repository ═══ -->
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="Git Repository" FontSize="16" FontWeight="SemiBold"
Foreground="#89b4fa" Margin="0,0,0,4" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,0,0,4">
<Border Width="4" Height="20" CornerRadius="2" Background="#60A5FA" />
<TextBlock Text="Git Repository" FontSize="16" FontWeight="SemiBold"
Foreground="#60A5FA" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Text="Template repository cloned for each new instance."
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
FontSize="12" Foreground="{StaticResource TextMutedBrush}" Margin="0,0,0,6" />
<TextBlock Text="Repository URL" FontSize="12" />
<TextBlock Text="Repository URL" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding GitRepoUrl}"
Watermark="https://github.com/org/template-repo.git" />
<TextBlock Text="Personal Access Token (PAT)" FontSize="12" />
<TextBlock Text="Personal Access Token (PAT)" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding GitRepoPat}" PasswordChar="●"
Watermark="ghp_xxxx..." />
</StackPanel>
</Border>
<!-- ═══ MySQL Connection ═══ -->
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="MySQL Connection" FontSize="16" FontWeight="SemiBold"
Foreground="#a6e3a1" Margin="0,0,0,4" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,0,0,4">
<Border Width="4" Height="20" CornerRadius="2" Background="#4ADE80" />
<TextBlock Text="MySQL Connection" FontSize="16" FontWeight="SemiBold"
Foreground="#4ADE80" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Text="Admin credentials used to create databases and users for new instances."
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
FontSize="12" Foreground="{StaticResource TextMutedBrush}" Margin="0,0,0,6" />
<Grid ColumnDefinitions="3*,8,1*" RowDefinitions="Auto,Auto">
<Grid ColumnDefinitions="3*,12,1*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Host" FontSize="12" />
<TextBlock Text="Host" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding MySqlHost}" Watermark="cms-sql.otshosting.app" />
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Port" FontSize="12" />
<TextBlock Text="Port" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding MySqlPort}" Watermark="3306" />
</StackPanel>
</Grid>
<TextBlock Text="Admin Username" FontSize="12" />
<TextBlock Text="Admin Username" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding MySqlAdminUser}" Watermark="root" />
<TextBlock Text="Admin Password" FontSize="12" />
<TextBlock Text="Admin Password" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding MySqlAdminPassword}" PasswordChar="●" />
<Button Content="Test MySQL Connection"
Command="{Binding TestMySqlConnectionCommand}"
IsEnabled="{Binding !IsBusy}"
Margin="0,4,0,0" />
Margin="0,6,0,0" />
</StackPanel>
</Border>
<!-- ═══ SMTP Settings ═══ -->
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="SMTP Settings" FontSize="16" FontWeight="SemiBold"
Foreground="#f5c2e7" Margin="0,0,0,4" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,0,0,4">
<Border Width="4" Height="20" CornerRadius="2" Background="#F472B6" />
<TextBlock Text="SMTP Settings" FontSize="16" FontWeight="SemiBold"
Foreground="#F472B6" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Text="Email configuration applied to all CMS instances."
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
FontSize="12" Foreground="{StaticResource TextMutedBrush}" Margin="0,0,0,6" />
<TextBlock Text="SMTP Server (host:port)" FontSize="12" />
<TextBlock Text="SMTP Server (host:port)" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding SmtpServer}" Watermark="smtp.azurecomm.net:587" />
<TextBlock Text="SMTP Username" FontSize="12" />
<TextBlock Text="SMTP Username" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding SmtpUsername}" Watermark="user@domain.com" />
<TextBlock Text="SMTP Password" FontSize="12" />
<TextBlock Text="SMTP Password" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding SmtpPassword}" PasswordChar="●" />
<StackPanel Orientation="Horizontal" Spacing="16">
<StackPanel Orientation="Horizontal" Spacing="20" Margin="0,4,0,0">
<CheckBox Content="Use TLS" IsChecked="{Binding SmtpUseTls}" />
<CheckBox Content="Use STARTTLS" IsChecked="{Binding SmtpUseStartTls}" />
</StackPanel>
<TextBlock Text="Rewrite Domain" FontSize="12" />
<TextBlock Text="Rewrite Domain" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding SmtpRewriteDomain}" Watermark="ots-signs.com" />
<TextBlock Text="SMTP Hostname" FontSize="12" />
<TextBlock Text="SMTP Hostname" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding SmtpHostname}" Watermark="demo.ots-signs.com" />
<TextBlock Text="From Line Override" FontSize="12" />
<TextBlock Text="From Line Override" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding SmtpFromLineOverride}" Watermark="NO" />
</StackPanel>
</Border>
<!-- ═══ Pangolin / Newt ═══ -->
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="Pangolin (Newt Tunnel)" FontSize="16" FontWeight="SemiBold"
Foreground="#fab387" Margin="0,0,0,4" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,0,0,4">
<Border Width="4" Height="20" CornerRadius="2" Background="#FBBF24" />
<TextBlock Text="Pangolin (Newt Tunnel)" FontSize="16" FontWeight="SemiBold"
Foreground="#FBBF24" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Text="Global Pangolin endpoint. Newt ID and Secret are configured per-instance."
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
FontSize="12" Foreground="{StaticResource TextMutedBrush}" Margin="0,0,0,6" />
<TextBlock Text="Pangolin Endpoint URL" FontSize="12" />
<TextBlock Text="Pangolin Endpoint URL" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding PangolinEndpoint}" Watermark="https://app.pangolin.net" />
</StackPanel>
</Border>
<!-- ═══ NFS Volumes ═══ -->
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="NFS Volumes" FontSize="16" FontWeight="SemiBold"
Foreground="#cba6f7" Margin="0,0,0,4" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,0,0,4">
<Border Width="4" Height="20" CornerRadius="2" Background="#C084FC" />
<TextBlock Text="NFS Volumes" FontSize="16" FontWeight="SemiBold"
Foreground="#C084FC" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Text="Network share settings for Docker volumes. Volumes will be mounted via NFS."
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
FontSize="12" Foreground="{StaticResource TextMutedBrush}" Margin="0,0,0,6" />
<TextBlock Text="NFS Server (hostname/IP)" FontSize="12" />
<TextBlock Text="NFS Server (hostname/IP)" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsServer}" Watermark="nas.local" />
<TextBlock Text="Export Path" FontSize="12" />
<TextBlock Text="Export Path" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsExport}" Watermark="/srv/nfs" />
<TextBlock Text="Export Folder (optional)" FontSize="12" />
<TextBlock Text="Export Folder (optional)" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsExportFolder}" Watermark="ots_cms (leave empty for export root)" />
<TextBlock Text="Extra Mount Options" FontSize="12" />
<TextBlock Text="Extra Mount Options" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding NfsOptions}" Watermark="Additional options after nfsvers=4,proto=tcp" />
</StackPanel>
</Border>
<!-- ═══ Instance Defaults ═══ -->
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
<Border Classes="card">
<StackPanel Spacing="8">
<TextBlock Text="Instance Defaults" FontSize="16" FontWeight="SemiBold"
Foreground="#89dceb" Margin="0,0,0,4" />
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,0,0,4">
<Border Width="4" Height="20" CornerRadius="2" Background="#2DD4BF" />
<TextBlock Text="Instance Defaults" FontSize="16" FontWeight="SemiBold"
Foreground="#2DD4BF" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Text="Default Docker images, naming templates, and PHP settings for new instances. Use {abbrev} as a placeholder for the customer abbreviation."
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" TextWrapping="Wrap" />
FontSize="12" Foreground="{StaticResource TextMutedBrush}" Margin="0,0,0,6" TextWrapping="Wrap" />
<TextBlock Text="Docker Images" FontSize="13" FontWeight="SemiBold" Margin="0,8,0,4" />
<!-- Sub-section: Docker Images -->
<TextBlock Text="Docker Images" FontSize="13" FontWeight="SemiBold" Margin="0,8,0,4"
Foreground="{StaticResource TextPrimaryBrush}" />
<TextBlock Text="CMS Image" FontSize="12" />
<TextBlock Text="CMS Image" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultCmsImage}"
Watermark="ghcr.io/xibosignage/xibo-cms:release-4.2.3" />
<TextBlock Text="Newt Image" FontSize="12" />
<TextBlock Text="Newt Image" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultNewtImage}" Watermark="fosrl/newt" />
<TextBlock Text="Memcached Image" FontSize="12" />
<TextBlock Text="Memcached Image" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultMemcachedImage}" Watermark="memcached:alpine" />
<TextBlock Text="QuickChart Image" FontSize="12" />
<TextBlock Text="QuickChart Image" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultQuickChartImage}" Watermark="ianw/quickchart" />
<TextBlock Text="Naming Templates" FontSize="13" FontWeight="SemiBold" Margin="0,12,0,4" />
<!-- Sub-section: Naming Templates -->
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,12,0,4" />
<TextBlock Text="Naming Templates" FontSize="13" FontWeight="SemiBold" Margin="0,4,0,4"
Foreground="{StaticResource TextPrimaryBrush}" />
<TextBlock Text="CMS Server Name Template" FontSize="12" />
<TextBlock Text="CMS Server Name Template" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultCmsServerNameTemplate}"
Watermark="{}{abbrev}.ots-signs.com" />
<TextBlock Text="Theme Host Path Template" FontSize="12" />
<TextBlock Text="Theme Host Path Template" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultThemeHostPath}"
Watermark="/cms/{abbrev}-cms-theme-custom" />
<TextBlock Text="MySQL Database Name Template" FontSize="12" />
<TextBlock Text="MySQL Database Name Template" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultMySqlDbTemplate}" Watermark="{}{abbrev}_cms_db" />
<TextBlock Text="MySQL User Template" FontSize="12" />
<TextBlock Text="MySQL User Template" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultMySqlUserTemplate}" Watermark="{}{abbrev}_cms_user" />
<TextBlock Text="PHP Settings" FontSize="13" FontWeight="SemiBold" Margin="0,12,0,4" />
<!-- Sub-section: PHP Settings -->
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,12,0,4" />
<TextBlock Text="PHP Settings" FontSize="13" FontWeight="SemiBold" Margin="0,4,0,4"
Foreground="{StaticResource TextPrimaryBrush}" />
<Grid ColumnDefinitions="1*,8,1*,8,1*">
<Grid ColumnDefinitions="1*,12,1*,12,1*">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Post Max Size" FontSize="12" />
<TextBlock Text="Post Max Size" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultPhpPostMaxSize}" Watermark="10G" />
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="Upload Max Filesize" FontSize="12" />
<TextBlock Text="Upload Max Filesize" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultPhpUploadMaxFilesize}" Watermark="10G" />
</StackPanel>
<StackPanel Grid.Column="4" Spacing="4">
<TextBlock Text="Max Execution Time" FontSize="12" />
<TextBlock Text="Max Execution Time" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" />
<TextBox Text="{Binding DefaultPhpMaxExecutionTime}" Watermark="600" />
</StackPanel>
</Grid>

Binary file not shown.

Binary file not shown.

View File

@@ -8,6 +8,7 @@ services:
environment:
CMS_USE_MEMCACHED: "true"
MEMCACHED_HOST: memcached
CMS_ALIAS: "/{{ABBREV}}"
MYSQL_HOST: {{MYSQL_HOST}}
MYSQL_PORT: "{{MYSQL_PORT}}"
MYSQL_DATABASE: {{MYSQL_DATABASE}}
@@ -26,7 +27,6 @@ services:
CMS_PHP_UPLOAD_MAX_FILESIZE: {{PHP_UPLOAD_MAX_FILESIZE}}
CMS_PHP_MAX_EXECUTION_TIME: "{{PHP_MAX_EXECUTION_TIME}}"
secrets:
- {{ABBREV}}-cms-db-user
- global_mysql_host
- global_mysql_port
volumes:
@@ -123,6 +123,8 @@ volumes:
o: "{{NFS_OPTS}}"
secrets:
{{ABBREV}}-cms-db-password:
external: true
{{ABBREV}}-cms-db-user:
external: true
global_mysql_host: