fix(adminui): Monaco text syncs on demand, diagnostics are sequenced, Problems list (D1)
R04:P1 - the editor no longer ships its full text JS->.NET on every keystroke. It reports at blur, and ScriptEdit / the VirtualTag modal read the authoritative value with MonacoEditor.GetValueAsync at Save (validation runs after the pull). The Blazor hub's MaximumReceiveMessageSize is raised from 32 KB to 1 MB. The JS refuses a value that would not fit instead of sending an oversize frame, and Save surfaces that refusal rather than persisting stale source. R04:P9 - diagnostics carry a generation counter and an AbortController. Every edit aborts the in-flight request, and only the response for the current text is applied. R04:S2 - the always-empty inlay-hints provider, endpoint, service method and contracts are removed. R04:S3 - MarkersChanged is typed (DiagnosticMarker) and feeds a new ScriptProblemsList. Clicking a problem calls RevealLineAsync. Markers cross to .NET only when a list subscribes. Refs #745 Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.ScriptAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// Presentation rules for the script editor's Problems list — the markers Monaco reports through
|
||||
/// <c>MonacoEditor.MarkersChanged</c> (the same <see cref="DiagnosticMarker"/> shape the diagnostics endpoint
|
||||
/// returns), rendered by <c>ScriptProblemsList</c>.
|
||||
/// </summary>
|
||||
public static class ScriptProblems
|
||||
{
|
||||
/// <summary>Monaco's error severity.</summary>
|
||||
public const int Error = 8;
|
||||
|
||||
/// <summary>Monaco's warning severity.</summary>
|
||||
public const int Warning = 4;
|
||||
|
||||
/// <summary>Errors first, then warnings, then the rest; within a severity, by position.</summary>
|
||||
/// <param name="markers">The reported markers (null treated as none).</param>
|
||||
/// <returns>The markers in display order.</returns>
|
||||
public static IReadOnlyList<DiagnosticMarker> Order(IEnumerable<DiagnosticMarker>? markers)
|
||||
=> (markers ?? Array.Empty<DiagnosticMarker>())
|
||||
.OrderByDescending(m => m.Severity)
|
||||
.ThenBy(m => m.StartLineNumber)
|
||||
.ThenBy(m => m.StartColumn)
|
||||
.ToList();
|
||||
|
||||
/// <summary>The label for a Monaco severity value.</summary>
|
||||
/// <param name="severity">8 = error, 4 = warning, 2 = info, otherwise hint.</param>
|
||||
/// <returns>The display label.</returns>
|
||||
public static string SeverityLabel(int severity) => severity switch
|
||||
{
|
||||
Error => "Error",
|
||||
Warning => "Warning",
|
||||
2 => "Info",
|
||||
_ => "Hint",
|
||||
};
|
||||
|
||||
/// <summary>A one-line count, e.g. <c>"2 errors, 1 warning"</c>.</summary>
|
||||
/// <param name="markers">The reported markers.</param>
|
||||
/// <returns>The summary, or <c>"No problems"</c>.</returns>
|
||||
public static string Summary(IReadOnlyCollection<DiagnosticMarker> markers)
|
||||
{
|
||||
if (markers.Count == 0) return "No problems";
|
||||
var errors = markers.Count(m => m.Severity == Error);
|
||||
var warnings = markers.Count(m => m.Severity == Warning);
|
||||
var other = markers.Count - errors - warnings;
|
||||
var parts = new List<string>(3);
|
||||
if (errors > 0) parts.Add(Plural(errors, "error"));
|
||||
if (warnings > 0) parts.Add(Plural(warnings, "warning"));
|
||||
if (other > 0) parts.Add($"{other} other");
|
||||
return string.Join(", ", parts);
|
||||
}
|
||||
|
||||
private static string Plural(int n, string noun) => n == 1 ? $"1 {noun}" : $"{n} {noun}s";
|
||||
}
|
||||
Reference in New Issue
Block a user