feat(adminui): inline script-source editor in the virtual-tag modal

This commit is contained in:
Joseph Doherty
2026-06-09 15:17:25 -04:00
parent 088fc50ef2
commit fc7dc3b57d
4 changed files with 478 additions and 4 deletions
@@ -401,4 +401,36 @@ public interface IUnsTreeService
/// <param name="ct">A token to cancel the operation.</param>
/// <returns>Success, a concurrency failure, or a delete-failed failure.</returns>
Task<UnsMutationResult> DeleteVirtualTagAsync(string virtualTagId, byte[] rowVersion, CancellationToken ct = default);
/// <summary>
/// Loads a script's editable source for the inline script-source panel in the virtual-tag modal,
/// along with the concurrency token the panel must echo back on save and the script's display name.
/// Reads untracked. Returns <c>null</c> when the script no longer exists.
/// </summary>
/// <param name="scriptId">The script whose source to load.</param>
/// <param name="ct">A token to cancel the load.</param>
/// <returns>The <c>(SourceCode, RowVersion, Name)</c> triple, or <c>null</c> when missing.</returns>
Task<(string SourceCode, byte[] RowVersion, string Name)?> GetScriptSourceAsync(string scriptId, CancellationToken ct = default);
/// <summary>
/// Counts how many virtual tags bind the given script, so the inline editor can warn the operator
/// that an edit to a shared script affects every virtual tag using it.
/// </summary>
/// <param name="scriptId">The script to count usages of.</param>
/// <param name="ct">A token to cancel the query.</param>
/// <returns>The number of virtual tags whose <c>ScriptId</c> matches.</returns>
Task<int> CountVirtualTagsUsingScriptAsync(string scriptId, CancellationToken ct = default);
/// <summary>
/// Saves an edited script body from the inline panel: updates <c>SourceCode</c> and recomputes the
/// SHA-256 <c>SourceHash</c> (lower-case hex, matching the Script-edit page). This save is separate
/// from the virtual-tag save and is guarded by its own last-write-wins optimistic concurrency on
/// <see cref="Configuration.Entities.Script.RowVersion"/>.
/// </summary>
/// <param name="scriptId">The script to update.</param>
/// <param name="sourceCode">The new source body.</param>
/// <param name="rowVersion">The concurrency token the panel last read.</param>
/// <param name="ct">A token to cancel the operation.</param>
/// <returns>Success, a missing-row failure, or a concurrency failure.</returns>
Task<(bool Ok, string? Error)> UpdateScriptSourceAsync(string scriptId, string sourceCode, byte[] rowVersion, CancellationToken ct = default);
}