From 0097521c7593a67d3f634977fb442ee1f28fa646 Mon Sep 17 00:00:00 2001 From: Alex Mickelson Date: Tue, 1 Aug 2023 23:22:38 -0600 Subject: [PATCH] breaking up logic for canvas syncronization --- .../Module/Assignment/AssignmentDetails.razor | 5 +- .../Features/Configuration/CoursePlanner.cs | 188 +----------------- .../CoursePlannerSyncronizationExtensions.cs | 186 +++++++++++++++++ ...s => CoursePlannerValidationExtensions.cs} | 0 Management/Services/WebRequestor.cs | 10 +- 5 files changed, 200 insertions(+), 189 deletions(-) create mode 100644 Management/Features/Configuration/CoursePlannerSyncronizationExtensions.cs rename Management/Features/Configuration/{CoursePlannerExtensions.cs => CoursePlannerValidationExtensions.cs} (100%) diff --git a/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor b/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor index 416aff0..62045ad 100644 --- a/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor +++ b/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor @@ -144,7 +144,10 @@ && planner.LocalCourse.CanvasId != null && planner.CanvasAssignments != null && planner.CanvasModules != null - && planner.AssignmentNeedsUpdates(Assignment) + && Assignment.NeedsUpdates( + planner.CanvasAssignments, + planner.LocalCourse.AssignmentTemplates + ) ) {
Need to update canvas
diff --git a/Management/Features/Configuration/CoursePlanner.cs b/Management/Features/Configuration/CoursePlanner.cs index eb4766b..917960c 100644 --- a/Management/Features/Configuration/CoursePlanner.cs +++ b/Management/Features/Configuration/CoursePlanner.cs @@ -97,14 +97,15 @@ public class CoursePlanner var canvasId = LocalCourse.CanvasId ?? throw new Exception("no course canvas id to sync with canvas"); - await ensureAllModulesExistInCanvas(canvasId); + await LocalCourse.EnsureAllModulesExistInCanvas(canvasId, CanvasModules, canvas); CanvasModules = await canvas.GetModules(canvasId); - await sortCanvasModules(canvasId); + + await LocalCourse.SortCanvasModules(canvasId, CanvasModules, canvas); CanvasModulesItems = await canvas.GetAllModulesItems(canvasId, CanvasModules); - await syncModulesWithCanvasData(canvasId); + LocalCourse = await LocalCourse.SyncModulesWithCanvasData(canvasId, CanvasModules, canvas); - await syncAssignmentsWithCanvas(canvasId); + await LocalCourse.SyncAssignmentsWithCanvas(canvasId, CanvasAssignments, canvas); CanvasAssignments = await canvas.Assignments.GetAll(canvasId); await syncModuleItemsWithCanvas(canvasId); @@ -115,185 +116,6 @@ public class CoursePlanner Console.WriteLine("done syncing with canvas\n"); } - private async Task syncModulesWithCanvasData(ulong canvasId) - { - if (LocalCourse == null) - return; - - CanvasModules = await canvas.GetModules(canvasId); - LocalCourse = LocalCourse with - { - Modules = LocalCourse.Modules.Select(m => - { - var canvasModule = CanvasModules.FirstOrDefault(cm => cm.Name == m.Name); - return canvasModule == null ? m : m with { CanvasId = canvasModule.Id }; - }) - }; - } - - private async Task ensureAllModulesExistInCanvas(ulong canvasId) - { - if (LocalCourse == null || CanvasModules == null) - return; - - foreach (var module in LocalCourse.Modules) - { - var canvasModule = CanvasModules.FirstOrDefault(cm => cm.Id == module.CanvasId); - if (canvasModule == null) - { - await canvas.CreateModule(canvasId, module.Name); - } - } - } - - private async Task sortCanvasModules(ulong canvasId) - { - if (LocalCourse == null) - throw new Exception("cannot sort modules, no course selected"); - if (CanvasModules == null) - throw new Exception("cannot sort modules, no canvas modules loaded"); - - var currentCanvasPositions = CanvasModules.ToDictionary(m => m.Id, m => m.Position); - foreach (var (localModule, i) in LocalCourse.Modules.Select((m, i) => (m, i))) - { - var correctPosition = i + 1; - var moduleCanvasId = - localModule.CanvasId ?? throw new Exception("cannot sort module if no module canvas id"); - var currentCanvasPosition = currentCanvasPositions[moduleCanvasId]; - if (currentCanvasPosition != correctPosition) - { - await canvas.UpdateModule(canvasId, moduleCanvasId, localModule.Name, correctPosition); - } - } - } - - private async Task syncAssignmentsWithCanvas(ulong canvasId) - { - if ( - LocalCourse == null - || LocalCourse.CanvasId == null - || CanvasAssignments == null - || CanvasModules == null - ) - return; - - var moduleTasks = LocalCourse.Modules.Select(async m => - { - var assignmentTasks = m.Assignments.Select(syncAssignmentToCanvas); - var assignments = await Task.WhenAll(assignmentTasks); - return m with { Assignments = assignments }; - }); - - var modules = await Task.WhenAll(moduleTasks); - LocalCourse = LocalCourse with { Modules = modules }; - } - - private async Task syncAssignmentToCanvas(LocalAssignment localAssignment) - { - if ( - LocalCourse == null - || LocalCourse.CanvasId == null - || CanvasAssignments == null - || CanvasModules == null - ) - throw new Exception( - "cannot create canvas assignment if local course is null or other values not set" - ); - - ulong canvasId = LocalCourse.CanvasId ?? throw new Exception("no canvas id to create course"); - var canvasAssignment = CanvasAssignments.FirstOrDefault( - ca => ca.Id == localAssignment.canvasId - ); - string localHtmlDescription = localAssignment.GetDescriptionHtml( - LocalCourse.AssignmentTemplates - ); - - if (canvasAssignment != null) - { - var assignmentNeedsUpdates = AssignmentNeedsUpdates(localAssignment, quiet: false); - if (assignmentNeedsUpdates) - { - await canvas.Assignments.Update(courseId: canvasId, localAssignment, localHtmlDescription); - } - return localAssignment; - } - else - { - return await canvas.Assignments.Create(canvasId, localAssignment, localHtmlDescription); - } - } - - public bool AssignmentNeedsUpdates(LocalAssignment localAssignment, bool quiet = true) - { - if ( - LocalCourse == null - || LocalCourse.CanvasId == null - || CanvasAssignments == null - || CanvasModules == null - ) - throw new Exception( - "cannot check if assignment needs updates if local course is null or other values not set" - ); - - var canvasAssignment = CanvasAssignments.First(ca => ca.Id == localAssignment.canvasId); - - var localHtmlDescription = localAssignment.GetDescriptionHtml(LocalCourse.AssignmentTemplates); - - var canvasHtmlDescription = canvasAssignment.Description; - canvasHtmlDescription = Regex.Replace(canvasHtmlDescription, "", ""); - canvasHtmlDescription = Regex.Replace(canvasHtmlDescription, "", ""); - - var dueDatesSame = canvasAssignment.DueAt == localAssignment.due_at; - var descriptionSame = canvasHtmlDescription == localHtmlDescription; - var nameSame = canvasAssignment.Name == localAssignment.name; - var lockDateSame = canvasAssignment.LockAt == localAssignment.lock_at; - var pointsSame = canvasAssignment.PointsPossible == localAssignment.points_possible; - var submissionTypesSame = canvasAssignment.SubmissionTypes.SequenceEqual( - localAssignment.submission_types.Select(t => t.ToString()) - ); - - if (!quiet) - { - if (!dueDatesSame) - Console.WriteLine( - $"Due dates different for {localAssignment.name}, local: {localAssignment.due_at}, in canvas {canvasAssignment.DueAt}" - ); - - if (!descriptionSame) - { - Console.WriteLine($"descriptions different for {localAssignment.name}"); - Console.WriteLine("Local Description:"); - Console.WriteLine(localHtmlDescription); - Console.WriteLine("Canvas Description: "); - Console.WriteLine(canvasHtmlDescription); - } - - if (!nameSame) - Console.WriteLine( - $"names different for {localAssignment.name}, local: {localAssignment.name}, in canvas {canvasAssignment.Name}" - ); - if (!lockDateSame) - Console.WriteLine( - $"Lock Dates different for {localAssignment.name}, local: {localAssignment.lock_at}, in canvas {canvasAssignment.LockAt}" - ); - if (!pointsSame) - Console.WriteLine( - $"Points different for {localAssignment.name}, local: {localAssignment.points_possible}, in canvas {canvasAssignment.PointsPossible}" - ); - if (!submissionTypesSame) - Console.WriteLine( - $"Submission Types different for {localAssignment.name}, local: {JsonSerializer.Serialize(localAssignment.submission_types.Select(t => t.ToString()))}, in canvas {JsonSerializer.Serialize(canvasAssignment.SubmissionTypes)}" - ); - } - - return !nameSame - || !dueDatesSame - || !lockDateSame - || !descriptionSame - || !pointsSame - || !submissionTypesSame; - } - private async Task syncModuleItemsWithCanvas(ulong canvasId) { if (LocalCourse == null) diff --git a/Management/Features/Configuration/CoursePlannerSyncronizationExtensions.cs b/Management/Features/Configuration/CoursePlannerSyncronizationExtensions.cs new file mode 100644 index 0000000..c7c4c97 --- /dev/null +++ b/Management/Features/Configuration/CoursePlannerSyncronizationExtensions.cs @@ -0,0 +1,186 @@ +using System.Text.RegularExpressions; +using CanvasModel.Assignments; +using CanvasModel.Modules; +using LocalModels; +using Management.Services.Canvas; + +namespace Management.Planner; + +public static class CoursePlannerSyncronizationExtensions +{ + internal static async Task EnsureAllModulesExistInCanvas( + this LocalCourse localCourse, + ulong canvasId, + IEnumerable canvasModules, + CanvasService canvas + ) + { + foreach (var module in localCourse.Modules) + { + var canvasModule = canvasModules.FirstOrDefault(cm => cm.Id == module.CanvasId); + if (canvasModule == null) + { + await canvas.CreateModule(canvasId, module.Name); + } + } + } + + internal static async Task SortCanvasModules( + this LocalCourse localCourse, + ulong canvasId, + IEnumerable canvasModules, + CanvasService canvas + ) + { + var currentCanvasPositions = canvasModules.ToDictionary(m => m.Id, m => m.Position); + foreach (var (localModule, i) in localCourse.Modules.Select((m, i) => (m, i))) + { + var correctPosition = i + 1; + var moduleCanvasId = + localModule.CanvasId ?? throw new Exception("cannot sort module if no module canvas id"); + var currentCanvasPosition = currentCanvasPositions[moduleCanvasId]; + if (currentCanvasPosition != correctPosition) + { + await canvas.UpdateModule(canvasId, moduleCanvasId, localModule.Name, correctPosition); + } + } + } + + internal static async Task SyncModulesWithCanvasData( + this LocalCourse localCourse, + ulong canvasId, + IEnumerable canvasModules, + CanvasService canvas + ) + { + canvasModules = await canvas.GetModules(canvasId); + return localCourse with + { + Modules = localCourse.Modules.Select(m => + { + var canvasModule = canvasModules.FirstOrDefault(cm => cm.Name == m.Name); + return canvasModule == null ? m : m with { CanvasId = canvasModule.Id }; + }) + }; + } + + internal static async Task SyncToCanvas( + this LocalCourse localCourse, + ulong canvasId, + LocalAssignment localAssignment, + IEnumerable canvasAssignments, + CanvasService canvas + ) + { + var canvasAssignment = canvasAssignments.FirstOrDefault( + ca => ca.Id == localAssignment.canvasId + ); + string localHtmlDescription = localAssignment.GetDescriptionHtml( + localCourse.AssignmentTemplates + ); + + if (canvasAssignment != null) + { + var assignmentNeedsUpdates = localAssignment.NeedsUpdates( + canvasAssignments, + localCourse.AssignmentTemplates, + quiet: false + ); + if (assignmentNeedsUpdates) + { + await canvas.Assignments.Update(courseId: canvasId, localAssignment, localHtmlDescription); + } + return localAssignment; + } + else + { + return await canvas.Assignments.Create(canvasId, localAssignment, localHtmlDescription); + } + } + + public static bool NeedsUpdates( + this LocalAssignment localAssignment, + IEnumerable canvasAssignments, + IEnumerable courseAssignmentTemplates, + bool quiet = true + ) + { + var canvasAssignment = canvasAssignments.First(ca => ca.Id == localAssignment.canvasId); + + var localHtmlDescription = localAssignment.GetDescriptionHtml(courseAssignmentTemplates); + + var canvasHtmlDescription = canvasAssignment.Description; + canvasHtmlDescription = Regex.Replace(canvasHtmlDescription, "", ""); + canvasHtmlDescription = Regex.Replace(canvasHtmlDescription, "", ""); + + var dueDatesSame = canvasAssignment.DueAt == localAssignment.due_at; + var descriptionSame = canvasHtmlDescription == localHtmlDescription; + var nameSame = canvasAssignment.Name == localAssignment.name; + var lockDateSame = canvasAssignment.LockAt == localAssignment.lock_at; + var pointsSame = canvasAssignment.PointsPossible == localAssignment.points_possible; + var submissionTypesSame = canvasAssignment.SubmissionTypes.SequenceEqual( + localAssignment.submission_types.Select(t => t.ToString()) + ); + + if (!quiet) + { + if (!dueDatesSame) + Console.WriteLine( + $"Due dates different for {localAssignment.name}, local: {localAssignment.due_at}, in canvas {canvasAssignment.DueAt}" + ); + + if (!descriptionSame) + { + Console.WriteLine($"descriptions different for {localAssignment.name}"); + Console.WriteLine("Local Description:"); + Console.WriteLine(localHtmlDescription); + Console.WriteLine("Canvas Description: "); + Console.WriteLine(canvasHtmlDescription); + } + + if (!nameSame) + Console.WriteLine( + $"names different for {localAssignment.name}, local: {localAssignment.name}, in canvas {canvasAssignment.Name}" + ); + if (!lockDateSame) + Console.WriteLine( + $"Lock Dates different for {localAssignment.name}, local: {localAssignment.lock_at}, in canvas {canvasAssignment.LockAt}" + ); + if (!pointsSame) + Console.WriteLine( + $"Points different for {localAssignment.name}, local: {localAssignment.points_possible}, in canvas {canvasAssignment.PointsPossible}" + ); + if (!submissionTypesSame) + Console.WriteLine( + $"Submission Types different for {localAssignment.name}, local: {JsonSerializer.Serialize(localAssignment.submission_types.Select(t => t.ToString()))}, in canvas {JsonSerializer.Serialize(canvasAssignment.SubmissionTypes)}" + ); + } + + return !nameSame + || !dueDatesSame + || !lockDateSame + || !descriptionSame + || !pointsSame + || !submissionTypesSame; + } + + internal static async Task SyncAssignmentsWithCanvas( + this LocalCourse localCourse, + ulong canvasId, + IEnumerable canvasAssignments, + CanvasService canvas + ) + { + var moduleTasks = localCourse.Modules.Select(async m => + { + var assignmentTasks = m.Assignments.Select( + (a) => localCourse.SyncToCanvas(canvasId, a, canvasAssignments, canvas) + ); + var assignments = await Task.WhenAll(assignmentTasks); + return m with { Assignments = assignments }; + }); + + var modules = await Task.WhenAll(moduleTasks); + return localCourse with { Modules = modules }; + } +} diff --git a/Management/Features/Configuration/CoursePlannerExtensions.cs b/Management/Features/Configuration/CoursePlannerValidationExtensions.cs similarity index 100% rename from Management/Features/Configuration/CoursePlannerExtensions.cs rename to Management/Features/Configuration/CoursePlannerValidationExtensions.cs diff --git a/Management/Services/WebRequestor.cs b/Management/Services/WebRequestor.cs index 0044119..b07be97 100644 --- a/Management/Services/WebRequestor.cs +++ b/Management/Services/WebRequestor.cs @@ -89,17 +89,17 @@ public class WebRequestor : IWebRequestor } return data; } - catch (System.NotSupportedException exception) + catch (System.NotSupportedException ) { Console.WriteLine(response.Content); - throw exception; + throw; } - catch (JsonException ex) + catch (JsonException) { System.Console.WriteLine(response.ResponseUri); System.Console.WriteLine(response.Content); - Console.WriteLine($"An error occurred during deserialization: {ex.Message}"); - throw ex; + Console.WriteLine($"An error occurred during deserialization"); + throw; } } }