From c238a807649aae8b5c53757dc9096fa383d8be03 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 2 Aug 2026 16:21:24 +0200 Subject: [PATCH] Merged the two validation systems of the visual briefing editor into one --- .../VisualBriefingAssistant.razor | 1 - .../VisualBriefingAssistant.razor.Build.cs | 25 ++++--- .../VisualBriefingAssistant.razor.Projects.cs | 2 - ...isualBriefingAssistant.razor.Validation.cs | 68 +++++++++++++------ .../VisualBriefingAssistant.razor.cs | 3 - 5 files changed, 62 insertions(+), 37 deletions(-) diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor index f9d8ef01..05519060 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor @@ -79,7 +79,6 @@ else { @this.editor.Name diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs index d00f3701..f89bdd63 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Build.cs @@ -23,20 +23,23 @@ public partial class VisualBriefingAssistant private bool CannotRecompile => this.IsCurrentBusy || this.selectedBriefing is null || this.selectedRevisionId == Guid.Empty || !this.SelectedVersionSupportsEdits; /// - /// Defines CannotGenerate for the visual briefing feature. + /// Gets whether one edit mode is currently blocked. /// + /// + /// 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. + /// + /// The edit mode the user asked for. + /// true when the mode must stay disabled. 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; /// /// Runs one long-running briefing operation inside the shared session, progress, and error envelope. diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs index 376ae643..fb3f6432 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Projects.cs @@ -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(); } diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Validation.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Validation.cs index 195fc22c..aad36754 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Validation.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.Validation.cs @@ -16,42 +16,70 @@ public partial class VisualBriefingAssistant private bool HasSourceMaterial => this.selectedBriefing?.Sources.Any(source => source.Kind is VisualBriefingSourceKind.SOURCE_MATERIAL) == true; /// Gets all current field, source, and revision issues shown below the actions. + /// + /// 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. + /// private IReadOnlyList ValidationIssues { get { - List issues = [.. this.formIssues]; + List 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)]; + } + } + + /// Gets the field issues that block generation regardless of the edit mode. + private IReadOnlyList FieldIssues + { + get + { + List 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; + } + } + + /// Gets the issues with the stored sources, which block only the modes that read them. + private IReadOnlyList SourceIssues + { + get + { + if (this.selectedBriefing is null) + return []; + + List 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; } } diff --git a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs index a7113117..d626b4c1 100644 --- a/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs +++ b/app/MindWork AI Studio/Assistants/VisualBriefing/VisualBriefingAssistant.razor.cs @@ -123,9 +123,6 @@ public partial class VisualBriefingAssistant : MSGComponentBase /// Owns MudBlazor validation for the selected briefing editor. private MudForm? visualBriefingForm; - /// Stores whether all MudBlazor fields in the editor are currently valid. - private bool formIsValid; - /// Stores the current MudBlazor validation messages. private string[] formIssues = [];