From 5839b404416b59b271793858777a01a2eed401f6 Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 15 May 2025 08:18:38 +0200 Subject: Clean up later... --- .../MassPolicyEditorModal.razor | 140 +++++++++++++++------ .../MassPolicyEditorModal.razor.css | 15 +++ 2 files changed, 118 insertions(+), 37 deletions(-) create mode 100644 MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor.css (limited to 'MatrixUtils.Web/Shared/PolicyEditorComponents') diff --git a/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor b/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor index 4ab899c..f7bb200 100644 --- a/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor +++ b/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor @@ -25,7 +25,7 @@
Entities:
- +
@@ -35,16 +35,43 @@ @* $1$ @PolicyEvent.ToJson(true, true) #1# *@ @* *@ @* *@ - Cancel - - Save - + @if (!VerifyIntent) { + Cancel + + Save + + @if (!string.IsNullOrWhiteSpace(Response)) { +
@Response
+ } + } + else { + WARNING!!! +
+ + @if (!string.IsNullOrWhiteSpace(Response)) { +
@Response
+ } + + Are you sure you want to do this? + No + + Yes + + } @@ -59,9 +86,20 @@ [Parameter] public required GenericRoom Room { get; set; } - public string Recommendation { get; set; } = "m.ban"; - public string Reason { get; set; } = "spam"; - public string Users { get; set; } = ""; + private string Recommendation { get; set; } = "m.ban"; + private string Reason { get; set; } = "spam"; + + private string Entities { get; set; } = ""; + + private string? Response { + get; + set { + field = value; + StateHasChanged(); + } + } + + private bool VerifyIntent { get; set; } private static FrozenSet KnownPolicyTypes = StateEvent.KnownStateEventTypes.Where(x => x.IsAssignableTo(typeof(PolicyRuleEventContent))).ToFrozenSet(); @@ -74,47 +112,75 @@ private string? MappedType { get; set; } - private async Task Save() { - try { - await DoActualSave(); - } - catch (Exception e) { - Console.WriteLine($"Failed to save: {e}"); - } - } - - private async Task DoActualSave() { + private async Task Save(bool force = false) { if (string.IsNullOrWhiteSpace(MappedType)) { - Console.WriteLine("No type selected"); + Response = "No type selected"; return; } - if (string.IsNullOrWhiteSpace(Users)) { - Console.WriteLine("No users selected"); + if (string.IsNullOrWhiteSpace(Entities)) { + Response = "No users selected"; return; } - Console.WriteLine($"Saving ---"); - Console.WriteLine($"Users = {Users}"); + Console.WriteLine("Saving ---"); - var users = Users.Split("\n") + var entities = Entities.Split("\n", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Select(x => x.Trim()) - .Where(x => x.StartsWith('@')) .Distinct() .ToList(); + + if (!force && !Validate(entities, PolicyTypes[MappedType])) { + List distinctTypes = entities + .Select(GuessType) + .Where(x => x != null) + .Distinct() + .Select(x => x!.Name) + .ToList(); + + VerifyIntent = true; + Response = $"Invalid entities. Expected {PolicyTypes[MappedType].Name}, got:\n - " + + string.Join("\n - ", distinctTypes); + return; + } + + try { + await SaveAll(entities); + } + catch (Exception e) { + Response = $"Failed to save: {e}"; + } + } + + private bool Validate(List entities, Type expectedType) { + return entities.All(x => GuessType(x) == expectedType); + } + + private Type? GuessType(string entity) { + var sigil = entity[0]; + return TypesBySigil.GetValueOrDefault(sigil.ToString(), typeof(ServerPolicyRuleEventContent)); + } + + private Dictionary TypesBySigil = new() { + { "@", typeof(UserPolicyRuleEventContent) }, + { "!", typeof(RoomPolicyRuleEventContent) }, + { "#", typeof(RoomPolicyRuleEventContent) } + }; + + private async Task SaveAll(List entities) { await foreach (var evt in Room.GetFullStateAsync()) { if (evt is null || !AllKnownPolicyTypes.Contains(evt.Type) || !evt.TypedContent!.GetType().IsAssignableTo(PolicyTypes[MappedType!]) ) continue; - + if (evt.TypedContent is PolicyRuleEventContent content && content.Recommendation == Recommendation && content.Reason == Reason) { - if (content.Entity != null && users.Contains(content.Entity)) - users.Remove(content.Entity); + if (content.Entity != null && entities.Contains(content.Entity)) + entities.Remove(content.Entity); } } - - var tasks = users.Select(x => ExecuteBan(Room, x)).ToList(); + + var tasks = entities.Select(x => ExecuteBan(Room, x)).ToList(); await Task.WhenAll(tasks); OnSaved.Invoke(); @@ -124,7 +190,7 @@ bool success = false; while (!success) { try { - var content = Activator.CreateInstance(PolicyTypes[MappedType!]) as PolicyRuleEventContent; + var content = Activator.CreateInstance(PolicyTypes[MappedType!]) as PolicyRuleEventContent ?? throw new InvalidOperationException("Failed to create event content"); content.Recommendation = Recommendation; content.Reason = Reason; content.Entity = entity; diff --git a/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor.css b/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor.css new file mode 100644 index 0000000..49ab31b --- /dev/null +++ b/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor.css @@ -0,0 +1,15 @@ +.blink { + animation: blinker 2s linear infinite; +} + +@keyframes blinker { + 0% { + opacity: 1; + } + 50% { + opacity: 0; + } + 100% { + opacity: 1; + } +} \ No newline at end of file -- cgit 1.5.1