fix(transport-ui): reset connection choices on site change + clear state on back (M8 E2 review)

Fix 1: OnSiteChoiceChangedAsync now resets _connectionChoices for every
RequiredConnectionMapping under the changed source site after loading the new
target's connections. Choices are re-seeded to the same-named connection on
the new target if present, or CreateNewValue otherwise — preventing BuildNameMap
from emitting MapToExisting for a connection absent from the newly-chosen target.

Fix 2: BackToUpload now calls ResetSessionState() before resetting _step so
_session, _preview, _resolutions, _siteChoices, _connectionChoices,
_targetSites, and _targetConnections are all cleared when the operator backs
out to re-upload, making it safe to start a new import flow from a clean slate.

Tests 12 + 13 added to TransportImportPageTests.
This commit is contained in:
Joseph Doherty
2026-06-18 07:39:19 -04:00
parent d45a7a5760
commit f881521cc9
2 changed files with 168 additions and 4 deletions
@@ -405,6 +405,11 @@ public partial class TransportImport : ComponentBase, IDisposable
private void BackToUpload()
{
// Reset all wizard + Map state so a subsequent re-upload starts from a
// clean slate and cannot observe stale session / preview / name-map data
// from the previous flow. ResetSessionState also clears _preview,
// _resolutions, _siteChoices, _connectionChoices, etc.
ResetSessionState();
_step = ImportWizardStep.Upload;
_errorMessage = null;
}
@@ -509,10 +514,14 @@ public partial class TransportImport : ComponentBase, IDisposable
}
/// <summary>
/// Handles a site-mapping dropdown change. Records the choice and, when a
/// concrete target site is chosen, eagerly loads + caches that site's
/// connections so the per-connection dropdowns underneath it can render
/// their option sets synchronously.
/// Handles a site-mapping dropdown change. Records the choice, eagerly loads +
/// caches the new target's connections, then resets the per-connection choices
/// for every <see cref="RequiredConnectionMapping"/> under this source site so
/// that stale selections from the previous target cannot survive into
/// <see cref="BuildNameMap"/>. Each connection is re-seeded: if the new target
/// has a same-named connection the choice defaults to that name (matching the
/// auto-match logic in <see cref="InitNameMappingStateAsync"/>); otherwise it
/// falls back to the <see cref="CreateNewValue"/> sentinel ("Create new").
/// </summary>
private async Task OnSiteChoiceChangedAsync(string sourceSiteIdentifier, string? value)
{
@@ -527,6 +536,26 @@ public partial class TransportImport : ComponentBase, IDisposable
await SiteRepo.GetDataConnectionsBySiteIdAsync(target.Id, CancellationToken.None);
}
}
// Reset connection choices for every RequiredConnectionMapping belonging
// to this source site. The previously-chosen connection name may not exist
// on the newly-chosen target site, and leaving it would cause BuildNameMap
// to emit a MapToExisting for a connection that does not exist there.
if (_preview is not null)
{
foreach (var rcm in _preview.RequiredConnectionMappings
.Where(m => m.SourceSiteIdentifier == sourceSiteIdentifier))
{
// Default to the new target's same-named connection when present;
// otherwise fall back to Create-new.
_connectionChoices[(sourceSiteIdentifier, rcm.SourceConnectionName)] =
(!string.IsNullOrEmpty(chosen)
&& _targetConnections.TryGetValue(chosen, out var conns)
&& conns.Any(c => c.Name == rcm.SourceConnectionName))
? rcm.SourceConnectionName
: CreateNewValue;
}
}
}
private void OnConnectionChoiceChanged(string sourceSiteIdentifier, string sourceConnectionName, string? value)