feat: Add main application views and structure
Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled
- Implemented CreateInstanceView for creating new instances. - Added HostsView for managing SSH hosts with CRUD operations. - Created InstancesView for displaying and managing instances. - Developed LogsView for viewing operation logs. - Introduced SecretsView for managing secrets associated with hosts. - Established SettingsView for configuring application settings. - Created MainWindow as the main application window with navigation. - Added app manifest and configuration files for logging and settings.
This commit is contained in:
146
OTSSignsOrchestrator.Desktop/Views/CreateInstanceView.axaml
Normal file
146
OTSSignsOrchestrator.Desktop/Views/CreateInstanceView.axaml
Normal file
@@ -0,0 +1,146 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.CreateInstanceView"
|
||||
x:DataType="vm:CreateInstanceViewModel">
|
||||
|
||||
<ScrollViewer>
|
||||
<Grid ColumnDefinitions="1*,16,1*" Margin="16,12">
|
||||
|
||||
<!-- ══ LEFT COLUMN — inputs ══ -->
|
||||
<StackPanel Grid.Column="0" Spacing="8">
|
||||
<TextBlock Text="Create New Instance" FontSize="20" FontWeight="Bold" Margin="0,0,0,12" />
|
||||
|
||||
<!-- 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" />
|
||||
|
||||
<!-- Core fields -->
|
||||
<TextBlock Text="Customer Name" FontSize="12" />
|
||||
<TextBox Text="{Binding CustomerName}" Watermark="e.g. Acme Corp" />
|
||||
|
||||
<TextBlock Text="Abbreviation (3 letters)" FontSize="12" />
|
||||
<TextBox Text="{Binding CustomerAbbrev}"
|
||||
Watermark="e.g. acm"
|
||||
MaxLength="3" />
|
||||
|
||||
<Separator Margin="0,12" />
|
||||
|
||||
<!-- 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)" />
|
||||
|
||||
<TextBlock Text="Newt Secret" FontSize="12" />
|
||||
<TextBox Text="{Binding NewtSecret}" PasswordChar="●" Watermark="(from Pangolin dashboard)" />
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
<!-- SMB / CIFS credentials (per-instance, defaults from global settings) -->
|
||||
<Expander Header="SMB / CIFS credentials">
|
||||
<StackPanel Spacing="8" Margin="0,8,0,0">
|
||||
<TextBlock Text="CIFS Server" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsServer}" Watermark="e.g. 192.168.1.100" />
|
||||
|
||||
<TextBlock Text="Share Base Path" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsShareBasePath}" Watermark="e.g. /share/cms" />
|
||||
|
||||
<TextBlock Text="Username" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsUsername}" Watermark="SMB username" />
|
||||
|
||||
<TextBlock Text="Password" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsPassword}" PasswordChar="●" Watermark="SMB password" />
|
||||
|
||||
<TextBlock Text="Extra Options" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsExtraOptions}" Watermark="file_mode=0777,dir_mode=0777" />
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
<Separator Margin="0,12" />
|
||||
|
||||
<!-- Deploy button + progress -->
|
||||
<Button Content="Deploy Instance"
|
||||
Command="{Binding DeployCommand}"
|
||||
IsEnabled="{Binding !IsBusy}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Center"
|
||||
Padding="12,8" FontWeight="SemiBold" />
|
||||
|
||||
<!-- Progress bar -->
|
||||
<Grid ColumnDefinitions="*,Auto" Margin="0,4,0,0"
|
||||
IsVisible="{Binding IsBusy}">
|
||||
<ProgressBar Value="{Binding ProgressPercent}"
|
||||
Maximum="100" Height="6"
|
||||
CornerRadius="3" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding ProgressStep}"
|
||||
FontSize="11" Foreground="#a6adc8"
|
||||
Margin="8,0,0,0" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="{Binding StatusMessage}" FontSize="12" Foreground="#a6adc8"
|
||||
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}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- ══ RIGHT COLUMN — live resource preview ══ -->
|
||||
<Border Grid.Column="2"
|
||||
Background="#1e1e2e"
|
||||
CornerRadius="8"
|
||||
Padding="16,14"
|
||||
VerticalAlignment="Top">
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Text="Resource Preview" FontSize="14" FontWeight="SemiBold"
|
||||
Foreground="#cdd6f4" Margin="0,0,0,8" />
|
||||
|
||||
<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="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="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="CIFS 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="Docker Secret" FontSize="11" Foreground="#6c7086" />
|
||||
<TextBlock Text="{Binding PreviewSecret}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#fab387" Margin="0,0,0,6" />
|
||||
|
||||
<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="CMS URL" FontSize="11" Foreground="#6c7086" />
|
||||
<TextBlock Text="{Binding PreviewCmsUrl}" FontFamily="Cascadia Mono, Consolas, monospace" FontSize="12" Foreground="#89dceb" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class CreateInstanceView : UserControl
|
||||
{
|
||||
public CreateInstanceView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
83
OTSSignsOrchestrator.Desktop/Views/HostsView.axaml
Normal file
83
OTSSignsOrchestrator.Desktop/Views/HostsView.axaml
Normal file
@@ -0,0 +1,83 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.HostsView"
|
||||
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}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Status -->
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Margin="0,8,0,0"
|
||||
FontSize="12" Foreground="#a6adc8" />
|
||||
|
||||
<!-- 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">
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="SSH Host" FontSize="16" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||
|
||||
<TextBlock Text="Label" FontSize="12" />
|
||||
<TextBox Text="{Binding EditLabel}" Watermark="e.g. Production Swarm" />
|
||||
|
||||
<TextBlock Text="Host" FontSize="12" />
|
||||
<TextBox Text="{Binding EditHost}" Watermark="hostname or IP" />
|
||||
|
||||
<TextBlock Text="Port" FontSize="12" />
|
||||
<NumericUpDown Value="{Binding EditPort}" Minimum="1" Maximum="65535" />
|
||||
|
||||
<TextBlock Text="Username" FontSize="12" />
|
||||
<TextBox Text="{Binding EditUsername}" Watermark="ssh username" />
|
||||
|
||||
<CheckBox Content="Use Key Authentication" IsChecked="{Binding EditUseKeyAuth}" />
|
||||
|
||||
<TextBlock Text="Private Key Path" FontSize="12"
|
||||
IsVisible="{Binding EditUseKeyAuth}" />
|
||||
<TextBox Text="{Binding EditPrivateKeyPath}" Watermark="~/.ssh/id_rsa"
|
||||
IsVisible="{Binding EditUseKeyAuth}" />
|
||||
|
||||
<TextBlock Text="Key Passphrase (optional)" FontSize="12"
|
||||
IsVisible="{Binding EditUseKeyAuth}" />
|
||||
<TextBox Text="{Binding EditKeyPassphrase}" PasswordChar="●"
|
||||
IsVisible="{Binding EditUseKeyAuth}" />
|
||||
|
||||
<TextBlock Text="Password (if not using key)" FontSize="12"
|
||||
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}" />
|
||||
<Button Content="Cancel" Command="{Binding CancelEditCommand}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<!-- Host list -->
|
||||
<DataGrid ItemsSource="{Binding Hosts}"
|
||||
SelectedItem="{Binding SelectedHost}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Label" Binding="{Binding Label}" Width="150" />
|
||||
<DataGridTextColumn Header="Host" Binding="{Binding Host}" Width="200" />
|
||||
<DataGridTextColumn Header="Port" Binding="{Binding Port}" Width="60" />
|
||||
<DataGridTextColumn Header="User" Binding="{Binding Username}" Width="100" />
|
||||
<DataGridCheckBoxColumn Header="Key Auth" Binding="{Binding UseKeyAuth}" Width="70" />
|
||||
<DataGridTextColumn Header="Last Tested" Binding="{Binding LastTestedAt, StringFormat='{}{0:g}'}" Width="150" />
|
||||
<DataGridCheckBoxColumn Header="OK" Binding="{Binding LastTestSuccess}" Width="50" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
11
OTSSignsOrchestrator.Desktop/Views/HostsView.axaml.cs
Normal file
11
OTSSignsOrchestrator.Desktop/Views/HostsView.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class HostsView : UserControl
|
||||
{
|
||||
public HostsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
98
OTSSignsOrchestrator.Desktop/Views/InstancesView.axaml
Normal file
98
OTSSignsOrchestrator.Desktop/Views/InstancesView.axaml
Normal file
@@ -0,0 +1,98 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.InstancesView"
|
||||
x:DataType="vm:InstancesViewModel">
|
||||
|
||||
<DockPanel>
|
||||
<!-- Toolbar -->
|
||||
<StackPanel DockPanel.Dock="Top" Spacing="8" Margin="0,0,0,12">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<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="List Remote Stacks" Command="{Binding RefreshRemoteStacksCommand}" />
|
||||
<Button Content="Inspect" Command="{Binding InspectInstanceCommand}" />
|
||||
<Button Content="Delete" Command="{Binding DeleteInstanceCommand}" />
|
||||
<Button Content="Refresh" Command="{Binding LoadInstancesCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBox Text="{Binding FilterText}" Watermark="Filter by name..." Width="250" />
|
||||
<Button Content="Search" Command="{Binding LoadInstancesCommand}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Status -->
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Margin="0,8,0,0"
|
||||
FontSize="12" Foreground="#a6adc8" />
|
||||
|
||||
<!-- Services panel (shown when inspecting) -->
|
||||
<Border DockPanel.Dock="Right" Width="350"
|
||||
IsVisible="{Binding SelectedServices.Count}"
|
||||
Background="#1e1e2e" CornerRadius="8" Padding="12" Margin="12,0,0,0">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Stack Services" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||
<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" />
|
||||
<TextBlock Text="{Binding Replicas, StringFormat='Replicas: {0}'}"
|
||||
FontSize="11" Foreground="#a6adc8" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Remote stacks panel -->
|
||||
<Border DockPanel.Dock="Bottom" MaxHeight="200"
|
||||
IsVisible="{Binding RemoteStacks.Count}"
|
||||
Background="#1e1e2e" CornerRadius="8" Padding="12" Margin="0,8,0,0">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Remote Stacks" FontWeight="SemiBold" />
|
||||
<ItemsControl ItemsSource="{Binding RemoteStacks}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock>
|
||||
<Run Text="{Binding Name}" FontWeight="SemiBold" />
|
||||
<Run Text="{Binding ServiceCount, StringFormat=' ({0} services)'}"
|
||||
Foreground="#a6adc8" />
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Instance list -->
|
||||
<DataGrid ItemsSource="{Binding Instances}"
|
||||
SelectedItem="{Binding SelectedInstance}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Stack" Binding="{Binding StackName}" Width="120" />
|
||||
<DataGridTextColumn Header="Customer" Binding="{Binding CustomerName}" Width="120" />
|
||||
<DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="80" />
|
||||
<DataGridTextColumn Header="Server" Binding="{Binding CmsServerName}" Width="150" />
|
||||
<DataGridTextColumn Header="Port" Binding="{Binding HostHttpPort}" Width="60" />
|
||||
<DataGridTextColumn Header="Host" Binding="{Binding SshHost.Label}" Width="120" />
|
||||
<DataGridTextColumn Header="Created" Binding="{Binding CreatedAt, StringFormat='{}{0:g}'}" Width="140" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
11
OTSSignsOrchestrator.Desktop/Views/InstancesView.axaml.cs
Normal file
11
OTSSignsOrchestrator.Desktop/Views/InstancesView.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class InstancesView : UserControl
|
||||
{
|
||||
public InstancesView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
29
OTSSignsOrchestrator.Desktop/Views/LogsView.axaml
Normal file
29
OTSSignsOrchestrator.Desktop/Views/LogsView.axaml
Normal file
@@ -0,0 +1,29 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.LogsView"
|
||||
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" />
|
||||
</StackPanel>
|
||||
|
||||
<DataGrid ItemsSource="{Binding Logs}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Time" Binding="{Binding Timestamp, StringFormat='{}{0:g}'}" Width="150" />
|
||||
<DataGridTextColumn Header="Operation" Binding="{Binding Operation}" Width="100" />
|
||||
<DataGridTextColumn Header="Status" Binding="{Binding Status}" Width="80" />
|
||||
<DataGridTextColumn Header="Instance" Binding="{Binding Instance.StackName}" Width="120" />
|
||||
<DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="*" />
|
||||
<DataGridTextColumn Header="Duration" Binding="{Binding DurationMs, StringFormat='{}{0}ms'}" Width="80" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
11
OTSSignsOrchestrator.Desktop/Views/LogsView.axaml.cs
Normal file
11
OTSSignsOrchestrator.Desktop/Views/LogsView.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class LogsView : UserControl
|
||||
{
|
||||
public LogsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
62
OTSSignsOrchestrator.Desktop/Views/MainWindow.axaml
Normal file
62
OTSSignsOrchestrator.Desktop/Views/MainWindow.axaml
Normal file
@@ -0,0 +1,62 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
xmlns:views="using:OTSSignsOrchestrator.Desktop.Views"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Title="OTS Signs Orchestrator"
|
||||
Width="1200" Height="800"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
<Window.DataTemplates>
|
||||
<DataTemplate DataType="vm:HostsViewModel">
|
||||
<views:HostsView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="vm:InstancesViewModel">
|
||||
<views:InstancesView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="vm:SecretsViewModel">
|
||||
<views:SecretsView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="vm:LogsViewModel">
|
||||
<views:LogsView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="vm:CreateInstanceViewModel">
|
||||
<views:CreateInstanceView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="vm:SettingsViewModel">
|
||||
<views:SettingsView />
|
||||
</DataTemplate>
|
||||
</Window.DataTemplates>
|
||||
|
||||
<DockPanel>
|
||||
<!-- Status bar -->
|
||||
<Border DockPanel.Dock="Bottom" Background="#1e1e2e" Padding="8,4">
|
||||
<TextBlock Text="{Binding StatusMessage}" FontSize="12" Foreground="#a0a0a0" />
|
||||
</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" />
|
||||
|
||||
<ListBox ItemsSource="{Binding NavItems}"
|
||||
SelectedItem="{Binding SelectedNav}"
|
||||
Background="Transparent"
|
||||
Margin="4,0">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" Padding="12,8" FontSize="14" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Main content -->
|
||||
<Border Padding="16">
|
||||
<ContentControl Content="{Binding CurrentView}" />
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
11
OTSSignsOrchestrator.Desktop/Views/MainWindow.axaml.cs
Normal file
11
OTSSignsOrchestrator.Desktop/Views/MainWindow.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
37
OTSSignsOrchestrator.Desktop/Views/SecretsView.axaml
Normal file
37
OTSSignsOrchestrator.Desktop/Views/SecretsView.axaml
Normal file
@@ -0,0 +1,37 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.SecretsView"
|
||||
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}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Margin="0,8,0,0"
|
||||
FontSize="12" Foreground="#a6adc8" />
|
||||
|
||||
<DataGrid ItemsSource="{Binding Secrets}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="ID" Binding="{Binding Id}" Width="200" />
|
||||
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="250" />
|
||||
<DataGridTextColumn Header="Created" Binding="{Binding CreatedAt, StringFormat='{}{0:g}'}" Width="180" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
11
OTSSignsOrchestrator.Desktop/Views/SecretsView.axaml.cs
Normal file
11
OTSSignsOrchestrator.Desktop/Views/SecretsView.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class SecretsView : UserControl
|
||||
{
|
||||
public SecretsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
205
OTSSignsOrchestrator.Desktop/Views/SettingsView.axaml
Normal file
205
OTSSignsOrchestrator.Desktop/Views/SettingsView.axaml
Normal file
@@ -0,0 +1,205 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.SettingsView"
|
||||
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" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Scrollable settings content -->
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="16" Margin="0,0,16,16" MaxWidth="800">
|
||||
|
||||
<!-- ═══ Git Repository ═══ -->
|
||||
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Git Repository" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#89b4fa" Margin="0,0,0,4" />
|
||||
<TextBlock Text="Template repository cloned for each new instance."
|
||||
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
|
||||
|
||||
<TextBlock Text="Repository URL" FontSize="12" />
|
||||
<TextBox Text="{Binding GitRepoUrl}"
|
||||
Watermark="https://github.com/org/template-repo.git" />
|
||||
|
||||
<TextBlock Text="Personal Access Token (PAT)" FontSize="12" />
|
||||
<TextBox Text="{Binding GitRepoPat}" PasswordChar="●"
|
||||
Watermark="ghp_xxxx..." />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ═══ MySQL Connection ═══ -->
|
||||
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="MySQL Connection" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#a6e3a1" Margin="0,0,0,4" />
|
||||
<TextBlock Text="Admin credentials used to create databases and users for new instances."
|
||||
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
|
||||
|
||||
<Grid ColumnDefinitions="3*,8,1*" RowDefinitions="Auto,Auto">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Host" FontSize="12" />
|
||||
<TextBox Text="{Binding MySqlHost}" Watermark="cms-sql.otshosting.app" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Port" FontSize="12" />
|
||||
<TextBox Text="{Binding MySqlPort}" Watermark="3306" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="Admin Username" FontSize="12" />
|
||||
<TextBox Text="{Binding MySqlAdminUser}" Watermark="root" />
|
||||
|
||||
<TextBlock Text="Admin Password" FontSize="12" />
|
||||
<TextBox Text="{Binding MySqlAdminPassword}" PasswordChar="●" />
|
||||
|
||||
<Button Content="Test MySQL Connection"
|
||||
Command="{Binding TestMySqlConnectionCommand}"
|
||||
IsEnabled="{Binding !IsBusy}"
|
||||
Margin="0,4,0,0" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ═══ SMTP Settings ═══ -->
|
||||
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="SMTP Settings" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#f5c2e7" Margin="0,0,0,4" />
|
||||
<TextBlock Text="Email configuration applied to all CMS instances."
|
||||
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
|
||||
|
||||
<TextBlock Text="SMTP Server (host:port)" FontSize="12" />
|
||||
<TextBox Text="{Binding SmtpServer}" Watermark="smtp.azurecomm.net:587" />
|
||||
|
||||
<TextBlock Text="SMTP Username" FontSize="12" />
|
||||
<TextBox Text="{Binding SmtpUsername}" Watermark="user@domain.com" />
|
||||
|
||||
<TextBlock Text="SMTP Password" FontSize="12" />
|
||||
<TextBox Text="{Binding SmtpPassword}" PasswordChar="●" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="16">
|
||||
<CheckBox Content="Use TLS" IsChecked="{Binding SmtpUseTls}" />
|
||||
<CheckBox Content="Use STARTTLS" IsChecked="{Binding SmtpUseStartTls}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="Rewrite Domain" FontSize="12" />
|
||||
<TextBox Text="{Binding SmtpRewriteDomain}" Watermark="ots-signs.com" />
|
||||
|
||||
<TextBlock Text="SMTP Hostname" FontSize="12" />
|
||||
<TextBox Text="{Binding SmtpHostname}" Watermark="demo.ots-signs.com" />
|
||||
|
||||
<TextBlock Text="From Line Override" FontSize="12" />
|
||||
<TextBox Text="{Binding SmtpFromLineOverride}" Watermark="NO" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ═══ Pangolin / Newt ═══ -->
|
||||
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Pangolin (Newt Tunnel)" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#fab387" Margin="0,0,0,4" />
|
||||
<TextBlock Text="Global Pangolin endpoint. Newt ID and Secret are configured per-instance."
|
||||
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
|
||||
|
||||
<TextBlock Text="Pangolin Endpoint URL" FontSize="12" />
|
||||
<TextBox Text="{Binding PangolinEndpoint}" Watermark="https://app.pangolin.net" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ═══ CIFS Volumes ═══ -->
|
||||
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="CIFS Volumes" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#cba6f7" Margin="0,0,0,4" />
|
||||
<TextBlock Text="Network share settings for Docker volumes. Volumes will be mounted via CIFS."
|
||||
FontSize="12" Foreground="#6c7086" Margin="0,0,0,4" />
|
||||
|
||||
<TextBlock Text="CIFS Server (hostname/IP)" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsServer}" Watermark="nas.local" />
|
||||
|
||||
<TextBlock Text="Share Base Path" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsShareBasePath}" Watermark="/share/cms" />
|
||||
|
||||
<TextBlock Text="Username" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsUsername}" Watermark="smbuser" />
|
||||
|
||||
<TextBlock Text="Password" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsPassword}" PasswordChar="●" />
|
||||
|
||||
<TextBlock Text="Extra Mount Options" FontSize="12" />
|
||||
<TextBox Text="{Binding CifsOptions}" Watermark="file_mode=0777,dir_mode=0777" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- ═══ Instance Defaults ═══ -->
|
||||
<Border Background="#1e1e2e" CornerRadius="8" Padding="16">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Instance Defaults" FontSize="16" FontWeight="SemiBold"
|
||||
Foreground="#89dceb" Margin="0,0,0,4" />
|
||||
<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" />
|
||||
|
||||
<TextBlock Text="Docker Images" FontSize="13" FontWeight="SemiBold" Margin="0,8,0,4" />
|
||||
|
||||
<TextBlock Text="CMS Image" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultCmsImage}"
|
||||
Watermark="ghcr.io/xibosignage/xibo-cms:release-4.2.3" />
|
||||
|
||||
<TextBlock Text="Newt Image" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultNewtImage}" Watermark="fosrl/newt" />
|
||||
|
||||
<TextBlock Text="Memcached Image" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultMemcachedImage}" Watermark="memcached:alpine" />
|
||||
|
||||
<TextBlock Text="QuickChart Image" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultQuickChartImage}" Watermark="ianw/quickchart" />
|
||||
|
||||
<TextBlock Text="Naming Templates" FontSize="13" FontWeight="SemiBold" Margin="0,12,0,4" />
|
||||
|
||||
<TextBlock Text="CMS Server Name Template" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultCmsServerNameTemplate}"
|
||||
Watermark="{}{abbrev}.ots-signs.com" />
|
||||
|
||||
<TextBlock Text="Theme Host Path Template" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultThemeHostPath}"
|
||||
Watermark="/cms/{abbrev}-cms-theme-custom" />
|
||||
|
||||
<TextBlock Text="MySQL Database Name Template" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultMySqlDbTemplate}" Watermark="{}{abbrev}_cms_db" />
|
||||
|
||||
<TextBlock Text="MySQL User Template" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultMySqlUserTemplate}" Watermark="{}{abbrev}_cms" />
|
||||
|
||||
<TextBlock Text="PHP Settings" FontSize="13" FontWeight="SemiBold" Margin="0,12,0,4" />
|
||||
|
||||
<Grid ColumnDefinitions="1*,8,1*,8,1*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Post Max Size" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultPhpPostMaxSize}" Watermark="10G" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Upload Max Filesize" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultPhpUploadMaxFilesize}" Watermark="10G" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="4" Spacing="4">
|
||||
<TextBlock Text="Max Execution Time" FontSize="12" />
|
||||
<TextBox Text="{Binding DefaultPhpMaxExecutionTime}" Watermark="600" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
11
OTSSignsOrchestrator.Desktop/Views/SettingsView.axaml.cs
Normal file
11
OTSSignsOrchestrator.Desktop/Views/SettingsView.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace OTSSignsOrchestrator.Desktop.Views;
|
||||
|
||||
public partial class SettingsView : UserControl
|
||||
{
|
||||
public SettingsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user