Merged the two validation systems of the visual briefing editor into one

This commit is contained in:
Thorsten Sommer 2026-08-02 16:21:24 +02:00
parent dc71c2ba0b
commit c238a80764
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
5 changed files with 62 additions and 37 deletions

View File

@ -79,7 +79,6 @@
else
{
<MudForm @ref="@(this.visualBriefingForm)"
@bind-IsValid="@(this.formIsValid)"
@bind-Errors="@(this.formIssues)">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center" Wrap="Wrap.Wrap" Class="mb-3">
<MudText Typo="Typo.h3">@this.editor.Name</MudText>

View File

@ -23,20 +23,23 @@ public partial class VisualBriefingAssistant
private bool CannotRecompile => this.IsCurrentBusy || this.selectedBriefing is null || this.selectedRevisionId == Guid.Empty || !this.SelectedVersionSupportsEdits;
/// <summary>
/// Defines <c>CannotGenerate</c> for the visual briefing feature.
/// Gets whether one edit mode is currently blocked.
/// </summary>
/// <remarks>
/// A mode is blocked by the very issues listed below the buttons, minus the ones that do not apply
/// to it. Changing only the design rebuilds the presentation from the validated content of a stored
/// version, so it neither needs source material nor cares whether a source file moved away in the
/// meantime. The two modes that edit a stored version instead require that version to still carry
/// its semantic artifacts.
/// </remarks>
/// <param name="mode">The edit mode the user asked for.</param>
/// <returns><c>true</c> when the mode must stay disabled.</returns>
private bool CannotGenerate(VisualBriefingEditMode mode) =>
this.IsCurrentBusy ||
this.editor.Provider == ProviderSettings.NONE ||
string.IsNullOrWhiteSpace(this.editor.Name) ||
this.editor.TargetLanguage is CommonLanguages.OTHER && string.IsNullOrWhiteSpace(this.editor.CustomTargetLanguage) ||
this.editor.ProtectionLevel is VisualBriefingProtectionLevel.OTHER && string.IsNullOrWhiteSpace(this.editor.CustomProtectionLevel) ||
mode is not VisualBriefingEditMode.CHANGE_DESIGN && !this.HasSourceMaterial ||
mode is VisualBriefingEditMode.CHANGE_DESIGN or VisualBriefingEditMode.UPDATE_CONTENT &&
!this.SelectedVersionSupportsEdits ||
mode is not VisualBriefingEditMode.CHANGE_DESIGN &&
this.selectedBriefing?.Sources.Any(source =>
source.Status is VisualBriefingSourceStatus.UNREACHABLE or VisualBriefingSourceStatus.TRANSCRIPT_OUTDATED) == true;
this.selectedBriefing is null ||
this.FieldIssues.Count > 0 ||
mode is not VisualBriefingEditMode.CHANGE_DESIGN && this.SourceIssues.Count > 0 ||
mode is VisualBriefingEditMode.CHANGE_DESIGN or VisualBriefingEditMode.UPDATE_CONTENT && !this.SelectedVersionSupportsEdits;
/// <summary>
/// Runs one long-running briefing operation inside the shared session, progress, and error envelope.

View File

@ -269,7 +269,6 @@ public partial class VisualBriefingAssistant
this.lastPersistedState = this.BuildPersistenceFingerprint();
this.formIssues = [];
this.formIsValid = false;
this.formValidationPending = true;
}
@ -304,7 +303,6 @@ public partial class VisualBriefingAssistant
this.reusableContentBuildId = null;
this.lastPersistedState = string.Empty;
this.formIssues = [];
this.formIsValid = false;
this.formValidationPending = false;
this.visualBriefingForm?.ResetValidation();
}

View File

