got basic question and answer creation from canvas

This commit is contained in:
2023-08-17 18:50:59 -06:00
parent 4fb257e000
commit 28ad344018
18 changed files with 604 additions and 204 deletions

View File

@@ -6,6 +6,7 @@ using CanvasModel.Assignments;
using CanvasModel.Modules;
using Management.Services.Canvas;
using System.Text.RegularExpressions;
using CanvasModel.Quizzes;
namespace Management.Planner;
@@ -54,7 +55,7 @@ public class CoursePlanner
private void saveCourseToFile(LocalCourse courseAsOfDebounce)
{
_debounceTimer?.Dispose();
// ignore initial load of course
if (LocalCourse == null)
{
@@ -71,6 +72,7 @@ public class CoursePlanner
public event Action? StateHasChanged;
public IEnumerable<CanvasAssignment>? CanvasAssignments { get; internal set; }
public IEnumerable<CanvasQuiz>? CanvasQuizzes { get; internal set; }
public IEnumerable<CanvasModule>? CanvasModules { get; internal set; }
public Dictionary<ulong, IEnumerable<CanvasModuleItem>>? CanvasModulesItems { get; internal set; }
@@ -87,13 +89,14 @@ public class CoursePlanner
LocalCourse?.CanvasId ?? throw new Exception("no canvas id found for selected course");
var assignmentsTask = canvas.Assignments.GetAll(canvasId);
var quizzesTask = canvas.Quizzes.GetAll(canvasId);
var modulesTask = canvas.GetModules(canvasId);
CanvasAssignments = await assignmentsTask;
CanvasQuizzes = await quizzesTask;
CanvasModules = await modulesTask;
CanvasModulesItems = await canvas.GetAllModulesItems(canvasId, CanvasModules);
// Console.WriteLine(JsonSerializer.Serialize(CanvasModulesItems));
LoadingCanvasData = false;
StateHasChanged?.Invoke();
@@ -107,6 +110,7 @@ public class CoursePlanner
|| LocalCourse.CanvasId == null
|| CanvasAssignments == null
|| CanvasModules == null
|| CanvasQuizzes == null
)
return;
@@ -138,9 +142,9 @@ public class CoursePlanner
LocalCourse = await LocalCourse.SyncAssignmentsWithCanvas(canvasId, CanvasAssignments, canvas);
CanvasAssignments = await canvas.Assignments.GetAll(canvasId);
LocalCourse = await LocalCourse.SyncQuizzesWithCanvas(canvasId, CanvasQuizzes, canvas);
await syncModuleItemsWithCanvas(canvasId);
await LocalCourse.SyncModuleItemsWithCanvas(canvasId, CanvasModulesItems, canvas);
CanvasModulesItems = await canvas.GetAllModulesItems(canvasId, CanvasModules);
LoadingCanvasData = false;
@@ -148,94 +152,6 @@ public class CoursePlanner
Console.WriteLine("done syncing with canvas\n");
}
private async Task syncModuleItemsWithCanvas(ulong canvasId)
{
if (LocalCourse == null)
throw new Exception("cannot sync modules without localcourse selected");
if (CanvasModulesItems == null)
throw new Exception("cannot sync modules with canvas if they are not loaded in the variable");
foreach (var localModule in LocalCourse.Modules)
{
var moduleCanvasId =
localModule.CanvasId
?? throw new Exception("cannot sync canvas modules items if module not synced with canvas");
bool anyUpdated = await ensureAllItemsCreated(canvasId, localModule, moduleCanvasId);
var canvasModuleItems = anyUpdated
? await canvas.GetModuleItems(canvasId, moduleCanvasId)
: CanvasModulesItems[moduleCanvasId];
await sortModuleItems(canvasId, localModule, moduleCanvasId, canvasModuleItems);
}
}
private async Task sortModuleItems(
ulong canvasId,
LocalModule localModule,
ulong moduleCanvasId,
IEnumerable<CanvasModuleItem> canvasModuleItems
)
{
var localItemsWithCorrectOrder = localModule.Assignments
.OrderBy(a => a.DueAt)
.Select((a, i) => (Assignment: a, Position: i + 1));
var canvasContentIdsByCurrentPosition =
canvasModuleItems.ToDictionary(item => item.Position, item => item.ContentId)
?? new Dictionary<int, ulong?>();
foreach (var (localAssignment, position) in localItemsWithCorrectOrder)
{
var itemIsInCorrectOrder =
canvasContentIdsByCurrentPosition.ContainsKey(position)
&& canvasContentIdsByCurrentPosition[position] == localAssignment.CanvasId;
var currentCanvasItem = canvasModuleItems.First(i => i.ContentId == localAssignment.CanvasId);
if (!itemIsInCorrectOrder)
{
await canvas.UpdateModuleItem(
canvasId,
moduleCanvasId,
currentCanvasItem with
{
Position = position
}
);
}
}
}
private async Task<bool> ensureAllItemsCreated(
ulong canvasId,
LocalModule localModule,
ulong moduleCanvasId
)
{
var anyUpdated = false;
foreach (var localAssignment in localModule.Assignments)
{
var canvasModuleItemContentIds = CanvasModulesItems[moduleCanvasId].Select(i => i.ContentId);
if (!canvasModuleItemContentIds.Contains(localAssignment.CanvasId))
{
var canvasAssignmentId =
localAssignment.CanvasId
?? throw new Exception("cannot create module item if assignment does not have canvas id");
await canvas.CreateModuleItem(
canvasId,
moduleCanvasId,
localAssignment.Name,
"Assignment",
canvasAssignmentId
);
anyUpdated = true;
}
}
return anyUpdated;
}
public void Clear()
{
LocalCourse = null;

View File

@@ -9,10 +9,9 @@ namespace Management.Planner;
public static partial class AssignmentSyncronizationExtensions
{
internal static async Task<LocalAssignment> SyncAssignmentToCanvas(
this LocalCourse localCourse,
ulong canvasId,
ulong canvasCourseId,
LocalAssignment localAssignment,
IEnumerable<CanvasAssignment> canvasAssignments,
CanvasService canvas
@@ -25,23 +24,41 @@ public static partial class AssignmentSyncronizationExtensions
localCourse.AssignmentTemplates
);
if (canvasAssignment != null)
{
var assignmentNeedsUpdates = localAssignment.NeedsUpdates(
return canvasAssignment != null
? await updateAssignmentIfNeeded(
localCourse,
canvasCourseId,
localAssignment,
canvasAssignments,
localCourse.AssignmentTemplates,
quiet: false
);
if (assignmentNeedsUpdates)
{
await canvas.Assignments.Update(courseId: canvasId, localAssignment, localHtmlDescription);
}
return localAssignment;
}
else
canvas,
localHtmlDescription
)
: await canvas.Assignments.Create(canvasCourseId, localAssignment, localHtmlDescription);
}
private static async Task<LocalAssignment> updateAssignmentIfNeeded(
LocalCourse localCourse,
ulong canvasCourseId,
LocalAssignment localAssignment,
IEnumerable<CanvasAssignment> canvasAssignments,
CanvasService canvas,
string localHtmlDescription
)
{
var assignmentNeedsUpdates = localAssignment.NeedsUpdates(
canvasAssignments,
localCourse.AssignmentTemplates,
quiet: false
);
if (assignmentNeedsUpdates)
{
return await canvas.Assignments.Create(canvasId, localAssignment, localHtmlDescription);
await canvas.Assignments.Update(
courseId: canvasCourseId,
localAssignment,
localHtmlDescription
);
}
return localAssignment;
}
public static bool NeedsUpdates(
@@ -168,7 +185,7 @@ public static partial class AssignmentSyncronizationExtensions
internal static async Task<LocalCourse> SyncAssignmentsWithCanvas(
this LocalCourse localCourse,
ulong canvasId,
ulong canvasCourseId,
IEnumerable<CanvasAssignment> canvasAssignments,
CanvasService canvas
)
@@ -176,7 +193,7 @@ public static partial class AssignmentSyncronizationExtensions
var moduleTasks = localCourse.Modules.Select(async m =>
{
var assignmentTasks = m.Assignments.Select(
(a) => localCourse.SyncAssignmentToCanvas(canvasId, a, canvasAssignments, canvas)
(a) => localCourse.SyncAssignmentToCanvas(canvasCourseId, a, canvasAssignments, canvas)
);
var assignments = await Task.WhenAll(assignmentTasks);
return m with { Assignments = assignments };

View File

@@ -69,4 +69,99 @@ public static partial class ModuleSyncronizationExtensions
})
};
}
internal static async Task SortModuleItems(
this LocalModule localModule,
ulong canvasId,
ulong moduleCanvasId,
IEnumerable<CanvasModuleItem> canvasModuleItems,
CanvasService canvas
)
{
var localItemsWithCorrectOrder = localModule.Assignments
.OrderBy(a => a.DueAt)
.Select((a, i) => (Assignment: a, Position: i + 1));
var canvasContentIdsByCurrentPosition =
canvasModuleItems.ToDictionary(item => item.Position, item => item.ContentId)
?? new Dictionary<int, ulong?>();
foreach (var (localAssignment, position) in localItemsWithCorrectOrder)
{
var itemIsInCorrectOrder =
canvasContentIdsByCurrentPosition.ContainsKey(position)
&& canvasContentIdsByCurrentPosition[position] == localAssignment.CanvasId;
var currentCanvasItem = canvasModuleItems.First(i => i.ContentId == localAssignment.CanvasId);
if (!itemIsInCorrectOrder)
{
await canvas.UpdateModuleItem(
canvasId,
moduleCanvasId,
currentCanvasItem with
{
Position = position
}
);
}
}
}
internal static async Task<bool> EnsureAllModulesItemsCreated(
this LocalModule localModule,
ulong canvasId,
ulong moduleCanvasId,
Dictionary<ulong, IEnumerable<CanvasModuleItem>> canvasModulesItems,
CanvasService canvas
)
{
var anyUpdated = false;
foreach (var localAssignment in localModule.Assignments)
{
var canvasModuleItemContentIds = canvasModulesItems[moduleCanvasId].Select(i => i.ContentId);
if (!canvasModuleItemContentIds.Contains(localAssignment.CanvasId))
{
var canvasAssignmentId =
localAssignment.CanvasId
?? throw new Exception("cannot create module item if assignment does not have canvas id");
await canvas.CreateModuleItem(
canvasId,
moduleCanvasId,
localAssignment.Name,
"Assignment",
canvasAssignmentId
);
anyUpdated = true;
}
}
return anyUpdated;
}
internal static async Task SyncModuleItemsWithCanvas(
this LocalCourse localCourse,
ulong canvasId,
Dictionary<ulong, IEnumerable<CanvasModuleItem>> canvasModulesItems,
CanvasService canvas
)
{
foreach (var localModule in localCourse.Modules)
{
var moduleCanvasId =
localModule.CanvasId
?? throw new Exception("cannot sync canvas modules items if module not synced with canvas");
bool anyUpdated = await localModule.EnsureAllModulesItemsCreated(
canvasId,
moduleCanvasId,
canvasModulesItems,
canvas
);
var canvasModuleItems = anyUpdated
? await canvas.GetModuleItems(canvasId, moduleCanvasId)
: canvasModulesItems[moduleCanvasId];
await localModule.SortModuleItems(canvasId, moduleCanvasId, canvasModuleItems, canvas);
}
}
}

