diff --git a/Management.Web/Program.cs b/Management.Web/Program.cs index 0559d99..67a3107 100644 --- a/Management.Web/Program.cs +++ b/Management.Web/Program.cs @@ -37,6 +37,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Management.Web/Shared/Module/ModuleDetail.razor b/Management.Web/Shared/Module/ModuleDetail.razor index 28b22a1..b25fdb6 100644 --- a/Management.Web/Shared/Module/ModuleDetail.razor +++ b/Management.Web/Shared/Module/ModuleDetail.razor @@ -132,7 +132,7 @@ /> *@
-
Assignments
+
+
Assignments
@foreach (var a in Module.Assignments) diff --git a/Management.Web/Shared/Module/RenameModule.razor b/Management.Web/Shared/Module/RenameModule.razor new file mode 100644 index 0000000..32ca765 --- /dev/null +++ b/Management.Web/Shared/Module/RenameModule.razor @@ -0,0 +1,65 @@ +@using Management.Web.Shared.Components + +@inject CoursePlanner planner + +@code { + + [Parameter] + [EditorRequired] + public LocalModule Module { get; set; } = default!; + private Modal? modal { get; set; } = null; + private string Name { get; set; } = string.Empty; + + protected override void OnParametersSet() + { + if (Name == string.Empty) + Name = Module.Name; + } + + private void submitHandler() + { + if (planner.LocalCourse == null) + return; + + var newModule = Module with + { + Name = Name + }; + + var newModules = planner.LocalCourse.Modules.Select( + m => m.Id == Module.Id + ? newModule + : m + ).ToArray(); + + planner.LocalCourse = planner.LocalCourse with + { + Modules = newModules + }; + Name = ""; + modal?.Hide(); + } +} + + + + + Rename Module + + +
+ + +
+ +
+ +
+
\ No newline at end of file diff --git a/Management/Features/Configuration/CoursePlanner.cs b/Management/Features/Configuration/CoursePlanner.cs index 9c5498a..e1dc7a3 100644 --- a/Management/Features/Configuration/CoursePlanner.cs +++ b/Management/Features/Configuration/CoursePlanner.cs @@ -93,7 +93,7 @@ public class CoursePlanner var assignmentsTask = canvas.Assignments.GetAll(canvasId); var quizzesTask = canvas.Quizzes.GetAll(canvasId); - var modulesTask = canvas.GetModules(canvasId); + var modulesTask = canvas.Modules.GetModules(canvasId); var assignmentGroupsTask = canvas.AssignmentGroups.GetAll(canvasId); CanvasAssignments = await assignmentsTask; @@ -101,7 +101,7 @@ public class CoursePlanner CanvasModules = await modulesTask; CanvasAssignmentGroups = await assignmentGroupsTask; - CanvasModulesItems = await canvas.GetAllModulesItems(canvasId, CanvasModules); + CanvasModulesItems = await canvas.Modules.GetAllModulesItems(canvasId, CanvasModules); LoadingCanvasData = false; StateHasChanged?.Invoke(); @@ -154,10 +154,10 @@ public class CoursePlanner canvas ); LocalCourse = LocalCourse with { Modules = newModules }; - CanvasModules = await canvas.GetModules(canvasId); + CanvasModules = await canvas.Modules.GetModules(canvasId); await LocalCourse.SortCanvasModules(canvasId, CanvasModules, canvas); - CanvasModulesItems = await canvas.GetAllModulesItems(canvasId, CanvasModules); + CanvasModulesItems = await canvas.Modules.GetAllModulesItems(canvasId, CanvasModules); LocalCourse = await LocalCourse.SyncModulesWithCanvasData(canvasId, CanvasModules, canvas); @@ -167,7 +167,7 @@ public class CoursePlanner LocalCourse = await LocalCourse.SyncQuizzesWithCanvas(canvasId, CanvasQuizzes, canvas); await LocalCourse.SyncModuleItemsWithCanvas(canvasId, CanvasModulesItems, canvas); - CanvasModulesItems = await canvas.GetAllModulesItems(canvasId, CanvasModules); + CanvasModulesItems = await canvas.Modules.GetAllModulesItems(canvasId, CanvasModules); LoadingCanvasData = false; StateHasChanged?.Invoke(); diff --git a/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs b/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs index 8306b4d..0490287 100644 --- a/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs +++ b/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs @@ -1,7 +1,4 @@ -using System.Text.RegularExpressions; -using CanvasModel.Assignments; using CanvasModel.Modules; -using CanvasModel.Quizzes; using LocalModels; using Management.Services.Canvas; @@ -11,7 +8,7 @@ public static partial class ModuleSyncronizationExtensions { internal static async Task> EnsureAllModulesExistInCanvas( this LocalCourse localCourse, - ulong canvasId, + ulong canvasCourseId, IEnumerable canvasModules, CanvasService canvas ) @@ -21,11 +18,15 @@ public static partial class ModuleSyncronizationExtensions var canvasModule = canvasModules.FirstOrDefault(cm => cm.Id == module.CanvasId); if (canvasModule == null) { - var newModule = await canvas.CreateModule(canvasId, module.Name); + var newModule = await canvas.Modules.CreateModule(canvasCourseId, module.Name); return module with { CanvasId = newModule.Id }; } - else - return module; + + if (canvasModule.Name != module.Name) + { + await canvas.Modules.UpdateModule(canvasCourseId, canvasModule.Id, module.Name, canvasModule.Position); + } + return module; }); var newModules = await Task.WhenAll(moduleTasks); return newModules ?? throw new Exception("Error ensuring all modules exist in canvas"); @@ -41,13 +42,13 @@ public static partial class ModuleSyncronizationExtensions 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; + uint correctPosition = (uint)(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); + await canvas.Modules.UpdateModule(canvasId, moduleCanvasId, localModule.Name, correctPosition); } } } @@ -59,7 +60,7 @@ public static partial class ModuleSyncronizationExtensions CanvasService canvas ) { - canvasModules = await canvas.GetModules(canvasId); + canvasModules = await canvas.Modules.GetModules(canvasId); return localCourse with { Modules = localCourse.Modules.Select(m => @@ -134,9 +135,9 @@ public static partial class ModuleSyncronizationExtensions } } - foreach(var localQuiz in localModule.Quizzes) + foreach (var localQuiz in localModule.Quizzes) { - + var canvasModuleItemContentIds = canvasModulesItems[moduleCanvasId].Select(i => i.ContentId); if (!canvasModuleItemContentIds.Contains(localQuiz.CanvasId)) { @@ -178,7 +179,7 @@ public static partial class ModuleSyncronizationExtensions ); var canvasModuleItems = anyUpdated - ? await canvas.GetModuleItems(canvasId, moduleCanvasId) + ? await canvas.Modules.GetModuleItems(canvasId, moduleCanvasId) : canvasModulesItems[moduleCanvasId]; await localModule.SortModuleItems(canvasId, moduleCanvasId, canvasModuleItems, canvas); diff --git a/Management/Services/Canvas/CanvasModuleService.cs b/Management/Services/Canvas/CanvasModuleService.cs new file mode 100644 index 0000000..7478e9f --- /dev/null +++ b/Management/Services/Canvas/CanvasModuleService.cs @@ -0,0 +1,93 @@ + +using CanvasModel.Modules; +using LocalModels; +using RestSharp; + +namespace Management.Services.Canvas; + +public class CanvasModuleService +{ + + private readonly IWebRequestor webRequestor; + private readonly CanvasServiceUtils utils; + + public CanvasModuleService(IWebRequestor webRequestor, CanvasServiceUtils utils) + { + this.webRequestor = webRequestor; + this.utils = utils; + } + + + public async Task> GetModules(ulong courseId) + { + var url = $"courses/{courseId}/modules"; + var request = new RestRequest(url); + var modules = await utils.PaginatedRequest>(request); + return modules.SelectMany(c => c).ToArray(); + } + + public async Task CreateModule(ulong courseId, string name) + { + Console.WriteLine($"Creating Module: {name}"); + var url = $"courses/{courseId}/modules"; + var request = new RestRequest(url); + var body = new + { + module = new + { + name + } + }; + request.AddBody(body); + + var (newModule, _) = await webRequestor.PostAsync(request); + return newModule ?? throw new Exception($"failed to create new canvas module {name}"); + } + + public async Task UpdateModule(ulong courseId, ulong moduleId, string name, uint position) + { + Console.WriteLine($"Updating Module: {name}"); + var url = $"courses/{courseId}/modules/{moduleId}"; + var body = new { module = new { name = name, position = position } }; + var request = new RestRequest(url); + request.AddBody(body); + + await webRequestor.PutAsync(request); + } + + public async Task> GetModuleItems(ulong courseId, ulong moduleId) + { + var url = $"courses/{courseId}/modules/{moduleId}/items"; + var request = new RestRequest(url); + var (items, response) = await webRequestor.GetAsync>(request); + if (items == null) + throw new Exception($"Error getting canvas module items for {url}"); + return items; + } + + public async Task>> GetAllModulesItems( + ulong courseId, + IEnumerable modules + ) + { + var itemsTasks = modules.Select( + async (m) => + { + var items = await GetModuleItems(courseId, m.Id); + return (m, items); + } + ); + + var output = new Dictionary>(); + var itemTasksResult = await Task.WhenAll(itemsTasks); + foreach (var (module, items) in itemTasksResult) + { + if (module == null || items == null) + throw new Exception( + "i'm not sure how we got here, but module and items are null after looking up module items" + ); + output[module.Id] = items; + } + return output; + } +} \ No newline at end of file diff --git a/Management/Services/Canvas/CanvasService.cs b/Management/Services/Canvas/CanvasService.cs index e231cd5..6ef4b24 100644 --- a/Management/Services/Canvas/CanvasService.cs +++ b/Management/Services/Canvas/CanvasService.cs @@ -14,6 +14,7 @@ public class CanvasService public CanvasAssignmentService Assignments { get; } public CanvasAssignmentGroupService AssignmentGroups { get; } + public CanvasModuleService Modules { get; } public CanvasQuizService Quizzes { get; } public CanvasService( @@ -21,6 +22,7 @@ public class CanvasService CanvasServiceUtils utils, CanvasAssignmentService Assignments, CanvasAssignmentGroupService AssignmentGroups, + CanvasModuleService Modules, CanvasQuizService Quizzes ) { @@ -28,6 +30,7 @@ public class CanvasService this.utils = utils; this.Assignments = Assignments; this.AssignmentGroups = AssignmentGroups; + this.Modules = Modules; this.Quizzes = Quizzes; } @@ -64,78 +67,7 @@ public class CanvasService return data; } - public async Task> GetModules(ulong courseId) - { - var url = $"courses/{courseId}/modules"; - var request = new RestRequest(url); - var modules = await utils.PaginatedRequest>(request); - return modules.SelectMany(c => c).ToArray(); - } - public async Task CreateModule(ulong courseId, string name) - { - Console.WriteLine($"Creating Module: {name}"); - var url = $"courses/{courseId}/modules"; - var request = new RestRequest(url); - var body = new - { - module = new - { - name = name - } - }; - request.AddBody(body); - - var (newModule, _) = await webRequestor.PostAsync(request); - return newModule ?? throw new Exception($"failed to create new canvas module {name}"); - } - - public async Task UpdateModule(ulong courseId, ulong moduleId, string name, int position) - { - Console.WriteLine($"Updating Module: {name}"); - var url = $"courses/{courseId}/modules/{moduleId}"; - var body = new { module = new { name = name, position = position } }; - var request = new RestRequest(url); - request.AddBody(body); - - await webRequestor.PutAsync(request); - } - - public async Task> GetModuleItems(ulong courseId, ulong moduleId) - { - var url = $"courses/{courseId}/modules/{moduleId}/items"; - var request = new RestRequest(url); - var (items, response) = await webRequestor.GetAsync>(request); - if (items == null) - throw new Exception($"Error getting canvas module items for {url}"); - return items; - } - - public async Task>> GetAllModulesItems( - ulong courseId, - IEnumerable modules - ) - { - var itemsTasks = modules.Select( - async (m) => - { - var items = await GetModuleItems(courseId, m.Id); - return (m, items); - } - ); - - var output = new Dictionary>(); - var itemTasksResult = await Task.WhenAll(itemsTasks); - foreach (var (module, items) in itemTasksResult) - { - if (module == null || items == null) - throw new Exception( - "i'm not sure how we got here, but module and items are null after looking up module items" - ); - output[module.Id] = items; - } - return output; - } public async Task> GetCurrentTermsFor( DateTime? _queryDate = null