Files
dnsmasq-webui/src/DnsmasqWebUI/Infrastructure/Helpers/Config/EffectiveConfigViews.cs
T
alex fd16d50107 Add DNS Records and Filters pages; unify effective config layout
- Add EffectiveConfigContext.DnsRecords and .Filters; map in EffectiveConfigViews
- Add DnsRecords.razor and Filters.razor with context-scoped effective config
- Add nav links for DNS records and Filters (icons: diagram-3-fill, funnel-fill)
- Put effective config block at top of Hosts, DHCP, DNS Records, Filters (no config file list on sub-pages)
- Hosts view: add expand-hosts to allow-list. Filters view: add domain-needed, bogus-priv, filterwin2k, no-round-robin
- Page titles: Hosts Configuration, DHCP Configuration, DNS Records Configuration, Filters Configuration
- Remove 'Config affecting...' subheadings and page intro text; add .page-intro and .page-chip styles
2026-03-09 23:22:13 +10:00

115 lines
4.7 KiB
C#

using DnsmasqWebUI.Models.Dnsmasq;
using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig;
using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions;
namespace DnsmasqWebUI.Infrastructure.Helpers.Config;
/// <summary>
/// Defines which sections and (optionally) which fields are visible per EffectiveConfigContext.
/// Single place to add new contexts or change what shows on Hosts/DHCP/etc.
/// </summary>
public static class EffectiveConfigViews
{
/// <summary>
/// Ordered list of sections and optional field allow-lists for the given context.
/// </summary>
public static IReadOnlyList<EffectiveConfigSectionView> GetViewsForContext(EffectiveConfigContext context)
{
return context switch
{
EffectiveConfigContext.All => GetAllSections(),
EffectiveConfigContext.Hosts => GetHostsView(),
EffectiveConfigContext.Dhcp => GetDhcpView(),
EffectiveConfigContext.DnsRecords => GetDnsRecordsView(),
EffectiveConfigContext.Filters => GetFiltersView(),
_ => [],
};
}
private static IReadOnlyList<EffectiveConfigSectionView> GetAllSections()
{
return EffectiveConfigSections.Sections
.Select(s => new EffectiveConfigSectionView(s.SectionId, s.Title, null))
.ToList();
}
private static IReadOnlyList<EffectiveConfigSectionView> GetHostsView() =>
[
new(EffectiveConfigSections.SectionHosts, "Hosts", [
DnsmasqConfKeys.NoHosts,
DnsmasqConfKeys.AddnHosts,
DnsmasqConfKeys.Hostsdir,
DnsmasqConfKeys.ReadEthers,
DnsmasqConfKeys.ExpandHosts,
]),
];
private static IReadOnlyList<EffectiveConfigSectionView> GetDhcpView() =>
[
new(EffectiveConfigSections.SectionDhcp, "DHCP", null),
new(EffectiveConfigSections.SectionTftpPxe, "TFTP / PXE", null),
];
private static IReadOnlyList<EffectiveConfigSectionView> GetDnsRecordsView() =>
[
new(EffectiveConfigSections.SectionDnsRecords, "DNS records", null),
];
private static IReadOnlyList<EffectiveConfigSectionView> GetFiltersView() =>
[
new(EffectiveConfigSections.SectionResolver, "Resolver / DNS", [
DnsmasqConfKeys.DomainNeeded,
DnsmasqConfKeys.Local,
DnsmasqConfKeys.Server,
DnsmasqConfKeys.RevServer,
DnsmasqConfKeys.Address,
DnsmasqConfKeys.BogusPriv,
DnsmasqConfKeys.BogusNxdomain,
DnsmasqConfKeys.IgnoreAddress,
DnsmasqConfKeys.Alias,
DnsmasqConfKeys.Filterwin2k,
DnsmasqConfKeys.FilterA,
DnsmasqConfKeys.FilterAaaa,
DnsmasqConfKeys.FilterRr,
DnsmasqConfKeys.StopDnsRebind,
DnsmasqConfKeys.RebindLocalhostOk,
DnsmasqConfKeys.RebindDomainOk,
DnsmasqConfKeys.Ipset,
DnsmasqConfKeys.Nftset,
DnsmasqConfKeys.ConnmarkAllowlistEnable,
DnsmasqConfKeys.ConnmarkAllowlist,
DnsmasqConfKeys.NoRoundRobin,
]),
];
/// <summary>
/// For each section in the view, returns the context-visible descriptors for that section.
/// Does not apply search; component applies search to each section's list and hides sections with no matches.
/// </summary>
/// <param name="registry">When provided, used to create the correct descriptor type per field (e.g. integer options).</param>
public static IReadOnlyDictionary<string, IReadOnlyList<EffectiveConfigFieldDescriptor>> GetDescriptorsBySection(
DnsmasqServiceStatus? status,
IReadOnlyList<EffectiveConfigSectionView> views,
IEffectiveConfigRenderFragmentRegistry? registry = null)
{
if (status == null || views.Count == 0)
return new Dictionary<string, IReadOnlyList<EffectiveConfigFieldDescriptor>>();
var allDescriptors = EffectiveConfigFieldBuilder.BuildFieldDescriptors(status, registry);
var result = new Dictionary<string, List<EffectiveConfigFieldDescriptor>>(StringComparer.OrdinalIgnoreCase);
foreach (var view in views)
{
var list = allDescriptors
.Where(d => string.Equals(d.SectionId, view.SectionId, StringComparison.OrdinalIgnoreCase))
.Where(d => view.AllowedOptionNames == null
|| view.AllowedOptionNames.Contains(d.OptionName, StringComparer.OrdinalIgnoreCase))
.ToList();
if (list.Count > 0)
result[view.SectionId] = list;
}
return result.ToDictionary(kv => kv.Key, kv => (IReadOnlyList<EffectiveConfigFieldDescriptor>)kv.Value, StringComparer.OrdinalIgnoreCase);
}
}