diff --git a/Management.Web/Pages/AssignmentForm/AssignmentForm.razor b/Management.Web/Pages/AssignmentForm/AssignmentForm.razor index 883bb10..1733de2 100644 --- a/Management.Web/Pages/AssignmentForm/AssignmentForm.razor +++ b/Management.Web/Pages/AssignmentForm/AssignmentForm.razor @@ -137,7 +137,7 @@ } private CanvasAssignment? assignmentInCanvas => - planner.CanvasAssignments?.FirstOrDefault(a => a.Name == assignmentContext.Assignment?.Name); + planner.CanvasData?.Assignments.FirstOrDefault(a => a.Name == assignmentContext.Assignment?.Name); private string canvasAssignmentUrl => $"https://snow.instructure.com/courses/{planner.LocalCourse?.Settings.CanvasId}/assignments/{assignmentInCanvas?.Id}"; diff --git a/Management.Web/Pages/Course/CourseDetails.razor b/Management.Web/Pages/Course/CourseDetails.razor index 03b141f..e66a515 100644 --- a/Management.Web/Pages/Course/CourseDetails.razor +++ b/Management.Web/Pages/Course/CourseDetails.razor @@ -17,7 +17,7 @@ if(firstRender) { if( - planner.CanvasAssignments == null + planner.CanvasData == null && planner.LocalCourse != null && planner.LocalCourse.Settings.CanvasId != null ) diff --git a/Management.Web/Pages/Course/Module/ModuleDetail.razor b/Management.Web/Pages/Course/Module/ModuleDetail.razor index f7a007d..81e5d77 100644 --- a/Management.Web/Pages/Course/Module/ModuleDetail.razor +++ b/Management.Web/Pages/Course/Module/ModuleDetail.razor @@ -87,7 +87,8 @@ } private bool isSyncedWithCanvas => planner - .CanvasModules? + .CanvasData? + .Modules .FirstOrDefault( cm => cm.Name == Module.Name ) != null; diff --git a/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor b/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor index 5ca0d3e..e39ff95 100644 --- a/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor +++ b/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor @@ -38,7 +38,8 @@ } private CanvasAssignment? assignmentInCanvas => planner - .CanvasAssignments? + .CanvasData? + .Assignments .FirstOrDefault( a => a.Name == Assignment.Name ); @@ -53,8 +54,7 @@ private bool NeedsToBeUpdatedInCanvas => planner.LocalCourse != null && planner.LocalCourse.Settings.CanvasId != null - && planner.CanvasAssignments != null - && planner.CanvasModules != null + && planner.CanvasData != null && assignmentInCanvas != null && Assignment.NeedsUpdates( (CanvasAssignment)assignmentInCanvas, diff --git a/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor b/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor index b0e9f63..2db4ab9 100644 --- a/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor +++ b/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor @@ -18,8 +18,8 @@ dragContainer.DropCallback = null; } private bool existsInCanvas => - planner.CanvasQuizzes != null - ? Quiz.QuizIsCreated(planner.CanvasQuizzes) + planner.CanvasData != null + ? Quiz.QuizIsCreated(planner.CanvasData.Quizzes) : false; diff --git a/Management.Web/Pages/CoursePageForm/CoursePageForm.razor b/Management.Web/Pages/CoursePageForm/CoursePageForm.razor index 6a3cc88..ced9760 100644 --- a/Management.Web/Pages/CoursePageForm/CoursePageForm.razor +++ b/Management.Web/Pages/CoursePageForm/CoursePageForm.razor @@ -32,7 +32,7 @@ private CanvasPage? pageInCanvas => - planner.CanvasPages?.FirstOrDefault(a => a.Title == pageContext.Page?.Name); + planner.CanvasData?.Pages.FirstOrDefault(a => a.Title == pageContext.Page?.Name); private string canvasPageUrl => diff --git a/Management.Web/Pages/QuizForm/QuizFormPage.razor b/Management.Web/Pages/QuizForm/QuizFormPage.razor index dad7122..f2e9177 100644 --- a/Management.Web/Pages/QuizForm/QuizFormPage.razor +++ b/Management.Web/Pages/QuizForm/QuizFormPage.razor @@ -62,7 +62,7 @@ } StateHasChanged(); - if (planner.CanvasQuizzes == null) + if (planner.CanvasData == null) { await planner.LoadCanvasData(); } @@ -91,7 +91,7 @@ Navigation.NavigateTo("/course/" + planner.LocalCourse?.Settings.Name); } - private CanvasQuiz? quizInCanvas => planner.CanvasQuizzes?.FirstOrDefault(q => q.Title == quizContext.Quiz?.Name); + private CanvasQuiz? quizInCanvas => planner.CanvasData?.Quizzes.FirstOrDefault(q => q.Title == quizContext.Quiz?.Name); private string canvasQuizUrl => $"https://snow.instructure.com/courses/{planner.LocalCourse?.Settings.CanvasId}/quizzes/{quizInCanvas?.Id}"; diff --git a/Management.Web/Program.cs b/Management.Web/Program.cs index 1f80bc2..71b0aff 100644 --- a/Management.Web/Program.cs +++ b/Management.Web/Program.cs @@ -98,11 +98,11 @@ builder.Services.AddHostedService(sp => sp.GetRequiredService()); // TODO: need to handle scoped requirements -builder.Services.AddSingleton(sp => -{ - var akka = sp.GetRequiredService(); - return new CanvasQueue(akka.CanvasQueueActor ?? throw new Exception("Canvas queue actor not properly created")); -}); +// builder.Services.AddSingleton(sp => +// { +// var akka = sp.GetRequiredService(); +// return new CanvasQueueActorWrapper(akka.CoursePlannerActor ?? throw new Exception("Canvas queue actor not properly created")); +// }); builder.Services.AddSingleton(sp => { var akka = sp.GetRequiredService(); diff --git a/Management/Features/Configuration/AssignmentEditorContext.cs b/Management/Features/Configuration/AssignmentEditorContext.cs index 5b3f527..112ad53 100644 --- a/Management/Features/Configuration/AssignmentEditorContext.cs +++ b/Management/Features/Configuration/AssignmentEditorContext.cs @@ -72,7 +72,7 @@ public class AssignmentEditorContext await planner.LoadCanvasData(); - if (planner.CanvasAssignments == null) + if (planner.CanvasData == null) { logger.Log("cannot update assignment in canvas, failed to retrieve current assignments"); return; @@ -87,7 +87,7 @@ public class AssignmentEditorContext logger.Log("Cannot update assignment with null local course canvas id"); return; } - var assignmentInCanvas = planner.CanvasAssignments?.FirstOrDefault(a => a.Id == canvasAssignmentId); + var assignmentInCanvas = planner.CanvasData.Assignments?.FirstOrDefault(a => a.Id == canvasAssignmentId); if (assignmentInCanvas == null) { logger.Log("cannot update assignment in canvas, could not find canvas assignment with id: " + canvasAssignmentId); @@ -121,7 +121,7 @@ public class AssignmentEditorContext return; } await planner.LoadCanvasData(); - if (planner.CanvasAssignments == null) + if (planner.CanvasData == null) { logger.Log("cannot add assignment to canvas, failed to retrieve current assignments"); return; @@ -144,7 +144,7 @@ public class AssignmentEditorContext var createdAssignmentCanvasId = await planner.LocalCourse.SyncAssignmentToCanvas( canvasCourseId: (ulong)courseCanvasId, localAssignment: Assignment, - canvasAssignments: planner.CanvasAssignments, + canvasAssignments: planner.CanvasData.Assignments, canvas: canvas ); @@ -179,7 +179,7 @@ public class AssignmentEditorContext private CanvasModule getCurrentCanvasModule(LocalAssignment assignment, LocalCourse course) { var localModule = getCurrentLocalModule(assignment, course); - var canvasModule = planner.CanvasModules?.FirstOrDefault(m => m.Name == localModule.Name) + var canvasModule = planner.CanvasData?.Modules.FirstOrDefault(m => m.Name == localModule.Name) ?? throw new Exception($"error in assignment context, canvas module with name {localModule.Name} not found in planner"); return canvasModule; } diff --git a/Management/Features/Configuration/CoursePlanner.cs b/Management/Features/Configuration/CoursePlanner.cs index a8897ce..6018a83 100644 --- a/Management/Features/Configuration/CoursePlanner.cs +++ b/Management/Features/Configuration/CoursePlanner.cs @@ -1,4 +1,5 @@ using System.Text.RegularExpressions; + using CanvasModel; using CanvasModel.Assignments; using CanvasModel.Courses; @@ -6,12 +7,25 @@ using CanvasModel.EnrollmentTerms; using CanvasModel.Modules; using CanvasModel.Pages; using CanvasModel.Quizzes; + using LocalModels; + using Management.Services; using Management.Services.Canvas; namespace Management.Planner; + +public record CanvasCourseData +{ + public required IEnumerable Assignments { get; init; } + public required IEnumerable AssignmentGroups { get; init; } + public required IEnumerable Quizzes { get; init; } + public required IEnumerable Modules { get; init; } + public required IEnumerable Pages { get; init; } + public required Dictionary> ModulesItems { get; init; } +} + public class CoursePlanner { private readonly MyLogger logger; @@ -72,11 +86,6 @@ public class CoursePlanner } } - public async Task LoadCourseByName(string courseName) - { - - } - private void saveCourseToFile(LocalCourse courseAsOfDebounce) { _debounceTimer?.Dispose(); @@ -117,23 +126,10 @@ public class CoursePlanner public event Action? StateHasChanged; - public IEnumerable? CanvasAssignments { get; internal set; } - public IEnumerable? CanvasAssignmentGroups { get; internal set; } - public IEnumerable? CanvasQuizzes { get; internal set; } - public IEnumerable? CanvasModules { get; internal set; } - public IEnumerable? CanvasPages { get; internal set; } - public Dictionary>? CanvasModulesItems { get; internal set; } + public CanvasCourseData? CanvasData { get; internal set; } - public async Task<( - IEnumerable CanvasAssignments, - IEnumerable CanvasModules, - Dictionary> CanvasModulesItems, - IEnumerable canvasQuizzes, - IEnumerable canvasAssignmentGroups, - IEnumerable canvasPages - )> LoadCanvasData() + public async Task LoadCanvasData() { - using var activity = DiagnosticsConfig.Source.StartActivity("Loading Canvas Data to Course Planner"); LoadingCanvasData = true; StateHasChanged?.Invoke(); @@ -147,17 +143,26 @@ public class CoursePlanner var assignmentGroupsTask = canvas.AssignmentGroups.GetAll(canvasId); var coursePagesTask = canvas.Pages.GetAll(canvasId); - CanvasAssignments = await assignmentsTask; - CanvasQuizzes = await quizzesTask; - CanvasModules = await modulesTask; - CanvasAssignmentGroups = await assignmentGroupsTask; - CanvasPages = await coursePagesTask; - CanvasModulesItems = await canvas.Modules.GetAllModulesItems(canvasId, CanvasModules); + var canvasAssignments = (await assignmentsTask) ?? throw new Exception("Error loading canvas assignments"); + var canvasQuizzes = (await quizzesTask) ?? throw new Exception("Error loading canvas quizzes"); + var canvasAssignmentGroups = (await assignmentGroupsTask) ?? throw new Exception("Error loading canvas assignment groups"); + var canvasPages = (await coursePagesTask) ?? throw new Exception("Error loading canvas pages"); + var canvasModules = (await modulesTask) ?? throw new Exception("Error loading canvas modules"); + var canvasModulesItems = (await canvas.Modules.GetAllModulesItems(canvasId, canvasModules)) ?? throw new Exception("Error loading canvas module items"); + + CanvasData = new CanvasCourseData + { + Assignments = canvasAssignments, + Quizzes = canvasQuizzes, + AssignmentGroups = canvasAssignmentGroups, + Pages = canvasPages, + Modules = canvasModules, + ModulesItems = canvasModulesItems, + }; LoadingCanvasData = false; StateHasChanged?.Invoke(); - return (CanvasAssignments, CanvasModules, CanvasModulesItems, CanvasQuizzes, CanvasAssignmentGroups, CanvasPages); } public async Task CreateModule(LocalModule newModule) @@ -167,14 +172,20 @@ public class CoursePlanner var canvasCourseId = LocalCourse.Settings.CanvasId ?? throw new Exception("no course canvas id to use to create module"); await canvas.Modules.CreateModule(canvasCourseId, newModule.Name); - CanvasModules = await canvas.Modules.GetModules(canvasCourseId); + var canvasModules = await canvas.Modules.GetModules(canvasCourseId); + if (CanvasData != null) + { + CanvasData = CanvasData with + { + Modules = canvasModules + }; + } } public void Clear() { + CanvasData = null; LocalCourse = null; - CanvasAssignments = null; - CanvasModules = null; } public async Task SyncAssignmentGroups() @@ -185,12 +196,11 @@ public class CoursePlanner var canvasCourseId = LocalCourse.Settings.CanvasId ?? throw new Exception("no course canvas id to use to create module"); + var canvasAssignmentGroups = await canvas.AssignmentGroups.GetAll(canvasCourseId); - CanvasAssignmentGroups = await canvas.AssignmentGroups.GetAll(canvasCourseId); + await LocalCourse.EnsureAllAssignmentGroupsExistInCanvas(canvasCourseId, canvasAssignmentGroups, canvas); - await LocalCourse.EnsureAllAssignmentGroupsExistInCanvas(canvasCourseId, CanvasAssignmentGroups, canvas); - - CanvasAssignmentGroups = await canvas.AssignmentGroups.GetAll(canvasCourseId); + canvasAssignmentGroups = await canvas.AssignmentGroups.GetAll(canvasCourseId); LocalCourse = LocalCourse with { @@ -198,12 +208,16 @@ public class CoursePlanner { AssignmentGroups = LocalCourse.Settings.AssignmentGroups.Select(g => { - var canvasGroup = CanvasAssignmentGroups.FirstOrDefault(c => c.Name == g.Name); + var canvasGroup = canvasAssignmentGroups.FirstOrDefault(c => c.Name == g.Name); return canvasGroup == null ? g : g with { CanvasId = canvasGroup.Id }; }) } }; + CanvasData = CanvasData with + { + AssignmentGroups = canvasAssignmentGroups + }; } } diff --git a/Management/Features/Configuration/PageEditorContext.cs b/Management/Features/Configuration/PageEditorContext.cs index 3475029..760abe2 100644 --- a/Management/Features/Configuration/PageEditorContext.cs +++ b/Management/Features/Configuration/PageEditorContext.cs @@ -89,7 +89,7 @@ public class PageEditorContext( return; } await planner.LoadCanvasData(); - if (planner.CanvasPages == null) + if (planner.CanvasData == null) { logger.Log("cannot add page to canvas, failed to retrieve current pages"); return; @@ -143,7 +143,7 @@ public class PageEditorContext( await planner.LoadCanvasData(); - if (planner.CanvasPages == null) + if (planner.CanvasData == null) { logger.Log("cannot update page in canvas, failed to retrieve current pages"); return; @@ -158,7 +158,7 @@ public class PageEditorContext( logger.Log("Cannot update page with null local course canvas id"); return; } - var assignmentInCanvas = planner.CanvasPages?.FirstOrDefault(p => p.PageId == canvasPageId); + var assignmentInCanvas = planner.CanvasData?.Pages.FirstOrDefault(p => p.PageId == canvasPageId); if (assignmentInCanvas == null) { logger.Log("cannot update page in canvas, could not find canvas page with id: " + canvasPageId); @@ -184,7 +184,7 @@ public class PageEditorContext( private CanvasModule getCurrentCanvasModule(LocalCoursePage quiz, LocalCourse course) { var localModule = getCurrentLocalModule(quiz, course); - var canvasModule = planner.CanvasModules?.FirstOrDefault(m => m.Name == localModule.Name) + var canvasModule = planner.CanvasData?.Modules.FirstOrDefault(m => m.Name == localModule.Name) ?? throw new Exception($"error in page context, canvas module with name {localModule.Name} not found in planner"); return canvasModule; } diff --git a/Management/Features/Configuration/QuizEditorContext.cs b/Management/Features/Configuration/QuizEditorContext.cs index 9f860e7..4810b30 100644 --- a/Management/Features/Configuration/QuizEditorContext.cs +++ b/Management/Features/Configuration/QuizEditorContext.cs @@ -1,6 +1,9 @@ using System.Reflection.Metadata.Ecma335; + using CanvasModel.Modules; + using LocalModels; + using Management.Planner; using Management.Services; using Management.Services.Canvas; @@ -91,7 +94,7 @@ public class QuizEditorContext( return; } await planner.LoadCanvasData(); - if (planner.CanvasQuizzes == null) + if (planner.CanvasData == null) { logger.Log("cannot add quiz to canvas, failed to retrieve current quizzes"); return; @@ -142,7 +145,7 @@ public class QuizEditorContext( private CanvasModule getCurrentCanvasModule(LocalQuiz quiz, LocalCourse course) { var localModule = getCurrentLocalModule(quiz, course); - var canvasModule = planner.CanvasModules?.FirstOrDefault(m => m.Name == localModule.Name) + var canvasModule = planner.CanvasData?.Modules.FirstOrDefault(m => m.Name == localModule.Name) ?? throw new Exception($"error in quiz context, canvas module with name {localModule.Name} not found in planner"); return canvasModule; } diff --git a/Management/Services/Actors/CanvasQueue.cs b/Management/Services/Actors/CanvasQueue.cs deleted file mode 100644 index f7ca500..0000000 --- a/Management/Services/Actors/CanvasQueue.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Akka.Actor; - -using Management.Services.Canvas; - -public class CanvasQueue(IActorRef canvasQueueActor) -{ - private readonly IActorRef canvasQueueActor = canvasQueueActor; - -} \ No newline at end of file diff --git a/Management/Services/Actors/CanvasQueueActor.cs b/Management/Services/Actors/CanvasQueueActor.cs deleted file mode 100644 index 8eff504..0000000 --- a/Management/Services/Actors/CanvasQueueActor.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Akka.Actor; - -using Microsoft.Extensions.DependencyInjection; - -public class CanvasQueueActor : ReceiveActor -{ - private readonly IServiceProvider serviceProvider; - private readonly IServiceScope scope; - private readonly ILogger logger; - - public CanvasQueueActor(IServiceProvider serviceProviderArg) - { - serviceProvider = serviceProviderArg; - scope = serviceProvider.CreateScope(); - logger = scope.ServiceProvider.GetRequiredService>(); - } -} \ No newline at end of file diff --git a/Management/Services/Actors/CoursePlannerActor.cs b/Management/Services/Actors/CoursePlannerActor.cs new file mode 100644 index 0000000..73efe13 --- /dev/null +++ b/Management/Services/Actors/CoursePlannerActor.cs @@ -0,0 +1,18 @@ +using Akka.Actor; + +using Management.Services; + +using Microsoft.Extensions.DependencyInjection; + +public class CoursePlannerActor: ReceiveActor +{ + private readonly IServiceProvider serviceProvider; + private readonly IServiceScope scope; + private readonly MyLogger logger; + public CoursePlannerActor(IServiceProvider serviceProviderArg) + { + serviceProvider = serviceProviderArg; + scope = serviceProvider.CreateScope(); + logger = scope.ServiceProvider.GetRequiredService>(); + } +} \ No newline at end of file diff --git a/Management/Services/Actors/LocalStorageActor.cs b/Management/Services/Actors/LocalStorageActor.cs index 9764c44..a651b78 100644 --- a/Management/Services/Actors/LocalStorageActor.cs +++ b/Management/Services/Actors/LocalStorageActor.cs @@ -1,15 +1,16 @@ using Akka.Actor; + using LocalModels; + using Management.Services; + using Microsoft.Extensions.DependencyInjection; -public class IStorageActor : ReceiveActor {} - -public class LocalStorageActor : IStorageActor +public class LocalStorageActor : ReceiveActor { private readonly IServiceProvider serviceProvider; private readonly IServiceScope scope; - private readonly MyLogger logger; + private readonly MyLogger logger; private readonly FileStorageService storage; private DateTime? cacheTime { get; set; } = null; @@ -20,7 +21,7 @@ public class LocalStorageActor : IStorageActor { serviceProvider = serviceProviderArg; scope = serviceProvider.CreateScope(); - logger = scope.ServiceProvider.GetRequiredService>(); + logger = scope.ServiceProvider.GetRequiredService>(); storage = scope.ServiceProvider.GetRequiredService(); Receive(m => diff --git a/Management/Services/AkkaService.cs b/Management/Services/AkkaService.cs index 5186f85..d5616e3 100644 --- a/Management/Services/AkkaService.cs +++ b/Management/Services/AkkaService.cs @@ -18,7 +18,7 @@ public class AkkaService( private readonly IConfiguration configuration = configuration; private readonly IServiceProvider serviceProvider = serviceProvider; private readonly IHostApplicationLifetime applicationLifetime = appLifetime; - public IActorRef? CanvasQueueActor { get; private set; } + public IActorRef? CoursePlannerActor { get; private set; } public IActorRef? StorageActor { get; private set; } public Task StartAsync(CancellationToken cancellationToken) @@ -30,8 +30,8 @@ public class AkkaService( actorSystem = ActorSystem.Create("canavas-management-actor-system", mergedSystemSetup); - var canvasQueueProps = DependencyResolver.For(actorSystem).Props(); - CanvasQueueActor = actorSystem.ActorOf(canvasQueueProps, "canvasQueue"); + var canvasQueueProps = DependencyResolver.For(actorSystem).Props(); + CoursePlannerActor = actorSystem.ActorOf(canvasQueueProps, "canvasQueue"); var localStorageProps = DependencyResolver.For(actorSystem).Props(); StorageActor = actorSystem.ActorOf(localStorageProps, "localStorage");