View File

@@ -9,16 +9,9 @@ namespace Management.Planner;
public static partial class QuizSyncronizationExtensions
{
internal static async Task<LocalQuiz> SyncQuizToCanvas(
this LocalCourse localCourse,
ulong canvasId,
LocalQuiz localQuiz,
IEnumerable<CanvasQuiz> canvasQuizzes,
CanvasService canvas
)
public static bool QuizIsCreated(this LocalQuiz localQuiz, IEnumerable<CanvasQuiz> canvasQuizzes)
{
// TODO actually sync
return localQuiz;
return canvasQuizzes.Any(q => q.Id == localQuiz.CanvasId);
}
internal static async Task<LocalCourse> SyncQuizzesWithCanvas(
@@ -38,6 +31,28 @@ public static partial class QuizSyncronizationExtensions
});
var modules = await Task.WhenAll(moduleTasks);
return localCourse;
return localCourse with { Modules = modules };
}
internal static async Task<LocalQuiz> SyncQuizToCanvas(
this LocalCourse localCourse,
ulong canvasCourseId,
LocalQuiz localQuiz,
IEnumerable<CanvasQuiz> canvasQuizzes,
CanvasService canvas
)
{
var isCreated = localQuiz.QuizIsCreated(canvasQuizzes);
if (isCreated)
{
// TODO write update
}
else
{
return await canvas.Quizzes.Create(canvasCourseId, localQuiz);
}
return localQuiz;
}
}