@ -16,42 +16,70 @@ public partial class VisualBriefingAssistant
private bool HasSourceMaterial => this.selectedBriefing?.Sources.Any(source => source.Kind is VisualBriefingSourceKind.SOURCE_MATERIAL) == true;
/// <summary>Gets all current field, source, and revision issues shown below the actions.</summary>
/// <remarks>
/// This is the complete list for the user. The generate buttons disable themselves from the same
/// two building blocks, so a listed issue and a blocked button can no longer contradict each other.
/// Only the MudBlazor field messages stay out of that gate: they arrive one validation pass late,
/// which would make the buttons flicker, and the validators behind them are evaluated directly by
/// FieldIssues anyway.
/// </remarks>
private IReadOnlyList<string> ValidationIssues
{
get
{
List<string> issues = [.. this.formIssues];
List<string> issues = [.. this.formIssues, .. this.FieldIssues, .. this.SourceIssues];
if (this.selectedBriefing is { Versions.Count: > 0 } && !this.SelectedVersionSupportsEdits)
issues.Add(T("This version has no compatible semantic artifacts. Rebuild the briefing instead."));
return [.. issues.Where(issue => !string.IsNullOrWhiteSpace(issue)).Distinct(StringComparer.Ordinal)];
}
}
/// <summary>Gets the field issues that block generation regardless of the edit mode.</summary>
private IReadOnlyList<string> FieldIssues
{
get
{
List<string> issues = [];
AddIssue(issues, this.ValidateProjectName(this.editor.Name));
AddIssue(issues, this.ValidateProvider(this.editor.Provider));
AddIssue(issues, this.ValidateCustomTargetLanguage(this.editor.CustomTargetLanguage));
AddIssue(issues, this.ValidateCustomProtectionLevel(this.editor.CustomProtectionLevel));
if (this.selectedBriefing is not null)
return issues;
}
}
/// <summary>Gets the issues with the stored sources, which block only the modes that read them.</summary>
private IReadOnlyList<string> SourceIssues
{
get
{
if (this.selectedBriefing is null)
return [];
List<string> issues = [];
if (!this.HasSourceMaterial)
issues.Add(T("Please add at least one source material file."));
foreach (var source in this.selectedBriefing.Sources)
{
if (!this.HasSourceMaterial)
issues.Add(T("Please add at least one source material file."));
foreach (var source in this.selectedBriefing.Sources)
var fileName = Path.GetFileName(source.Path);
switch (source.Status)
{
var fileName = Path.GetFileName(source.Path);
switch (source.Status)
{
case VisualBriefingSourceStatus.UNREACHABLE:
issues.Add(string.Format(T("The source '{0}' is no longer reachable. Restore or relink it."), fileName));
break;
case VisualBriefingSourceStatus.UNREACHABLE:
issues.Add(string.Format(T("The source '{0}' is no longer reachable. Restore or relink it."), fileName));
break;
case VisualBriefingSourceStatus.TRANSCRIPT_OUTDATED:
issues.Add(string.Format(T("The transcript for '{0}' is missing or outdated. Transcribe the media source again."), fileName));
break;
}
case VisualBriefingSourceStatus.TRANSCRIPT_OUTDATED:
issues.Add(string.Format(T("The transcript for '{0}' is missing or outdated. Transcribe the media source again."), fileName));
break;
}
if (this.selectedBriefing.Versions.Count > 0 && !this.SelectedVersionSupportsEdits)
issues.Add(T("This version has no compatible semantic artifacts. Rebuild the briefing instead."));
}
return [.. issues.Where(issue => !string.IsNullOrWhiteSpace(issue)).Distinct(StringComparer.Ordinal)];
return issues;
}
}

View File

@ -123,9 +123,6 @@ public partial class VisualBriefingAssistant : MSGComponentBase
/// <summary>Owns MudBlazor validation for the selected briefing editor.</summary>
private MudForm? visualBriefingForm;
/// <summary>Stores whether all MudBlazor fields in the editor are currently valid.</summary>
private bool formIsValid;
/// <summary>Stores the current MudBlazor validation messages.</summary>
private string[] formIssues = [];