Files
dashcaddy/desktop/AddServiceDialog.xaml.cs
Hermes 86e4c9fc81 wip: Windows desktop app scaffold (WinUI 3/.NET 8) + NSIS installer + docs
Owner decision pending (STATE.md DC-100 tick): adopt/ship/park.
Preserved from fragile git stash to named branch 2026-08-23.
NOTE: requires a Windows build machine (WinUI XAML compiler + MSIX do not
cross-build on Linux) — see WINDOWS_APP_BUILD.md in this tree.
Secret-scanned clean 2026-08-23 (no keys/tokens/PEM in tree).
2026-08-22 23:50:34 -07:00

172 lines
5.8 KiB
C#

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using DashCaddy.Desktop.ViewModels;
using DashCaddy.Desktop.Services;
using System.Collections.Generic;
namespace DashCaddy.Desktop;
public sealed partial class AddServiceDialog : ContentDialog
{
public MainViewModel ViewModel { get; }
public AddServiceDialog(MainViewModel viewModel)
{
ViewModel = viewModel;
InitializeComponent();
LoadTemplates();
}
private void LoadTemplates()
{
var templates = TemplateRegistry.GetAll().ToList();
TemplateCombo.ItemsSource = templates;
if (templates.Count > 0)
TemplateCombo.SelectedIndex = 0;
}
private void AddMethod_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (AddMethodRadio.SelectedItem is RadioButton rb)
{
var method = rb.Tag?.ToString();
TemplatePanel.Visibility = method == "template" ? Visibility.Visible : Visibility.Collapsed;
ComposePanel.Visibility = method == "compose" ? Visibility.Visible : Visibility.Collapsed;
CustomPanel.Visibility = method == "custom" ? Visibility.Visible : Visibility.Collapsed;
}
}
private void TemplateCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (TemplateCombo.SelectedItem is ServiceTemplate template)
{
ViewModel.TemplateVariables = template.RequiredVariables.Length > 0 || template.Environment.Count > 0
? BuildVariables(template)
: new List<VariableViewModel>();
VariablesPanel.Visibility = ViewModel.TemplateVariables.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
}
}
private List<VariableViewModel> BuildVariables(ServiceTemplate template)
{
var vars = new List<VariableViewModel>();
foreach (var (key, value) in template.Environment)
{
vars.Add(new VariableViewModel
{
Key = key,
Value = value,
Placeholder = key,
Description = $"Environment variable: {key}"
});
}
foreach (var required in template.RequiredVariables)
{
if (!vars.Exists(v => v.Key == required))
{
vars.Add(new VariableViewModel
{
Key = required,
Value = "",
Placeholder = required,
Description = $"Required: {required}"
});
}
}
return vars;
}
private async void BrowseCompose_Click(object sender, RoutedEventArgs e)
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.FileTypeFilter.Add(".yaml");
picker.FileTypeFilter.Add(".yml");
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
var file = await picker.PickSingleFileAsync();
if (file != null)
{
ComposePathText.Text = file.Path;
ViewModel.SelectedComposeFile = file.Path;
}
}
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
if (AddMethodRadio.SelectedItem is RadioButton rb)
{
var method = rb.Tag?.ToString();
switch (method)
{
case "template":
if (TemplateCombo.SelectedItem is ServiceTemplate template)
{
var variables = new Dictionary<string, string>();
foreach (var v in ViewModel.TemplateVariables)
{
variables[v.Key] = v.Value;
}
ViewModel.SelectedTemplate = template;
ViewModel.TemplateVariablesDict = variables;
}
else
{
args.Cancel = true;
}
break;
case "compose":
if (string.IsNullOrEmpty(ViewModel.SelectedComposeFile))
{
args.Cancel = true;
}
break;
case "custom":
if (string.IsNullOrWhiteSpace(CustomName.Text) || string.IsNullOrWhiteSpace(CustomImage.Text))
{
args.Cancel = true;
}
else
{
ViewModel.CustomService = new
{
Name = CustomName.Text,
Image = CustomImage.Text,
Port = int.TryParse(CustomPort.Text, out var p) ? p : 80,
Domain = CustomDomain.Text,
Volumes = CustomVolumes.Text.Split('\n', StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()).ToList(),
Environment = ParseEnv(CustomEnv.Text)
};
}
break;
}
}
}
private Dictionary<string, string> ParseEnv(string text)
{
var dict = new Dictionary<string, string>();
foreach (var line in text.Split('\n', StringSplitOptions.RemoveEmptyEntries))
{
var parts = line.Split('=', 2);
if (parts.Length == 2)
dict[parts[0].Trim()] = parts[1].Trim();
}
return dict;
}
}
public class VariableViewModel
{
public string Key { get; set; }
public string Value { get; set; }
public string Placeholder { get; set; }
public string Description { get; set; }
}