feat: allow searching by server name
All checks were successful
Caddy Manager CI build / docker (push) Successful in 1m1s

This commit is contained in:
2025-07-12 10:55:04 +07:00
parent d90b77d537
commit d0bb0f709a
7 changed files with 42 additions and 58 deletions

View File

@@ -1,5 +1,6 @@
@page "/" @page "/"
@attribute [StreamRendering] @attribute [StreamRendering]
@using CaddyManager.Models.Caddy
<PageTitle>Reverse proxy configurations</PageTitle> <PageTitle>Reverse proxy configurations</PageTitle>
@@ -24,11 +25,11 @@
AdornmentIcon="@(string.IsNullOrWhiteSpace(_debouncedText) ? Icons.Material.Filled.Search : Icons.Material.Filled.Close)" AdornmentIcon="@(string.IsNullOrWhiteSpace(_debouncedText) ? Icons.Material.Filled.Search : Icons.Material.Filled.Close)"
OnAdornmentClick="HandleSearchBarAdornmentClick" /> OnAdornmentClick="HandleSearchBarAdornmentClick" />
</MudContainer> </MudContainer>
<MudList T="string" Class="pt-10" SelectionMode="SelectionMode.MultiSelection" <MudList T="CaddyConfigurationInfo" Class="pt-10" SelectionMode="SelectionMode.MultiSelection"
@bind-SelectedValues="_selectedCaddyConfigurations"> @bind-SelectedValues="_selectedCaddyConfigurations">
@foreach (var (index, caddyConfig) in _availableCaddyConfigurations.Index()) @foreach (var (index, caddyConfig) in _availableCaddyConfigurations.Index())
{ {
<CaddyReverseProxyItem FileName="@caddyConfig" OnCaddyRestartRequired="@RestartCaddy"/> <CaddyReverseProxyItem ConfigurationInfo="@caddyConfig" OnCaddyRestartRequired="@RestartCaddy"/>
@if (index < _availableCaddyConfigurations.Count - 1) @if (index < _availableCaddyConfigurations.Count - 1)
{ {

View File

@@ -2,9 +2,11 @@ using System.Globalization;
using CaddyManager.Components.Pages.Generic; using CaddyManager.Components.Pages.Generic;
using CaddyManager.Contracts.Caddy; using CaddyManager.Contracts.Caddy;
using CaddyManager.Contracts.Docker; using CaddyManager.Contracts.Docker;
using CaddyManager.Models.Caddy;
using Humanizer; using Humanizer;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MudBlazor; using MudBlazor;
using CaddyfileEditorComponent = CaddyManager.Components.Pages.Caddy.CaddyfileEditor.CaddyfileEditor;
namespace CaddyManager.Components.Pages.Caddy.CaddyReverseProxies; namespace CaddyManager.Components.Pages.Caddy.CaddyReverseProxies;
@@ -15,8 +17,8 @@ namespace CaddyManager.Components.Pages.Caddy.CaddyReverseProxies;
public partial class CaddyReverseProxiesPage : ComponentBase public partial class CaddyReverseProxiesPage : ComponentBase
{ {
private bool _isProcessing; private bool _isProcessing;
private List<string> _availableCaddyConfigurations = []; private List<CaddyConfigurationInfo> _availableCaddyConfigurations = [];
private IReadOnlyCollection<string> _selectedCaddyConfigurations = []; private IReadOnlyCollection<CaddyConfigurationInfo> _selectedCaddyConfigurations = [];
private string _debouncedText = string.Empty; private string _debouncedText = string.Empty;
[Inject] private ICaddyService CaddyService { get; set; } = null!; [Inject] private ICaddyService CaddyService { get; set; } = null!;
@@ -41,14 +43,14 @@ public partial class CaddyReverseProxiesPage : ComponentBase
/// <returns></returns> /// <returns></returns>
private async Task NewReverseProxy() private async Task NewReverseProxy()
{ {
var dialog = await DialogService.ShowAsync<CaddyfileEditor.CaddyfileEditor>("New configuration", var dialog = await DialogService.ShowAsync<CaddyfileEditorComponent>("New configuration",
options: new MudBlazor.DialogOptions options: new DialogOptions
{ {
FullWidth = true, FullWidth = true,
MaxWidth = MudBlazor.MaxWidth.Medium MaxWidth = MaxWidth.Medium
}, parameters: new MudBlazor.DialogParameters }, parameters: new DialogParameters<CaddyfileEditorComponent>
{ {
{ "FileName", string.Empty } { p => p.FileName, string.Empty }
}); });
var result = await dialog.Result; var result = await dialog.Result;
@@ -66,9 +68,9 @@ public partial class CaddyReverseProxiesPage : ComponentBase
private void Refresh() private void Refresh()
{ {
var notSearching = string.IsNullOrWhiteSpace(_debouncedText); var notSearching = string.IsNullOrWhiteSpace(_debouncedText);
_availableCaddyConfigurations = CaddyService.GetExistingCaddyConfigurations() _availableCaddyConfigurations = [..CaddyService.GetExistingCaddyConfigurations()
.Where(confName => notSearching || confName.Contains(_debouncedText, StringComparison.OrdinalIgnoreCase)) .Where(conf => notSearching || conf.FileName.Contains(_debouncedText, StringComparison.OrdinalIgnoreCase) || conf.ReverseProxyHostname.Contains(_debouncedText, StringComparison.OrdinalIgnoreCase))
.ToList(); .OrderBy(conf => conf.FileName)];
StateHasChanged(); StateHasChanged();
} }
@@ -93,10 +95,10 @@ public partial class CaddyReverseProxiesPage : ComponentBase
{ {
p => p.OnConfirm, EventCallback.Factory.Create(this, () => p => p.OnConfirm, EventCallback.Factory.Create(this, () =>
{ {
var response = CaddyService.DeleteCaddyConfigurations(_selectedCaddyConfigurations.ToList()); var response = CaddyService.DeleteCaddyConfigurations(_selectedCaddyConfigurations.Select(c => c.FileName).ToList());
_selectedCaddyConfigurations = _selectedCaddyConfigurations =
_selectedCaddyConfigurations.Except(response.DeletedConfigurations).ToList(); _selectedCaddyConfigurations.Where(c => !response.DeletedConfigurations.Contains(c.FileName)).ToList();
if (response.Success) if (response.Success)
{ {

View File

@@ -1,10 +1,11 @@
@using Humanizer @using Humanizer
@using CaddyManager.Models.Caddy
@attribute [StreamRendering] @attribute [StreamRendering]
<MudListItem T="string" Text="@FileName" OnClick="Edit" OnClickPreventDefault="true"> <MudListItem T="CaddyConfigurationInfo" Text="@ConfigurationInfo.FileName" OnClick="Edit" OnClickPreventDefault="true">
<MudStack Row AlignItems="AlignItems.Center" Class="pl-2"> <MudStack Row AlignItems="AlignItems.Center" Class="pl-2">
<MudIcon Icon="@Icons.Custom.FileFormats.FileCode"></MudIcon> <MudIcon Icon="@Icons.Custom.FileFormats.FileCode"></MudIcon>
<MudText>@FileName</MudText> <MudText>@ConfigurationInfo.FileName</MudText>
<MudSpacer/> <MudSpacer/>
<MudChip T="string" Variant="Variant.Outlined">@ConfigurationInfo.ReverseProxyHostname</MudChip> <MudChip T="string" Variant="Variant.Outlined">@ConfigurationInfo.ReverseProxyHostname</MudChip>
<MudTooltip Delay="0" Placement="Placement.Left"> <MudTooltip Delay="0" Placement="Placement.Left">

View File

@@ -11,49 +11,21 @@ namespace CaddyManager.Components.Pages.Caddy.CaddyReverseProxies;
/// </summary> /// </summary>
public partial class CaddyReverseProxyItem : ComponentBase public partial class CaddyReverseProxyItem : ComponentBase
{ {
/// <summary>
/// File path of the Caddy configuration file
/// </summary>
[Parameter]
public string FileName { get; set; } = string.Empty;
/// <summary> /// <summary>
/// Callback to refresh the Caddy reverse proxies on the main page /// Callback to refresh the Caddy reverse proxies on the main page
/// </summary> /// </summary>
[Parameter] [Parameter]
public EventCallback OnCaddyRestartRequired { get; set; } public EventCallback OnCaddyRestartRequired { get; set; }
[Parameter]
public CaddyConfigurationInfo ConfigurationInfo { get; set; } = null!;
/// <summary> /// <summary>
/// Dialog service for showing the Caddy file editor dialog /// Dialog service for showing the Caddy file editor dialog
/// </summary> /// </summary>
[Inject] [Inject]
private IDialogService DialogService { get; set; } = null!; private IDialogService DialogService { get; set; } = null!;
/// <summary>
/// Caddy service for getting the Caddy configuration file information
/// </summary>
[Inject]
private ICaddyService CaddyService { get; set; } = null!;
private CaddyConfigurationInfo ConfigurationInfo { get; set; } = new();
/// <summary>
/// Refresh the current state of the component.
/// </summary>
private void Refresh()
{
ConfigurationInfo = CaddyService.GetCaddyConfigurationInfo(FileName);
StateHasChanged();
}
/// <inheritdoc />
protected override void OnAfterRender(bool firstRender)
{
if (!firstRender) return;
Refresh();
}
/// <summary> /// <summary>
/// Show the Caddy file editor dialog /// Show the Caddy file editor dialog
/// </summary> /// </summary>
@@ -63,10 +35,10 @@ public partial class CaddyReverseProxyItem : ComponentBase
var dialog = await DialogService.ShowAsync<CaddyfileEditor.CaddyfileEditor>("Caddy file", options: new DialogOptions var dialog = await DialogService.ShowAsync<CaddyfileEditor.CaddyfileEditor>("Caddy file", options: new DialogOptions
{ {
FullWidth = true, FullWidth = true,
MaxWidth = MaxWidth.Medium, MaxWidth = MudBlazor.MaxWidth.Medium,
}, parameters: new DialogParameters }, parameters: new MudBlazor.DialogParameters
{ {
{ "FileName", FileName } { "FileName", ConfigurationInfo.FileName }
}); });
var result = await dialog.Result; var result = await dialog.Result;
@@ -75,7 +47,5 @@ public partial class CaddyReverseProxyItem : ComponentBase
{ {
await OnCaddyRestartRequired.InvokeAsync(); await OnCaddyRestartRequired.InvokeAsync();
} }
Refresh();
} }
} }

View File

@@ -11,7 +11,7 @@ public interface ICaddyService
/// Returns the existing Caddy configurations within the configured directory /// Returns the existing Caddy configurations within the configured directory
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
List<string> GetExistingCaddyConfigurations(); List<CaddyConfigurationInfo> GetExistingCaddyConfigurations();
/// <summary> /// <summary>
/// Method to get the content of a Caddy configuration file by its name /// Method to get the content of a Caddy configuration file by its name

View File

@@ -19,4 +19,9 @@ public class CaddyConfigurationInfo
/// Ports being used with the reverse proxy hostname /// Ports being used with the reverse proxy hostname
/// </summary> /// </summary>
public List<int> ReverseProxyPorts { get; set; } = []; public List<int> ReverseProxyPorts { get; set; } = [];
/// <summary>
/// The name of the configuration file.
/// </summary>
public string FileName { get; set; } = string.Empty;
} }

View File

@@ -18,18 +18,23 @@ public class CaddyService(
private CaddyServiceConfigurations Configurations => configurationsService.Get<CaddyServiceConfigurations>(); private CaddyServiceConfigurations Configurations => configurationsService.Get<CaddyServiceConfigurations>();
/// <inheritdoc /> /// <inheritdoc />
public List<string> GetExistingCaddyConfigurations() public List<CaddyConfigurationInfo> GetExistingCaddyConfigurations()
{ {
if (!Directory.Exists(Configurations.ConfigDir)) if (!Directory.Exists(Configurations.ConfigDir))
{ {
Directory.CreateDirectory(Configurations.ConfigDir); Directory.CreateDirectory(Configurations.ConfigDir);
} }
return Directory.GetFiles(Configurations.ConfigDir) return [.. Directory.GetFiles(Configurations.ConfigDir)
.Where(filePath => Path.GetFileName(filePath) != CaddyGlobalConfigName) .Where(filePath => Path.GetFileName(filePath) != CaddyGlobalConfigName)
.Select(Path.GetFileNameWithoutExtension) .Select(filePath =>
.Order() {
.ToList()!; var fileName = Path.GetFileNameWithoutExtension(filePath);
var info = GetCaddyConfigurationInfo(fileName);
info.FileName = fileName;
return info;
})
.OrderBy(info => info.FileName)];
} }
/// <inheritdoc /> /// <inheritdoc />