Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 62 additions & 4 deletions src/NetworkOptimizer.Web/Components/Pages/PerformanceTweaks.razor
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<div class="page-header">
<h1>Performance Tweaks</h1>
<p class="page-description">Deploy and manage hardware-level performance optimizations for your UCG-Fiber, UXG-Fiber, or UCG-Max gateway. These tweaks address eMMC write pressure, thermal management, and SFP+ link speed - all persistent across reboots via udm-boot. We have more tweaks in testing that we'll be bringing over soon, and we're always looking for ideas.</p>
<p class="page-description">Deploy and manage performance optimizations for your UCG-Fiber, UXG-Fiber, or UCG-Max gateway. These tweaks address eMMC write pressure, thermal management, and SFP+ link speed - all persistent across reboots via udm-boot. We have more tweaks in testing that we'll be bringing over soon, and we're always looking for ideas.</p>
</div>

@if (!ConnectionService.IsConnected && ConnectionService.IsInitialized && !string.IsNullOrEmpty(ConnectionService.LastError))
Expand Down Expand Up @@ -352,7 +352,7 @@
</button>
@if (tweakStatus?.IsManuallyDeployed != true)
{
<button class="btn btn-sm btn-danger" @onclick="() => RemoveTweak(def.Id)" disabled="@(_removingTweakId == def.Id || _deployingTweakId == def.Id)">
<button class="btn btn-sm btn-danger" @onclick="() => ShowRemoveConfirmation(def.Id)" disabled="@(_removingTweakId == def.Id || _deployingTweakId == def.Id)">
@if (_removingTweakId == def.Id)
{
<span class="spinner spinner-sm"></span>
Expand Down Expand Up @@ -399,8 +399,16 @@
<button class="btn btn-sm btn-secondary" @onclick="RefreshStatus" disabled="@_isLoading">
Check Status
</button>
<button class="btn btn-sm btn-danger" @onclick="() => RemoveTweak(def.Id)" disabled="@(_deployingTweakId == def.Id)">
Remove
<button class="btn btn-sm btn-danger" @onclick="() => ShowRemoveConfirmation(def.Id)" disabled="@(_removingTweakId == def.Id || _deployingTweakId == def.Id)">
@if (_removingTweakId == def.Id)
{
<span class="spinner spinner-sm"></span>
<span>Removing...</span>
}
else
{
<span>Remove</span>
}
</button>
}
</div>
Expand Down Expand Up @@ -462,6 +470,34 @@
</div>
}

<!-- Remove Confirmation Modal -->
@if (_showRemoveConfirm && _pendingRemoveTweakId != null)
{
var removeDef = _tweakDefs.FirstOrDefault(d => d.Id == _pendingRemoveTweakId);
<div class="pt-modal-overlay" @onclick="CancelRemove">
<div class="pt-modal" @onclick:stopPropagation="true">
<div class="pt-modal-header">
<h3>Confirm Removal</h3>
</div>
<div class="pt-modal-body">
<p>Are you sure you want to remove <strong>@(removeDef?.Title ?? _pendingRemoveTweakId)</strong>? This will delete the boot script and reverse the tweak's changes on your gateway.</p>
@if (_pendingRemoveTweakId == "mongodb-ssd")
{
<div class="alert alert-warning" style="margin-top: 0.75rem;">
<strong>Note:</strong> Removal will briefly stop UniFi Network while migrating MongoDB data back from SSD to eMMC, then restart it.
</div>
}
</div>
<div class="pt-modal-footer">
<button class="btn btn-secondary btn-sm" @onclick="CancelRemove">Cancel</button>
<button class="btn btn-danger btn-sm" @onclick="ConfirmRemove">
Confirm Remove
</button>
</div>
</div>
</div>
}

<style>
.pt-container {
display: flex;
Expand Down Expand Up @@ -755,6 +791,8 @@
private bool _confirmBackupDownloaded;
private bool _confirmWarranty;
private bool _confirmRisk;
private bool _showRemoveConfirm;
private string? _pendingRemoveTweakId;
private bool _allConfirmed => _confirmBackup && _confirmBackupDownloaded && _confirmWarranty && _confirmRisk;
private bool _canDeploy => _status?.UdmBootInstalled == true && _status?.FirmwareSupported == true;
private List<string> _deploySteps = new();
Expand Down Expand Up @@ -873,6 +911,26 @@
_pendingDeployTweakId = null;
}

private void ShowRemoveConfirmation(string tweakId)
{
_pendingRemoveTweakId = tweakId;
_showRemoveConfirm = true;
}

private async Task ConfirmRemove()
{
_showRemoveConfirm = false;
if (_pendingRemoveTweakId != null)
await RemoveTweak(_pendingRemoveTweakId);
_pendingRemoveTweakId = null;
}

private void CancelRemove()
{
_showRemoveConfirm = false;
_pendingRemoveTweakId = null;
}

private async Task DeployTweak(string tweakId)
{
_deployingTweakId = tweakId;
Expand Down
6 changes: 3 additions & 3 deletions src/NetworkOptimizer.Web/Services/UwnSpeedTestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,16 +276,16 @@ public UwnSpeedTestService(
// configured speed, assume multiple WANs are bonded. The 25% margin
// accounts for ISP overprovisioning and burst headroom.
var maxSingleDown = wanNetworks!.Max(n => n.WanDownloadMbps ?? 0);
var maxSingleUp = wanNetworks.Max(n => n.WanUploadMbps ?? 0);
var maxSingleUp = wanNetworks!.Max(n => n.WanUploadMbps ?? 0);
const double fudgeFactor = 1.25;

if (downloadMbps > maxSingleDown * fudgeFactor || uploadMbps > maxSingleUp * fudgeFactor)
{
var groups = wanNetworks
var groups = wanNetworks!
.Select(n => n.WanNetworkgroup ?? "WAN")
.Distinct().OrderBy(g => g);
result.WanNetworkGroup = string.Join("+", groups);
var names = wanNetworks
var names = wanNetworks!
.Select(n => !string.IsNullOrEmpty(n.Name) ? n.Name : n.WanNetworkgroup ?? "WAN")
.Distinct().OrderBy(n => n);
result.WanName = string.Join(" + ", names);
Expand Down
5 changes: 5 additions & 0 deletions src/NetworkOptimizer.Web/wwwroot/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -4009,6 +4009,11 @@ select.form-control {
animation: spin 0.8s linear infinite;
}

.btn .spinner-sm {
border-color: rgba(255, 255, 255, 0.4);
border-top-color: white;
}

.status-offline {
color: var(--danger-color);
}
Expand Down
Loading