mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-03 22:12:00 +10:00
Hosts page UX: simpler table, projection, and effective-config tweaks
Remove the Status column and row-level badges/actions; keep source-level Editable on group headers. Double-click managed rows to edit; commit staged drafts when focus leaves the row via isFocusOutsideElement in the shared scroll-cue module. Hide inactive system-host rows when dnsmasq ignores them and move system-hosts / expand-hosts notes below the content area. Memoize VisibleGroups so BuildGroups runs once per render during search. Move read-ethers metadata to the DHCP section; adjust Hosts page state copy and related effective-config tooltips/builders where needed.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
|
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
|
||||||
@using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions
|
@using DnsmasqWebUI.Infrastructure.Services.Dnsmasq.Hosts.Abstractions
|
||||||
@using DnsmasqWebUI.Components.EffectiveConfig
|
@using DnsmasqWebUI.Components.EffectiveConfig
|
||||||
|
@using Microsoft.AspNetCore.Components.Web
|
||||||
@using Microsoft.JSInterop
|
@using Microsoft.JSInterop
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
@inject IStatusClient StatusClient
|
@inject IStatusClient StatusClient
|
||||||
@@ -37,13 +38,6 @@ else
|
|||||||
<EffectiveConfigSection Status="_status" Context="EffectiveConfigContext.Hosts" ShowSearchBox="true" OnSaveCompleted="RefreshStatusAsync" />
|
<EffectiveConfigSection Status="_status" Context="EffectiveConfigContext.Hosts" ShowSearchBox="true" OnSaveCompleted="RefreshStatusAsync" />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@if (!pageState.SystemHostsActive && !string.IsNullOrEmpty(pageState.SystemHostsInactiveReason))
|
|
||||||
{
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<strong>System hosts</strong> is inactive: @pageState.SystemHostsInactiveReason
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (!pageState.ManagedHostsAvailable)
|
@if (!pageState.ManagedHostsAvailable)
|
||||||
{
|
{
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
@@ -97,14 +91,13 @@ else
|
|||||||
<th scope="col">Address</th>
|
<th scope="col">Address</th>
|
||||||
<th scope="col">Names</th>
|
<th scope="col">Names</th>
|
||||||
<th scope="col">Effective names</th>
|
<th scope="col">Effective names</th>
|
||||||
<th scope="col">Status</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@foreach (var group in VisibleGroups)
|
@foreach (var group in VisibleGroups)
|
||||||
{
|
{
|
||||||
<tbody @key="@group.Key">
|
<tbody @key="@group.Key">
|
||||||
<tr class="hosts-group-header">
|
<tr class="hosts-group-header">
|
||||||
<th colspan="4" scope="colgroup" class="hosts-group-header-cell">
|
<th colspan="3" scope="colgroup" class="hosts-group-header-cell">
|
||||||
<div class="hosts-group-header__content">
|
<div class="hosts-group-header__content">
|
||||||
<div class="hosts-group-header__title">
|
<div class="hosts-group-header__title">
|
||||||
<span>@group.Title</span>
|
<span>@group.Title</span>
|
||||||
@@ -128,32 +121,25 @@ else
|
|||||||
{
|
{
|
||||||
@if (IsEditingRow(row))
|
@if (IsEditingRow(row))
|
||||||
{
|
{
|
||||||
<tr class="hosts-row hosts-row--editing table-info" @key="@("edit:" + row.Id)">
|
<tr class="hosts-row hosts-row--editing table-info"
|
||||||
|
@key="@("edit:" + row.Id)"
|
||||||
|
@ref="_editingRowRef"
|
||||||
|
@onfocusout="OnEditingRowFocusOut">
|
||||||
<td>
|
<td>
|
||||||
<input class="form-control form-control-sm" @bind="_editAddress" />
|
<input class="form-control form-control-sm" @bind="_editAddress" autofocus />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input class="form-control form-control-sm" placeholder="Comma-separated names" @bind="_editNames" />
|
<input class="form-control form-control-sm" placeholder="Comma-separated names" @bind="_editNames" />
|
||||||
</td>
|
</td>
|
||||||
<td class="text-muted small">@string.Join(", ", HostsEffectiveNames.Expand(ParseNamesList(_editNames), pageState.ExpandHostsEnabled, pageState.ExpansionDomain))</td>
|
<td class="text-muted small">@string.Join(", ", HostsEffectiveNames.Expand(ParseNamesList(_editNames), pageState.ExpandHostsEnabled, pageState.ExpansionDomain))</td>
|
||||||
<td>
|
|
||||||
<div class="hosts-status-cell">
|
|
||||||
<span class="hosts-status-pill hosts-status-pill--editable">Editable</span>
|
|
||||||
@if (row.IsComment)
|
|
||||||
{
|
|
||||||
<span class="hosts-status-pill hosts-status-pill--muted">Commented</span>
|
|
||||||
}
|
|
||||||
<div class="hosts-status-actions">
|
|
||||||
<button type="button" class="btn btn-sm btn-primary" @onclick="SaveEditAsync">Save</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary" @onclick="CancelEdit">Cancel</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<tr class="@RowClass(row)" @key="@row.Id">
|
<tr class="@RowClass(row)"
|
||||||
|
@key="@row.Id"
|
||||||
|
title="@(row.IsEditable ? "Double-click to edit" : string.Empty)"
|
||||||
|
@ondblclick="@(() => OnRowDoubleClick(row))">
|
||||||
<td><code>@row.Address</code></td>
|
<td><code>@row.Address</code></td>
|
||||||
<td>@string.Join(", ", row.Names)</td>
|
<td>@string.Join(", ", row.Names)</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -166,30 +152,6 @@ else
|
|||||||
@string.Join(", ", row.EffectiveNames)
|
@string.Join(", ", row.EffectiveNames)
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
<div class="hosts-status-cell">
|
|
||||||
@if (!row.IsActive)
|
|
||||||
{
|
|
||||||
<span class="hosts-status-pill hosts-status-pill--inactive" title="@row.InactiveReason">Inactive</span>
|
|
||||||
}
|
|
||||||
@if (row.IsComment)
|
|
||||||
{
|
|
||||||
<span class="hosts-status-pill hosts-status-pill--muted">Commented</span>
|
|
||||||
}
|
|
||||||
@if (row.IsEditable)
|
|
||||||
{
|
|
||||||
<span class="hosts-status-pill hosts-status-pill--editable">Editable</span>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<span class="hosts-status-pill hosts-status-pill--readonly">Read-only</span>
|
|
||||||
}
|
|
||||||
@if (row.IsEditable && string.IsNullOrEmpty(_editingRowId))
|
|
||||||
{
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary hosts-inline-action" @onclick="() => BeginEdit(row)">Edit</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,17 +162,25 @@ else
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (pageState.ExpandHostsEnabled && !string.IsNullOrEmpty(pageState.ExpansionDomain))
|
|
||||||
{
|
|
||||||
<div class="alert alert-info mt-3 mb-0">
|
|
||||||
<strong>expand-hosts</strong> is enabled with domain <code>@pageState.ExpansionDomain</code>.
|
|
||||||
Simple hostnames (without dots) will be expanded to include the domain suffix.
|
|
||||||
The <strong>Effective names</strong> column shows how dnsmasq will resolve each entry.
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<div class="hosts-page-notes mt-3 d-flex flex-column gap-2">
|
||||||
|
@if (!pageState.SystemHostsActive && !string.IsNullOrEmpty(pageState.SystemHostsInactiveReason))
|
||||||
|
{
|
||||||
|
<div class="alert alert-info mb-0">
|
||||||
|
<strong>System hosts</strong>: @pageState.SystemHostsInactiveReason
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (pageState.ExpandHostsEnabled && !string.IsNullOrEmpty(pageState.ExpansionDomain))
|
||||||
|
{
|
||||||
|
<div class="alert alert-info mb-0">
|
||||||
|
<strong>expand-hosts</strong> is enabled with domain <code>@pageState.ExpansionDomain</code>.
|
||||||
|
Simple hostnames (without dots) will be expanded to include the domain suffix.
|
||||||
|
The <strong>Effective names</strong> column shows how dnsmasq will resolve each entry.
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -227,10 +197,31 @@ else
|
|||||||
private string? _editingRowId;
|
private string? _editingRowId;
|
||||||
private string _editAddress = "";
|
private string _editAddress = "";
|
||||||
private string _editNames = "";
|
private string _editNames = "";
|
||||||
|
private ElementReference _editingRowRef;
|
||||||
private IJSObjectReference? _hostsTableScrollCueModule;
|
private IJSObjectReference? _hostsTableScrollCueModule;
|
||||||
|
|
||||||
private IReadOnlyList<HostsPageGroup> VisibleGroups =>
|
// Memoize: markup reads VisibleGroups.Count then foreach — avoid building twice per render.
|
||||||
HostsProjection.BuildGroups(_unifiedRows, BuildQuery());
|
private IReadOnlyList<HostsPageGroup>? _visibleGroupsCache;
|
||||||
|
private object? _visibleGroupsCacheRowsRef;
|
||||||
|
private string _visibleGroupsCacheSearch = "\0";
|
||||||
|
|
||||||
|
private IReadOnlyList<HostsPageGroup> VisibleGroups
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_visibleGroupsCache != null
|
||||||
|
&& ReferenceEquals(_visibleGroupsCacheRowsRef, _unifiedRows)
|
||||||
|
&& _visibleGroupsCacheSearch == _search)
|
||||||
|
{
|
||||||
|
return _visibleGroupsCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
_visibleGroupsCache = HostsProjection.BuildGroups(_unifiedRows, BuildQuery());
|
||||||
|
_visibleGroupsCacheRowsRef = _unifiedRows;
|
||||||
|
_visibleGroupsCacheSearch = _search;
|
||||||
|
return _visibleGroupsCache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private HostsPageQueryState BuildQuery()
|
private HostsPageQueryState BuildQuery()
|
||||||
{
|
{
|
||||||
@@ -247,13 +238,15 @@ else
|
|||||||
private static string RowClass(HostsPageRow row)
|
private static string RowClass(HostsPageRow row)
|
||||||
{
|
{
|
||||||
var parts = new List<string> { "hosts-row" };
|
var parts = new List<string> { "hosts-row" };
|
||||||
if (row.IsComment)
|
if (row.IsEditable)
|
||||||
parts.Add("table-secondary");
|
parts.Add("hosts-row--editable");
|
||||||
if (!row.IsActive)
|
if (!row.IsActive)
|
||||||
parts.Add("hosts-row--inactive");
|
parts.Add("hosts-row--inactive");
|
||||||
return string.Join(" ", parts);
|
return string.Join(" ", parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRowDoubleClick(HostsPageRow row) => BeginEdit(row);
|
||||||
|
|
||||||
private bool IsEditingRow(HostsPageRow row) =>
|
private bool IsEditingRow(HostsPageRow row) =>
|
||||||
!string.IsNullOrEmpty(_editingRowId) && string.Equals(_editingRowId, row.Id, StringComparison.Ordinal);
|
!string.IsNullOrEmpty(_editingRowId) && string.Equals(_editingRowId, row.Id, StringComparison.Ordinal);
|
||||||
|
|
||||||
@@ -276,7 +269,30 @@ else
|
|||||||
_editNames = "";
|
_editNames = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveEditAsync()
|
private async Task OnEditingRowFocusOut(FocusEventArgs _)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_editingRowId))
|
||||||
|
return;
|
||||||
|
await Task.Delay(10);
|
||||||
|
if (string.IsNullOrEmpty(_editingRowId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var outside = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_hostsTableScrollCueModule != null)
|
||||||
|
outside = await _hostsTableScrollCueModule.InvokeAsync<bool>("isFocusOutsideElement", _editingRowRef);
|
||||||
|
}
|
||||||
|
catch (JSDisconnectedException)
|
||||||
|
{
|
||||||
|
outside = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outside)
|
||||||
|
await CommitAndEndInlineEditAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CommitAndEndInlineEditAsync()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_editingRowId) || _status == null)
|
if (string.IsNullOrEmpty(_editingRowId) || _status == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -139,6 +139,14 @@
|
|||||||
opacity: 0.72;
|
opacity: 0.72;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::deep .hosts-row--editable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
::deep .hosts-row--editable:hover {
|
||||||
|
background-color: rgba(13, 110, 253, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
::deep .hosts-row code {
|
::deep .hosts-row code {
|
||||||
font-size: 0.93em;
|
font-size: 0.93em;
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
@@ -151,66 +159,6 @@
|
|||||||
background: #f0f7ff;
|
background: #f0f7ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hosts-status-cell {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-pill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.22rem 0.48rem;
|
|
||||||
border-radius: 999px;
|
|
||||||
font-size: 0.72rem;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 1.1;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-pill--active {
|
|
||||||
color: #0f5132;
|
|
||||||
background: #d1e7dd;
|
|
||||||
border-color: #badbcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-pill--inactive {
|
|
||||||
color: #5c3d00;
|
|
||||||
background: #fff3cd;
|
|
||||||
border-color: #ffe69c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-pill--editable {
|
|
||||||
color: #084298;
|
|
||||||
background: #dbeafe;
|
|
||||||
border-color: #b6d4fe;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-pill--readonly {
|
|
||||||
color: #475569;
|
|
||||||
background: #f1f5f9;
|
|
||||||
border-color: #d8e0ea;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-pill--muted {
|
|
||||||
color: #495057;
|
|
||||||
background: #f3f4f6;
|
|
||||||
border-color: #e5e7eb;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-inline-action {
|
|
||||||
margin-left: 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hosts-status-actions {
|
|
||||||
display: inline-flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.3rem;
|
|
||||||
margin-left: 0.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 991.98px) {
|
@media (max-width: 991.98px) {
|
||||||
.hosts-controls-bar {
|
.hosts-controls-bar {
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
|
|||||||
+5
-37
@@ -31,13 +31,15 @@ public sealed class HostsPageProjectionService : IHostsPageProjectionService
|
|||||||
if (query.ActiveFilter is { } act)
|
if (query.ActiveFilter is { } act)
|
||||||
filtered = filtered.Where(r => r.IsActive == act);
|
filtered = filtered.Where(r => r.IsActive == act);
|
||||||
|
|
||||||
|
// When dnsmasq ignores system hosts (e.g. no-hosts), do not show those rows in the table.
|
||||||
|
filtered = filtered.Where(r =>
|
||||||
|
!(r.SourceKind == HostsRowSourceKind.SystemHosts && !r.IsActive));
|
||||||
|
|
||||||
var list = filtered.ToList();
|
var list = filtered.ToList();
|
||||||
if (list.Count == 0)
|
if (list.Count == 0)
|
||||||
return Array.Empty<HostsPageGroup>();
|
return Array.Empty<HostsPageGroup>();
|
||||||
|
|
||||||
return query.Grouping == HostsGroupingMode.Activity
|
return BuildSourceGroups(list, query);
|
||||||
? BuildActivityGroups(list, query)
|
|
||||||
: BuildSourceGroups(list, query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyList<HostsPageGroup> BuildSourceGroups(List<HostsPageRow> rows, HostsPageQueryState query)
|
private static IReadOnlyList<HostsPageGroup> BuildSourceGroups(List<HostsPageRow> rows, HostsPageQueryState query)
|
||||||
@@ -76,40 +78,6 @@ public sealed class HostsPageProjectionService : IHostsPageProjectionService
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IReadOnlyList<HostsPageGroup> BuildActivityGroups(List<HostsPageRow> rows, HostsPageQueryState query)
|
|
||||||
{
|
|
||||||
var orderedGroups = rows
|
|
||||||
.GroupBy(r => r.IsActive)
|
|
||||||
.OrderByDescending(g => g.Key);
|
|
||||||
|
|
||||||
var result = new List<HostsPageGroup>();
|
|
||||||
foreach (var g in orderedGroups)
|
|
||||||
{
|
|
||||||
var sortedRows = SortRows(g, query.Sort, query.Descending).ToList();
|
|
||||||
if (sortedRows.Count == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var active = g.Key;
|
|
||||||
var title = active ? "Active" : "Inactive";
|
|
||||||
var subtitle = active
|
|
||||||
? "Entries from sources dnsmasq loads for hosts."
|
|
||||||
: "Entries from sources that are ignored or unavailable (e.g. system hosts under no-hosts).";
|
|
||||||
|
|
||||||
result.Add(new HostsPageGroup(
|
|
||||||
Key: active ? "activity:active" : "activity:inactive",
|
|
||||||
Title: title,
|
|
||||||
Subtitle: subtitle,
|
|
||||||
SourceKind: null,
|
|
||||||
GroupContainsEditableRows: sortedRows.Any(r => r.IsEditable),
|
|
||||||
IsActive: active,
|
|
||||||
InactiveReason: null,
|
|
||||||
VisibleRowCount: sortedRows.Count,
|
|
||||||
Rows: sortedRows));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<HostsPageRow> SortRows(IEnumerable<HostsPageRow> rows, HostsSortMode sort, bool descending)
|
private static IEnumerable<HostsPageRow> SortRows(IEnumerable<HostsPageRow> rows, HostsSortMode sort, bool descending)
|
||||||
{
|
{
|
||||||
IEnumerable<HostsPageRow> ordered = sort switch
|
IEnumerable<HostsPageRow> ordered = sort switch
|
||||||
|
|||||||
+3
-3
@@ -150,7 +150,7 @@ public static class DnsmasqOptionTooltips
|
|||||||
[DnsmasqConfKeys.DnssecCheckUnsigned] = "Treat unsigned zones as bogus.",
|
[DnsmasqConfKeys.DnssecCheckUnsigned] = "Treat unsigned zones as bogus.",
|
||||||
[DnsmasqConfKeys.DnssecNoTimecheck] = "Do not validate DNSSEC signatures against the current time (e.g. for testing).",
|
[DnsmasqConfKeys.DnssecNoTimecheck] = "Do not validate DNSSEC signatures against the current time (e.g. for testing).",
|
||||||
[DnsmasqConfKeys.DnssecDebug] = "Log DNSSEC validation failures at debug level.",
|
[DnsmasqConfKeys.DnssecDebug] = "Log DNSSEC validation failures at debug level.",
|
||||||
[DnsmasqConfKeys.AddCpeId] = "Add CPE-ID to DHCP requests (for identification).",
|
[DnsmasqConfKeys.AddCpeId] = "Add an identifying string to DNS queries forwarded upstream (EDNS0).",
|
||||||
[DnsmasqConfKeys.DnssecTimestamp] = "Path to file for DNSSEC timestamp (e.g. for validation).",
|
[DnsmasqConfKeys.DnssecTimestamp] = "Path to file for DNSSEC timestamp (e.g. for validation).",
|
||||||
[DnsmasqConfKeys.DnssecLimits] = "DNSSEC validation limits (e.g. max signed zones).",
|
[DnsmasqConfKeys.DnssecLimits] = "DNSSEC validation limits (e.g. max signed zones).",
|
||||||
[DnsmasqConfKeys.TrustAnchor] = "DNSSEC trust anchors. Can repeat.",
|
[DnsmasqConfKeys.TrustAnchor] = "DNSSEC trust anchors. Can repeat.",
|
||||||
@@ -163,8 +163,8 @@ public static class DnsmasqOptionTooltips
|
|||||||
[DnsmasqConfKeys.MaxTtl] = "Maximum TTL for cached responses (cap on upstream TTL).",
|
[DnsmasqConfKeys.MaxTtl] = "Maximum TTL for cached responses (cap on upstream TTL).",
|
||||||
[DnsmasqConfKeys.MaxCacheTtl] = "Maximum TTL for positive cache entries.",
|
[DnsmasqConfKeys.MaxCacheTtl] = "Maximum TTL for positive cache entries.",
|
||||||
[DnsmasqConfKeys.MinCacheTtl] = "Minimum TTL for positive cache entries.",
|
[DnsmasqConfKeys.MinCacheTtl] = "Minimum TTL for positive cache entries.",
|
||||||
[DnsmasqConfKeys.Dumpfile] = "Dump cache to this file (for debugging).",
|
[DnsmasqConfKeys.Dumpfile] = "Pcap file path for packet capture (debugging).",
|
||||||
[DnsmasqConfKeys.Dumpmask] = "Mask for cache dump (which data to include).",
|
[DnsmasqConfKeys.Dumpmask] = "Bitmask selecting which packet types are written to the dump file.",
|
||||||
[DnsmasqConfKeys.UseStaleCache] = "Use stale cache when upstream is unavailable. Off, On (key-only), or custom seconds.",
|
[DnsmasqConfKeys.UseStaleCache] = "Use stale cache when upstream is unavailable. Off, On (key-only), or custom seconds.",
|
||||||
[DnsmasqConfKeys.AddMac] = "Add MAC address to DNS queries. Off, On (key-only), or custom value.",
|
[DnsmasqConfKeys.AddMac] = "Add MAC address to DNS queries. Off, On (key-only), or custom value.",
|
||||||
[DnsmasqConfKeys.StripMac] = "Strip MAC address information from forwarded DNS queries.",
|
[DnsmasqConfKeys.StripMac] = "Strip MAC address information from forwarded DNS queries.",
|
||||||
|
|||||||
+10
-10
@@ -54,7 +54,8 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoHosts, status, s => Config(s)?.NoHosts, s => Sources(s)?.NoHosts, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoHosts, status, s => Config(s)?.NoHosts, s => Sources(s)?.NoHosts, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.AddnHosts, status, null, null, s => ToValueWithSourceList(s?.AddnHostsPaths, Sources(s)?.AddnHostsPaths));
|
list.AddDescriptor(registry, DnsmasqConfKeys.AddnHosts, status, null, null, s => ToValueWithSourceList(s?.AddnHostsPaths, Sources(s)?.AddnHostsPaths));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Hostsdir, status, s => Config(s)?.HostsdirPath, s => Sources(s)?.HostsdirPath, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.Hostsdir, status, s => Config(s)?.HostsdirPath, s => Sources(s)?.HostsdirPath, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ReadEthers, status, s => Config(s)?.ReadEthers, s => Sources(s)?.ReadEthers, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.ExpandHosts, status, s => Config(s)?.ExpandHosts, s => Sources(s)?.ExpandHosts, null);
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.Domain, status, null, null, Items(ec => ec?.DomainValues, src => src?.DomainValues));
|
||||||
|
|
||||||
// Resolver / DNS
|
// Resolver / DNS
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Server, status, null, null, Items(ec => ec?.ServerValues, src => src?.ServerValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.Server, status, null, null, Items(ec => ec?.ServerValues, src => src?.ServerValues));
|
||||||
@@ -78,7 +79,6 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.StopDnsRebind, status, s => Config(s)?.StopDnsRebind, s => Sources(s)?.StopDnsRebind, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.StopDnsRebind, status, s => Config(s)?.StopDnsRebind, s => Sources(s)?.StopDnsRebind, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.RebindLocalhostOk, status, s => Config(s)?.RebindLocalhostOk, s => Sources(s)?.RebindLocalhostOk, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.RebindLocalhostOk, status, s => Config(s)?.RebindLocalhostOk, s => Sources(s)?.RebindLocalhostOk, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ClearOnReload, status, s => Config(s)?.ClearOnReload, s => Sources(s)?.ClearOnReload, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.ClearOnReload, status, s => Config(s)?.ClearOnReload, s => Sources(s)?.ClearOnReload, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ExpandHosts, status, s => Config(s)?.ExpandHosts, s => Sources(s)?.ExpandHosts, null);
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.BogusPriv, status, s => Config(s)?.BogusPriv, s => Sources(s)?.BogusPriv, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.BogusPriv, status, s => Config(s)?.BogusPriv, s => Sources(s)?.BogusPriv, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.RebindDomainOk, status, null, null, Items(ec => ec?.RebindDomainOkValues, src => src?.RebindDomainOkValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.RebindDomainOk, status, null, null, Items(ec => ec?.RebindDomainOkValues, src => src?.RebindDomainOkValues));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.BogusNxdomain, status, null, null, Items(ec => ec?.BogusNxdomainValues, src => src?.BogusNxdomainValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.BogusNxdomain, status, null, null, Items(ec => ec?.BogusNxdomainValues, src => src?.BogusNxdomainValues));
|
||||||
@@ -96,10 +96,10 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoRoundRobin, status, s => Config(s)?.NoRoundRobin, s => Sources(s)?.NoRoundRobin, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoRoundRobin, status, s => Config(s)?.NoRoundRobin, s => Sources(s)?.NoRoundRobin, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DnsForwardMax, status, s => Config(s)?.DnsForwardMax, s => Sources(s)?.DnsForwardMax, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DnsForwardMax, status, s => Config(s)?.DnsForwardMax, s => Sources(s)?.DnsForwardMax, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ConnmarkAllowlist, status, null, null, Items(ec => ec?.ConnmarkAllowlistValues, src => src?.ConnmarkAllowlistValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.ConnmarkAllowlist, status, null, null, Items(ec => ec?.ConnmarkAllowlistValues, src => src?.ConnmarkAllowlistValues));
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.AddCpeId, status, s => Config(s)?.AddCpeId, s => Sources(s)?.AddCpeId, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Do0x20Encode, status, s => Config(s)?.Do0x20EncodeState, s => Sources(s)?.Do0x20Encode, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.Do0x20Encode, status, s => Config(s)?.Do0x20EncodeState, s => Sources(s)?.Do0x20Encode, null);
|
||||||
|
|
||||||
// DNS records
|
// DNS records
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Domain, status, null, null, Items(ec => ec?.DomainValues, src => src?.DomainValues));
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Cname, status, null, null, Items(ec => ec?.CnameValues, src => src?.CnameValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.Cname, status, null, null, Items(ec => ec?.CnameValues, src => src?.CnameValues));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.MxHost, status, null, null, Items(ec => ec?.MxHostValues, src => src?.MxHostValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.MxHost, status, null, null, Items(ec => ec?.MxHostValues, src => src?.MxHostValues));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Srv, status, null, null, Items(ec => ec?.SrvValues, src => src?.SrvValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.Srv, status, null, null, Items(ec => ec?.SrvValues, src => src?.SrvValues));
|
||||||
@@ -121,11 +121,16 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Selfmx, status, s => Config(s)?.Selfmx, s => Sources(s)?.Selfmx, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.Selfmx, status, s => Config(s)?.Selfmx, s => Sources(s)?.Selfmx, null);
|
||||||
|
|
||||||
// DHCP
|
// DHCP
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoDhcpInterface, status, null, null, Items(ec => ec?.NoDhcpInterfaceValues, src => src?.NoDhcpInterfaceValues));
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoDhcpv4Interface, status, null, null, Items(ec => ec?.NoDhcpv4InterfaceValues, src => src?.NoDhcpv4InterfaceValues));
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoDhcpv6Interface, status, null, null, Items(ec => ec?.NoDhcpv6InterfaceValues, src => src?.NoDhcpv6InterfaceValues));
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.EnableRa, status, s => Config(s)?.EnableRa, s => Sources(s)?.EnableRa, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpAuthoritative, status, s => Config(s)?.DhcpAuthoritative, s => Sources(s)?.DhcpAuthoritative, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpAuthoritative, status, s => Config(s)?.DhcpAuthoritative, s => Sources(s)?.DhcpAuthoritative, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpRapidCommit, status, s => Config(s)?.DhcpRapidCommit, s => Sources(s)?.DhcpRapidCommit, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpRapidCommit, status, s => Config(s)?.DhcpRapidCommit, s => Sources(s)?.DhcpRapidCommit, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.LeasefileRo, status, s => Config(s)?.LeasefileRo, s => Sources(s)?.LeasefileRo, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.LeasefileRo, status, s => Config(s)?.LeasefileRo, s => Sources(s)?.LeasefileRo, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Leasequery, status, null, null, Items(ec => ec?.LeasequeryValues, src => src?.LeasequeryValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.Leasequery, status, null, null, Items(ec => ec?.LeasequeryValues, src => src?.LeasequeryValues));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpGenerateNames, status, s => Config(s)?.DhcpGenerateNames, s => Sources(s)?.DhcpGenerateNames, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpGenerateNames, status, s => Config(s)?.DhcpGenerateNames, s => Sources(s)?.DhcpGenerateNames, null);
|
||||||
|
list.AddDescriptor(registry, DnsmasqConfKeys.ReadEthers, status, s => Config(s)?.ReadEthers, s => Sources(s)?.ReadEthers, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpBroadcast, status, s => Config(s)?.DhcpBroadcast, s => Sources(s)?.DhcpBroadcast, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpBroadcast, status, s => Config(s)?.DhcpBroadcast, s => Sources(s)?.DhcpBroadcast, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpSequentialIp, status, s => Config(s)?.DhcpSequentialIp, s => Sources(s)?.DhcpSequentialIp, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpSequentialIp, status, s => Config(s)?.DhcpSequentialIp, s => Sources(s)?.DhcpSequentialIp, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpIgnoreClid, status, s => Config(s)?.DhcpIgnoreClid, s => Sources(s)?.DhcpIgnoreClid, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DhcpIgnoreClid, status, s => Config(s)?.DhcpIgnoreClid, s => Sources(s)?.DhcpIgnoreClid, null);
|
||||||
@@ -186,7 +191,6 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecNoTimecheck, status, s => Config(s)?.DnssecNoTimecheck, s => Sources(s)?.DnssecNoTimecheck, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecNoTimecheck, status, s => Config(s)?.DnssecNoTimecheck, s => Sources(s)?.DnssecNoTimecheck, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecDebug, status, s => Config(s)?.DnssecDebug, s => Sources(s)?.DnssecDebug, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecDebug, status, s => Config(s)?.DnssecDebug, s => Sources(s)?.DnssecDebug, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ProxyDnssec, status, s => Config(s)?.ProxyDnssec, s => Sources(s)?.ProxyDnssec, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.ProxyDnssec, status, s => Config(s)?.ProxyDnssec, s => Sources(s)?.ProxyDnssec, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.AddCpeId, status, s => Config(s)?.AddCpeId, s => Sources(s)?.AddCpeId, null);
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecTimestamp, status, s => Config(s)?.DnssecTimestamp, s => Sources(s)?.DnssecTimestamp, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecTimestamp, status, s => Config(s)?.DnssecTimestamp, s => Sources(s)?.DnssecTimestamp, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecLimits, status, s => Config(s)?.DnssecLimits, s => Sources(s)?.DnssecLimits, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.DnssecLimits, status, s => Config(s)?.DnssecLimits, s => Sources(s)?.DnssecLimits, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.TrustAnchor, status, null, null, Items(ec => ec?.TrustAnchorValues, src => src?.TrustAnchorValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.TrustAnchor, status, null, null, Items(ec => ec?.TrustAnchorValues, src => src?.TrustAnchorValues));
|
||||||
@@ -196,8 +200,6 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.CacheSize, status, s => Config(s)?.CacheSize, s => Sources(s)?.CacheSize, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.CacheSize, status, s => Config(s)?.CacheSize, s => Sources(s)?.CacheSize, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.LocalTtl, status, s => Config(s)?.LocalTtl, s => Sources(s)?.LocalTtl, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.LocalTtl, status, s => Config(s)?.LocalTtl, s => Sources(s)?.LocalTtl, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoNegcache, status, s => Config(s)?.NoNegcache, s => Sources(s)?.NoNegcache, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoNegcache, status, s => Config(s)?.NoNegcache, s => Sources(s)?.NoNegcache, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Dumpfile, status, s => Config(s)?.DumpfilePath, s => Sources(s)?.DumpfilePath, null);
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Dumpmask, status, s => Config(s)?.Dumpmask, s => Sources(s)?.Dumpmask, null);
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.UseStaleCache, status, s => Config(s)?.UseStaleCache, s => Sources(s)?.UseStaleCache, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.UseStaleCache, status, s => Config(s)?.UseStaleCache, s => Sources(s)?.UseStaleCache, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.AddMac, status, s => Config(s)?.AddMac, s => Sources(s)?.AddMac, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.AddMac, status, s => Config(s)?.AddMac, s => Sources(s)?.AddMac, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.StripMac, status, s => Config(s)?.StripMac, s => Sources(s)?.StripMac, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.StripMac, status, s => Config(s)?.StripMac, s => Sources(s)?.StripMac, null);
|
||||||
@@ -220,16 +222,14 @@ public sealed class EffectiveConfigFieldBuilder : IEffectiveConfigFieldBuilder
|
|||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ListenAddress, status, null, null, Items(ec => ec?.ListenAddresses, src => src?.ListenAddresses));
|
list.AddDescriptor(registry, DnsmasqConfKeys.ListenAddress, status, null, null, Items(ec => ec?.ListenAddresses, src => src?.ListenAddresses));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.ExceptInterface, status, null, null, Items(ec => ec?.ExceptInterfaces, src => src?.ExceptInterfaces));
|
list.AddDescriptor(registry, DnsmasqConfKeys.ExceptInterface, status, null, null, Items(ec => ec?.ExceptInterfaces, src => src?.ExceptInterfaces));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.AuthServer, status, null, null, Items(ec => ec?.AuthServerValues, src => src?.AuthServerValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.AuthServer, status, null, null, Items(ec => ec?.AuthServerValues, src => src?.AuthServerValues));
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoDhcpInterface, status, null, null, Items(ec => ec?.NoDhcpInterfaceValues, src => src?.NoDhcpInterfaceValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.Dumpfile, status, s => Config(s)?.DumpfilePath, s => Sources(s)?.DumpfilePath, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoDhcpv4Interface, status, null, null, Items(ec => ec?.NoDhcpv4InterfaceValues, src => src?.NoDhcpv4InterfaceValues));
|
list.AddDescriptor(registry, DnsmasqConfKeys.Dumpmask, status, s => Config(s)?.Dumpmask, s => Sources(s)?.Dumpmask, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoDhcpv6Interface, status, null, null, Items(ec => ec?.NoDhcpv6InterfaceValues, src => src?.NoDhcpv6InterfaceValues));
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.PidFile, status, s => Config(s)?.PidFilePath, s => Sources(s)?.PidFilePath, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.PidFile, status, s => Config(s)?.PidFilePath, s => Sources(s)?.PidFilePath, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.User, status, s => Config(s)?.User, s => Sources(s)?.User, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.User, status, s => Config(s)?.User, s => Sources(s)?.User, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.Group, status, s => Config(s)?.Group, s => Sources(s)?.Group, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.Group, status, s => Config(s)?.Group, s => Sources(s)?.Group, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.LogFacility, status, s => Config(s)?.LogFacility, s => Sources(s)?.LogFacility, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.LogFacility, status, s => Config(s)?.LogFacility, s => Sources(s)?.LogFacility, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.EnableDbus, status, s => Config(s)?.EnableDbus, s => Sources(s)?.EnableDbus, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.EnableDbus, status, s => Config(s)?.EnableDbus, s => Sources(s)?.EnableDbus, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.EnableUbus, status, s => Config(s)?.EnableUbus, s => Sources(s)?.EnableUbus, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.EnableUbus, status, s => Config(s)?.EnableUbus, s => Sources(s)?.EnableUbus, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.EnableRa, status, s => Config(s)?.EnableRa, s => Sources(s)?.EnableRa, null);
|
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.LogDhcp, status, s => Config(s)?.LogDhcp, s => Sources(s)?.LogDhcp, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.LogDhcp, status, s => Config(s)?.LogDhcp, s => Sources(s)?.LogDhcp, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.KeepInForeground, status, s => Config(s)?.KeepInForeground, s => Sources(s)?.KeepInForeground, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.KeepInForeground, status, s => Config(s)?.KeepInForeground, s => Sources(s)?.KeepInForeground, null);
|
||||||
list.AddDescriptor(registry, DnsmasqConfKeys.NoDaemon, status, s => Config(s)?.NoDaemon, s => Sources(s)?.NoDaemon, null);
|
list.AddDescriptor(registry, DnsmasqConfKeys.NoDaemon, status, s => Config(s)?.NoDaemon, s => Sources(s)?.NoDaemon, null);
|
||||||
|
|||||||
+9
-9
@@ -29,6 +29,8 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.NoHosts,
|
DnsmasqConfKeys.NoHosts,
|
||||||
DnsmasqConfKeys.AddnHosts,
|
DnsmasqConfKeys.AddnHosts,
|
||||||
DnsmasqConfKeys.Hostsdir,
|
DnsmasqConfKeys.Hostsdir,
|
||||||
|
DnsmasqConfKeys.ExpandHosts,
|
||||||
|
DnsmasqConfKeys.Domain,
|
||||||
]),
|
]),
|
||||||
new SectionDef(SectionResolver, "Resolver / DNS", [
|
new SectionDef(SectionResolver, "Resolver / DNS", [
|
||||||
DnsmasqConfKeys.Server,
|
DnsmasqConfKeys.Server,
|
||||||
@@ -52,7 +54,6 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.StopDnsRebind,
|
DnsmasqConfKeys.StopDnsRebind,
|
||||||
DnsmasqConfKeys.RebindLocalhostOk,
|
DnsmasqConfKeys.RebindLocalhostOk,
|
||||||
DnsmasqConfKeys.ClearOnReload,
|
DnsmasqConfKeys.ClearOnReload,
|
||||||
DnsmasqConfKeys.ExpandHosts,
|
|
||||||
DnsmasqConfKeys.BogusPriv,
|
DnsmasqConfKeys.BogusPriv,
|
||||||
DnsmasqConfKeys.RebindDomainOk,
|
DnsmasqConfKeys.RebindDomainOk,
|
||||||
DnsmasqConfKeys.BogusNxdomain,
|
DnsmasqConfKeys.BogusNxdomain,
|
||||||
@@ -70,10 +71,10 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.NoRoundRobin,
|
DnsmasqConfKeys.NoRoundRobin,
|
||||||
DnsmasqConfKeys.DnsForwardMax,
|
DnsmasqConfKeys.DnsForwardMax,
|
||||||
DnsmasqConfKeys.ConnmarkAllowlist,
|
DnsmasqConfKeys.ConnmarkAllowlist,
|
||||||
|
DnsmasqConfKeys.AddCpeId,
|
||||||
DnsmasqConfKeys.Do0x20Encode,
|
DnsmasqConfKeys.Do0x20Encode,
|
||||||
]),
|
]),
|
||||||
new SectionDef(SectionDnsRecords, "DNS records", [
|
new SectionDef(SectionDnsRecords, "DNS records", [
|
||||||
DnsmasqConfKeys.Domain,
|
|
||||||
DnsmasqConfKeys.Cname,
|
DnsmasqConfKeys.Cname,
|
||||||
DnsmasqConfKeys.MxHost,
|
DnsmasqConfKeys.MxHost,
|
||||||
DnsmasqConfKeys.Srv,
|
DnsmasqConfKeys.Srv,
|
||||||
@@ -95,6 +96,10 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.Selfmx,
|
DnsmasqConfKeys.Selfmx,
|
||||||
]),
|
]),
|
||||||
new SectionDef(SectionDhcp, "DHCP", [
|
new SectionDef(SectionDhcp, "DHCP", [
|
||||||
|
DnsmasqConfKeys.NoDhcpInterface,
|
||||||
|
DnsmasqConfKeys.NoDhcpv4Interface,
|
||||||
|
DnsmasqConfKeys.NoDhcpv6Interface,
|
||||||
|
DnsmasqConfKeys.EnableRa,
|
||||||
DnsmasqConfKeys.DhcpAuthoritative,
|
DnsmasqConfKeys.DhcpAuthoritative,
|
||||||
DnsmasqConfKeys.DhcpRapidCommit,
|
DnsmasqConfKeys.DhcpRapidCommit,
|
||||||
DnsmasqConfKeys.LeasefileRo,
|
DnsmasqConfKeys.LeasefileRo,
|
||||||
@@ -161,7 +166,6 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.DnssecNoTimecheck,
|
DnsmasqConfKeys.DnssecNoTimecheck,
|
||||||
DnsmasqConfKeys.DnssecDebug,
|
DnsmasqConfKeys.DnssecDebug,
|
||||||
DnsmasqConfKeys.ProxyDnssec,
|
DnsmasqConfKeys.ProxyDnssec,
|
||||||
DnsmasqConfKeys.AddCpeId,
|
|
||||||
DnsmasqConfKeys.DnssecTimestamp,
|
DnsmasqConfKeys.DnssecTimestamp,
|
||||||
DnsmasqConfKeys.DnssecLimits,
|
DnsmasqConfKeys.DnssecLimits,
|
||||||
DnsmasqConfKeys.TrustAnchor,
|
DnsmasqConfKeys.TrustAnchor,
|
||||||
@@ -175,8 +179,6 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.MaxTtl,
|
DnsmasqConfKeys.MaxTtl,
|
||||||
DnsmasqConfKeys.MaxCacheTtl,
|
DnsmasqConfKeys.MaxCacheTtl,
|
||||||
DnsmasqConfKeys.MinCacheTtl,
|
DnsmasqConfKeys.MinCacheTtl,
|
||||||
DnsmasqConfKeys.Dumpfile,
|
|
||||||
DnsmasqConfKeys.Dumpmask,
|
|
||||||
DnsmasqConfKeys.UseStaleCache,
|
DnsmasqConfKeys.UseStaleCache,
|
||||||
DnsmasqConfKeys.AddMac,
|
DnsmasqConfKeys.AddMac,
|
||||||
DnsmasqConfKeys.StripMac,
|
DnsmasqConfKeys.StripMac,
|
||||||
@@ -195,16 +197,14 @@ public static class EffectiveConfigSections
|
|||||||
DnsmasqConfKeys.ListenAddress,
|
DnsmasqConfKeys.ListenAddress,
|
||||||
DnsmasqConfKeys.ExceptInterface,
|
DnsmasqConfKeys.ExceptInterface,
|
||||||
DnsmasqConfKeys.AuthServer,
|
DnsmasqConfKeys.AuthServer,
|
||||||
DnsmasqConfKeys.NoDhcpInterface,
|
DnsmasqConfKeys.Dumpfile,
|
||||||
DnsmasqConfKeys.NoDhcpv4Interface,
|
DnsmasqConfKeys.Dumpmask,
|
||||||
DnsmasqConfKeys.NoDhcpv6Interface,
|
|
||||||
DnsmasqConfKeys.PidFile,
|
DnsmasqConfKeys.PidFile,
|
||||||
DnsmasqConfKeys.User,
|
DnsmasqConfKeys.User,
|
||||||
DnsmasqConfKeys.Group,
|
DnsmasqConfKeys.Group,
|
||||||
DnsmasqConfKeys.LogFacility,
|
DnsmasqConfKeys.LogFacility,
|
||||||
DnsmasqConfKeys.EnableDbus,
|
DnsmasqConfKeys.EnableDbus,
|
||||||
DnsmasqConfKeys.EnableUbus,
|
DnsmasqConfKeys.EnableUbus,
|
||||||
DnsmasqConfKeys.EnableRa,
|
|
||||||
DnsmasqConfKeys.LogDhcp,
|
DnsmasqConfKeys.LogDhcp,
|
||||||
DnsmasqConfKeys.KeepInForeground,
|
DnsmasqConfKeys.KeepInForeground,
|
||||||
DnsmasqConfKeys.NoDaemon,
|
DnsmasqConfKeys.NoDaemon,
|
||||||
|
|||||||
+1
-2
@@ -38,9 +38,8 @@ public static class EffectiveConfigViews
|
|||||||
DnsmasqConfKeys.NoHosts,
|
DnsmasqConfKeys.NoHosts,
|
||||||
DnsmasqConfKeys.AddnHosts,
|
DnsmasqConfKeys.AddnHosts,
|
||||||
DnsmasqConfKeys.Hostsdir,
|
DnsmasqConfKeys.Hostsdir,
|
||||||
]),
|
|
||||||
new(EffectiveConfigSections.SectionResolver, "Resolver / DNS", [
|
|
||||||
DnsmasqConfKeys.ExpandHosts,
|
DnsmasqConfKeys.ExpandHosts,
|
||||||
|
DnsmasqConfKeys.Domain,
|
||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
+11
-12
@@ -71,10 +71,9 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
|
|
||||||
private void RegisterFlagDisplays()
|
private void RegisterFlagDisplays()
|
||||||
{
|
{
|
||||||
RegisterFlags(EffectiveConfigSections.SectionHosts, DnsmasqConfKeys.NoHosts);
|
RegisterFlags(EffectiveConfigSections.SectionHosts, DnsmasqConfKeys.NoHosts, DnsmasqConfKeys.ExpandHosts);
|
||||||
RegisterFlags(
|
RegisterFlags(
|
||||||
EffectiveConfigSections.SectionResolver,
|
EffectiveConfigSections.SectionResolver,
|
||||||
DnsmasqConfKeys.ExpandHosts,
|
|
||||||
DnsmasqConfKeys.BogusPriv,
|
DnsmasqConfKeys.BogusPriv,
|
||||||
DnsmasqConfKeys.StrictOrder,
|
DnsmasqConfKeys.StrictOrder,
|
||||||
DnsmasqConfKeys.AllServers,
|
DnsmasqConfKeys.AllServers,
|
||||||
@@ -91,6 +90,7 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
DnsmasqConfKeys.NoRoundRobin);
|
DnsmasqConfKeys.NoRoundRobin);
|
||||||
RegisterFlags(
|
RegisterFlags(
|
||||||
EffectiveConfigSections.SectionDhcp,
|
EffectiveConfigSections.SectionDhcp,
|
||||||
|
DnsmasqConfKeys.EnableRa,
|
||||||
DnsmasqConfKeys.DhcpAuthoritative,
|
DnsmasqConfKeys.DhcpAuthoritative,
|
||||||
DnsmasqConfKeys.ReadEthers,
|
DnsmasqConfKeys.ReadEthers,
|
||||||
DnsmasqConfKeys.DhcpRapidCommit,
|
DnsmasqConfKeys.DhcpRapidCommit,
|
||||||
@@ -125,7 +125,6 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
DnsmasqConfKeys.BindInterfaces,
|
DnsmasqConfKeys.BindInterfaces,
|
||||||
DnsmasqConfKeys.BindDynamic,
|
DnsmasqConfKeys.BindDynamic,
|
||||||
DnsmasqConfKeys.LogDebug,
|
DnsmasqConfKeys.LogDebug,
|
||||||
DnsmasqConfKeys.EnableRa,
|
|
||||||
DnsmasqConfKeys.LogDhcp,
|
DnsmasqConfKeys.LogDhcp,
|
||||||
DnsmasqConfKeys.KeepInForeground,
|
DnsmasqConfKeys.KeepInForeground,
|
||||||
DnsmasqConfKeys.NoDaemon,
|
DnsmasqConfKeys.NoDaemon,
|
||||||
@@ -177,11 +176,9 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
RegisterSemanticSingles(
|
RegisterSemanticSingles(
|
||||||
EffectiveConfigSections.SectionDnssec,
|
EffectiveConfigSections.SectionDnssec,
|
||||||
DnsmasqConfKeys.DnssecTimestamp);
|
DnsmasqConfKeys.DnssecTimestamp);
|
||||||
RegisterSemanticSingles(
|
|
||||||
EffectiveConfigSections.SectionCache,
|
|
||||||
DnsmasqConfKeys.Dumpfile);
|
|
||||||
RegisterSemanticSingles(
|
RegisterSemanticSingles(
|
||||||
EffectiveConfigSections.SectionProcess,
|
EffectiveConfigSections.SectionProcess,
|
||||||
|
DnsmasqConfKeys.Dumpfile,
|
||||||
DnsmasqConfKeys.PidFile);
|
DnsmasqConfKeys.PidFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +190,10 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
behavior: new DistinctMultiValueEditBehavior());
|
behavior: new DistinctMultiValueEditBehavior());
|
||||||
RegisterSemanticMultiDescriptor(EffectiveConfigSections.SectionProcess, DnsmasqConfKeys.ListenAddress);
|
RegisterSemanticMultiDescriptor(EffectiveConfigSections.SectionProcess, DnsmasqConfKeys.ListenAddress);
|
||||||
|
|
||||||
RegisterSemanticMultis(EffectiveConfigSections.SectionHosts, DnsmasqConfKeys.AddnHosts);
|
RegisterSemanticMultis(
|
||||||
|
EffectiveConfigSections.SectionHosts,
|
||||||
|
DnsmasqConfKeys.AddnHosts,
|
||||||
|
DnsmasqConfKeys.Domain);
|
||||||
RegisterSemanticMultis(
|
RegisterSemanticMultis(
|
||||||
EffectiveConfigSections.SectionResolver,
|
EffectiveConfigSections.SectionResolver,
|
||||||
DnsmasqConfKeys.Local,
|
DnsmasqConfKeys.Local,
|
||||||
@@ -209,6 +209,9 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
DnsmasqConfKeys.ConnmarkAllowlist);
|
DnsmasqConfKeys.ConnmarkAllowlist);
|
||||||
RegisterSemanticMultis(
|
RegisterSemanticMultis(
|
||||||
EffectiveConfigSections.SectionDhcp,
|
EffectiveConfigSections.SectionDhcp,
|
||||||
|
DnsmasqConfKeys.NoDhcpInterface,
|
||||||
|
DnsmasqConfKeys.NoDhcpv4Interface,
|
||||||
|
DnsmasqConfKeys.NoDhcpv6Interface,
|
||||||
DnsmasqConfKeys.DhcpRange,
|
DnsmasqConfKeys.DhcpRange,
|
||||||
DnsmasqConfKeys.DhcpHost,
|
DnsmasqConfKeys.DhcpHost,
|
||||||
DnsmasqConfKeys.DhcpOption,
|
DnsmasqConfKeys.DhcpOption,
|
||||||
@@ -239,7 +242,6 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
DnsmasqConfKeys.FilterRr);
|
DnsmasqConfKeys.FilterRr);
|
||||||
RegisterSemanticMultis(
|
RegisterSemanticMultis(
|
||||||
EffectiveConfigSections.SectionDnsRecords,
|
EffectiveConfigSections.SectionDnsRecords,
|
||||||
DnsmasqConfKeys.Domain,
|
|
||||||
DnsmasqConfKeys.Cname,
|
DnsmasqConfKeys.Cname,
|
||||||
DnsmasqConfKeys.MxHost,
|
DnsmasqConfKeys.MxHost,
|
||||||
DnsmasqConfKeys.PtrRecord,
|
DnsmasqConfKeys.PtrRecord,
|
||||||
@@ -273,10 +275,7 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm
|
|||||||
EffectiveConfigSections.SectionProcess,
|
EffectiveConfigSections.SectionProcess,
|
||||||
DnsmasqConfKeys.Interface,
|
DnsmasqConfKeys.Interface,
|
||||||
DnsmasqConfKeys.ExceptInterface,
|
DnsmasqConfKeys.ExceptInterface,
|
||||||
DnsmasqConfKeys.AuthServer,
|
DnsmasqConfKeys.AuthServer);
|
||||||
DnsmasqConfKeys.NoDhcpInterface,
|
|
||||||
DnsmasqConfKeys.NoDhcpv4Interface,
|
|
||||||
DnsmasqConfKeys.NoDhcpv6Interface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterComponents(string sectionId, Type componentType, params string[] optionNames)
|
private void RegisterComponents(string sectionId, Type componentType, params string[] optionNames)
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ public sealed record HostsPageState(
|
|||||||
: "Hosts editing is unavailable: managed hosts path is not configured. Set Dnsmasq:MainConfigPath (and optionally Dnsmasq:ManagedHostsFileName) so the app can create and edit the managed hosts file.",
|
: "Hosts editing is unavailable: managed hosts path is not configured. Set Dnsmasq:MainConfigPath (and optionally Dnsmasq:ManagedHostsFileName) so the app can create and edit the managed hosts file.",
|
||||||
SystemHostsActive: systemHostsActive,
|
SystemHostsActive: systemHostsActive,
|
||||||
SystemHostsInactiveReason: noHosts
|
SystemHostsInactiveReason: noHosts
|
||||||
? "System hosts is ignored because no-hosts is enabled in dnsmasq config."
|
? "Dnsmasq is ignoring system hosts (no-hosts is enabled), so system hosts rows are hidden from this table."
|
||||||
: string.IsNullOrEmpty(status.SystemHostsPath)
|
: string.IsNullOrEmpty(status.SystemHostsPath)
|
||||||
? "System hosts path is not configured."
|
? "System hosts path is not configured; system hosts rows are hidden from this table."
|
||||||
: !status.SystemHostsPathExists
|
: !status.SystemHostsPathExists
|
||||||
? $"System hosts file not found: {status.SystemHostsPath}"
|
? $"System hosts file not found ({status.SystemHostsPath}); those rows are hidden from this table."
|
||||||
: null,
|
: null,
|
||||||
ExpandHostsEnabled: expandHosts,
|
ExpandHostsEnabled: expandHosts,
|
||||||
ExpansionDomain: expandHosts ? domain : null);
|
ExpansionDomain: expandHosts ? domain : null);
|
||||||
|
|||||||
@@ -158,3 +158,15 @@ export function disposeTableScrollCue() {
|
|||||||
if (right) right.remove();
|
if (right) right.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the active element is not inside `container` (e.g. focus left a table row).
|
||||||
|
* Use after a short delay following focusout so document.activeElement has updated.
|
||||||
|
* @param {HTMLElement | null} container
|
||||||
|
*/
|
||||||
|
export function isFocusOutsideElement(container) {
|
||||||
|
if (!container) return true;
|
||||||
|
const active = document.activeElement;
|
||||||
|
if (!active) return true;
|
||||||
|
return !container.contains(active);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user