diff --git a/Management.Web/Pages/Index.razor b/Management.Web/Pages/Index.razor
index 69a572a..5cd9450 100644
--- a/Management.Web/Pages/Index.razor
+++ b/Management.Web/Pages/Index.razor
@@ -84,6 +84,11 @@
>
Sync With Canvas
+
+ @if(planner.LoadingCanvasData)
+ {
+
+ }
}
diff --git a/Management.Web/Program.cs b/Management.Web/Program.cs
index 47f19cc..054e707 100644
--- a/Management.Web/Program.cs
+++ b/Management.Web/Program.cs
@@ -1,6 +1,7 @@
global using System.Text.Json.Serialization;
global using System.Text.Json;
global using System.ComponentModel.DataAnnotations;
+global using Management.Services.Canvas;
global using CanvasModel.EnrollmentTerms;
global using CanvasModel.Courses;
global using CanvasModel;
@@ -19,8 +20,12 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
+
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/Course/CourseDetails.razor b/Management.Web/Shared/Course/CourseDetails.razor
index fe7f1ca..bd5108f 100644
--- a/Management.Web/Shared/Course/CourseDetails.razor
+++ b/Management.Web/Shared/Course/CourseDetails.razor
@@ -14,19 +14,24 @@
}
protected override async Task OnInitializedAsync()
{
- if(
- planner.CanvasAssignments == null
- && planner.LocalCourse != null
- && planner.LocalCourse.CanvasId != null
- )
- {
- var canvasId = planner.LocalCourse.CanvasId ?? throw new Exception("no canvas id found for selected course");
- planner.CanvasAssignments = await canvas.GetAssignments(canvasId);
- planner.CanvasModules = await canvas.GetModules(canvasId);
- System.Console.WriteLine(JsonSerializer.Serialize(planner.CanvasAssignments));
- }
- await base.OnInitializedAsync();
}
+ protected override async Task OnAfterRenderAsync(bool firstRender)
+ {
+ if(firstRender)
+ {
+ if(
+ planner.CanvasAssignments == null
+ && planner.LocalCourse != null
+ && planner.LocalCourse.CanvasId != null
+ )
+ {
+ await planner.LoadCanvasData();
+ }
+
+ }
+ }
+
+
private void reload()
{
diff --git a/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor b/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor
index bdda72c..01eb365 100644
--- a/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor
+++ b/Management.Web/Shared/Module/Assignment/AssignmentDetails.razor
@@ -140,7 +140,19 @@
@if(isSyncedWithCanvas)
{
- Synced With Canvas
+ @if(planner.LocalCourse != null
+ && planner.LocalCourse.CanvasId != null
+ && planner.CanvasAssignments != null
+ && planner.CanvasModules != null
+ && planner.AssignmentNeedsUpdates(Assignment)
+ )
+ {
+ need to update canvas
+ }
+ else
+ {
+ Canvas is up to date
+ }
}
else
{
diff --git a/Management/Features/Configuration/CoursePlanner.cs b/Management/Features/Configuration/CoursePlanner.cs
index 3d17cc6..483fd59 100644
--- a/Management/Features/Configuration/CoursePlanner.cs
+++ b/Management/Features/Configuration/CoursePlanner.cs
@@ -4,11 +4,14 @@ using CanvasModel;
using LocalModels;
using CanvasModel.Assignments;
using CanvasModel.Modules;
+using Management.Services.Canvas;
+using System.Text.RegularExpressions;
public class CoursePlanner
{
private readonly YamlManager yamlManager;
private readonly CanvasService canvas;
+ public bool LoadingCanvasData { get; internal set; } = false;
public CoursePlanner(YamlManager yamlManager, CanvasService canvas)
{
@@ -29,7 +32,7 @@ public class CoursePlanner
return;
}
- var verifiedCourse = verifyCourse(value);
+ var verifiedCourse = cleanupCourse(value);
// ignore initial load of course
if (_localCourse != null)
{
@@ -41,7 +44,7 @@ public class CoursePlanner
}
public event Action? StateHasChanged;
- private LocalCourse verifyCourse(LocalCourse incomingCourse)
+ private LocalCourse cleanupCourse(LocalCourse incomingCourse)
{
var modulesWithUniqueAssignments = incomingCourse.Modules.Select(
module => module with { Assignments = module.Assignments.DistinctBy(a => a.id) }
@@ -53,8 +56,42 @@ public class CoursePlanner
};
}
- public IEnumerable? CanvasAssignments { get; set; } = null;
- public IEnumerable? CanvasModules { get; set; } = null;
+ private IEnumerable? canvasAssignments = null;
+
+ public IEnumerable? CanvasAssignments
+ {
+ get => canvasAssignments;
+ set
+ {
+ canvasAssignments = value;
+ StateHasChanged?.Invoke();
+ }
+ }
+ private IEnumerable? canvasModules = null;
+ public IEnumerable? CanvasModules
+ {
+ get => canvasModules;
+ set
+ {
+ canvasModules = value;
+ StateHasChanged?.Invoke();
+ }
+ }
+
+ public async Task LoadCanvasData()
+ {
+ LoadingCanvasData = true;
+ StateHasChanged?.Invoke();
+
+ Thread.Sleep(1000);
+ var canvasId =
+ LocalCourse?.CanvasId ?? throw new Exception("no canvas id found for selected course");
+ CanvasAssignments = await canvas.Assignments.GetAll(canvasId);
+ CanvasModules = await canvas.GetModules(canvasId);
+
+ LoadingCanvasData = false;
+ StateHasChanged?.Invoke();
+ }
public async Task SyncWithCanvas()
{
@@ -66,12 +103,18 @@ public class CoursePlanner
)
return;
+ LoadingCanvasData = true;
+ StateHasChanged?.Invoke();
+
var canvasId =
LocalCourse.CanvasId ?? throw new Exception("no course canvas id to sync with canvas");
await ensureAllModulesCreated(canvasId);
await reloadModules_UpdateLocalModulesWithNewId(canvasId);
await ensureAllAssignmentsCreated_updateIds(canvasId);
+
+ LoadingCanvasData = false;
+ StateHasChanged?.Invoke();
}
private async Task reloadModules_UpdateLocalModulesWithNewId(ulong canvasId)
@@ -139,21 +182,121 @@ public class CoursePlanner
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 = await canvas.CreateAssignment(
- courseId: canvasId,
- name: localAssignment.name,
- submissionTypes: localAssignment.submission_types,
- description: localAssignment.description,
- dueAt: localAssignment.due_at,
- lockAt: localAssignment.lock_at,
- pointsPossible: localAssignment.points_possible
+ var canvasAssignment = CanvasAssignments.FirstOrDefault(
+ ca => ca.Id == localAssignment.canvasId
+ );
+ string localHtmlDescription = getAssignmentDescriptionHtml(localAssignment);
+
+ if (canvasAssignment != null)
+ {
+ var assignmentNeedsUpdates = AssignmentNeedsUpdates(localAssignment);
+ if (assignmentNeedsUpdates)
+ {
+ await canvas.Assignments.Update(courseId: canvasId, localAssignment, localHtmlDescription);
+ }
+ return localAssignment;
+ }
+ else
+ {
+ var createdAssignment = await canvas.Assignments.Create(
+ courseId: canvasId,
+ name: localAssignment.name,
+ submissionTypes: localAssignment.submission_types,
+ description: localHtmlDescription,
+ dueAt: localAssignment.due_at,
+ lockAt: localAssignment.lock_at,
+ pointsPossible: localAssignment.points_possible
+ );
+
+ return localAssignment with
+ {
+ canvasId = createdAssignment.Id
+ };
+ }
+ }
+
+ private string getAssignmentDescriptionHtml(LocalAssignment localAssignment)
+ {
+ if (LocalCourse == null)
+ throw new Exception(
+ "cannot get assignment description if local course is null or other values not set"
+ );
+ return localAssignment.use_template
+ ? AssignmentTemplate.GetHtml(
+ LocalCourse.AssignmentTemplates.First(t => t.Id == localAssignment.template_id),
+ localAssignment
+ )
+ : Markdig.Markdown.ToHtml(localAssignment.description);
+ }
+
+ public bool AssignmentNeedsUpdates(LocalAssignment localAssignment)
+ {
+ 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 = getAssignmentDescriptionHtml(localAssignment);
+
+ 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())
);
- return localAssignment with
+ if (!dueDatesSame)
+ Console.WriteLine(
+ $"Due dates different for {localAssignment.name}, local: {localAssignment.due_at}, in canvas {canvasAssignment.DueAt}"
+ );
+
+ if (!descriptionSame)
{
- canvasId = canvasAssignment.Id
- };
+ 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;
}
public void Clear()
diff --git a/Management/Models/Local/LocalAssignment.cs b/Management/Models/Local/LocalAssignment.cs
index 6393974..cd86d00 100644
--- a/Management/Models/Local/LocalAssignment.cs
+++ b/Management/Models/Local/LocalAssignment.cs
@@ -1,3 +1,5 @@
+using LocalModels;
+
public record RubricItem
{
public static readonly string extraCredit = "(Extra Credit) ";
diff --git a/Management/Services/Canvas/CanvasAssignmentService.cs b/Management/Services/Canvas/CanvasAssignmentService.cs
new file mode 100644
index 0000000..eaa914e
--- /dev/null
+++ b/Management/Services/Canvas/CanvasAssignmentService.cs
@@ -0,0 +1,89 @@
+using CanvasModel.Assignments;
+using RestSharp;
+
+namespace Management.Services.Canvas;
+
+public class CanvasAssignmentService
+{
+ private IWebRequestor webRequestor;
+ private readonly CanvasServiceUtils utils;
+
+ public CanvasAssignmentService(IWebRequestor webRequestor, CanvasServiceUtils utils)
+ {
+ this.webRequestor = webRequestor;
+ this.utils = utils;
+ }
+
+ public async Task> GetAll(ulong courseId)
+ {
+ var url = $"courses/{courseId}/assignments";
+ var request = new RestRequest(url);
+ var assignmentResponse = await utils.PaginatedRequest>(request);
+ return assignmentResponse.SelectMany(
+ assignments =>
+ assignments.Select(
+ a =>
+ a with
+ {
+ DueAt = a.DueAt?.ToLocalTime(),
+ LockAt = a.LockAt?.ToLocalTime()
+ }
+ )
+ );
+ }
+
+ public async Task Create(
+ ulong courseId,
+ string name,
+ IEnumerable submissionTypes,
+ string? description,
+ DateTime? dueAt,
+ DateTime? lockAt,
+ int? pointsPossible
+ )
+ {
+ System.Console.WriteLine($"creating assignment: {name}");
+ var url = $"courses/{courseId}/assignments";
+ var request = new RestRequest(url);
+ var body = new CanvasAssignmentCreationRequest()
+ {
+ name = name,
+ submission_types = submissionTypes.Select(t => t.ToString()),
+ description = description ?? "",
+ due_at = dueAt,
+ lock_at = lockAt,
+ points_possible = pointsPossible ?? 0
+ };
+ request.AddHeader("Content-Type", "application/json");
+ var bodyObj = new { assignment = body };
+ request.AddBody(bodyObj);
+ var (canvasAssignment, response) = await webRequestor.PostAsync(request);
+ if (canvasAssignment == null)
+ throw new Exception("created canvas assignment was null");
+ return canvasAssignment with
+ {
+ DueAt = canvasAssignment.DueAt?.ToLocalTime(),
+ LockAt = canvasAssignment.LockAt?.ToLocalTime()
+ };
+ }
+
+ public async Task Update(ulong courseId, LocalAssignment localAssignment, string htmlDescription)
+ {
+ System.Console.WriteLine($"updating assignment: {localAssignment.name}");
+ var url = $"courses/{courseId}/assignments/{localAssignment.canvasId}";
+ var request = new RestRequest(url);
+ var body = new CanvasAssignmentCreationRequest()
+ {
+ name = localAssignment.name,
+ submission_types = localAssignment.submission_types.Select(t => t.ToString()),
+ description = htmlDescription,
+ due_at = localAssignment.due_at,
+ lock_at = localAssignment.lock_at,
+ points_possible = localAssignment.points_possible
+ };
+ request.AddHeader("Content-Type", "application/json");
+ var bodyObj = new { assignment = body };
+ request.AddBody(bodyObj);
+ await webRequestor.PutAsync(request);
+ }
+}
diff --git a/Management/Services/CanvasRequests/CanvasAssignmentCreationRequest.cs b/Management/Services/Canvas/CanvasRequests/CanvasAssignmentCreationRequest.cs
similarity index 89%
rename from Management/Services/CanvasRequests/CanvasAssignmentCreationRequest.cs
rename to Management/Services/Canvas/CanvasRequests/CanvasAssignmentCreationRequest.cs
index 1f37595..66743a9 100644
--- a/Management/Services/CanvasRequests/CanvasAssignmentCreationRequest.cs
+++ b/Management/Services/Canvas/CanvasRequests/CanvasAssignmentCreationRequest.cs
@@ -1,3 +1,6 @@
+
+namespace Management.Services.Canvas;
+
public record CanvasAssignmentCreationRequest
{
public string? name { get; set; }
diff --git a/Management/Services/Canvas/CanvasService.cs b/Management/Services/Canvas/CanvasService.cs
new file mode 100644
index 0000000..28f85eb
--- /dev/null
+++ b/Management/Services/Canvas/CanvasService.cs
@@ -0,0 +1,93 @@
+using CanvasModel;
+using CanvasModel.Assignments;
+using CanvasModel.Courses;
+using CanvasModel.EnrollmentTerms;
+using CanvasModel.Modules;
+using RestSharp;
+namespace Management.Services.Canvas;
+
+public class CanvasService
+{
+ private readonly IWebRequestor webRequestor;
+ private readonly CanvasServiceUtils utils;
+
+ public CanvasAssignmentService Assignments { get; }
+
+ public CanvasService(
+ IWebRequestor webRequestor,
+ CanvasServiceUtils utils,
+ CanvasAssignmentService Assignments
+ )
+ {
+ this.webRequestor = webRequestor;
+ this.utils = utils;
+ this.Assignments = Assignments;
+ }
+
+ public async Task> GetTerms()
+ {
+ var url = $"accounts/10/terms";
+
+ var request = new RestRequest(url);
+ var termResponses = await utils.PaginatedRequest(request);
+ var terms = termResponses.Select(r => r.EnrollmentTerms).SelectMany(s => s).ToArray();
+ return terms;
+ }
+
+ public async Task> GetCourses(ulong termId)
+ {
+ var url = $"courses";
+ var request = new RestRequest(url);
+ var coursesResponse = await utils.PaginatedRequest>(request);
+ return coursesResponse.SelectMany(c => c).Where(c => c.EnrollmentTermId == termId).ToArray();
+ }
+
+ public async Task GetCourse(ulong courseId)
+ {
+ var url = $"courses/{courseId}";
+ var request = new RestRequest(url);
+ var (data, response) = await webRequestor.GetAsync(request);
+
+ if (data == null)
+ {
+ System.Console.WriteLine(response.Content);
+ System.Console.WriteLine(response.ResponseUri);
+ throw new Exception("error getting course from canvas");
+ }
+ 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);
+ request.AddParameter("module[name]", name);
+
+ await webRequestor.PostAsync(request);
+ }
+
+ public async Task> GetCurrentTermsFor(
+ DateTime? _queryDate = null
+ )
+ {
+ DateTime queryDate = _queryDate ?? DateTime.Now;
+
+ var terms = await GetTerms();
+
+ var currentTerms = terms
+ .Where(t => t.EndAt != null && t.EndAt > queryDate && t.EndAt < queryDate.AddYears(1))
+ .Take(3)
+ .OrderBy(t => t.StartAt);
+
+ return currentTerms;
+ }
+}
diff --git a/Management/Services/Canvas/CanvasServiceUtils.cs b/Management/Services/Canvas/CanvasServiceUtils.cs
new file mode 100644
index 0000000..1a40e20
--- /dev/null
+++ b/Management/Services/Canvas/CanvasServiceUtils.cs
@@ -0,0 +1,58 @@
+using RestSharp;
+
+namespace Management.Services.Canvas;
+public class CanvasServiceUtils
+{
+ private const string BaseUrl = "https://snow.instructure.com/api/v1/";
+ private readonly IWebRequestor webRequestor;
+ public CanvasServiceUtils(IWebRequestor webRequestor)
+ {
+ this.webRequestor = webRequestor;
+ }
+
+ internal async Task> PaginatedRequest(RestRequest request)
+ {
+ var requestCount = 1;
+ request.AddQueryParameter("per_page", "100");
+ var (data, response) = await webRequestor.GetAsync(request);
+
+ if (response.ErrorMessage?.Length > 0)
+ {
+ System.Console.WriteLine("error in response");
+ System.Console.WriteLine(response.ErrorMessage);
+ throw new Exception("error in response");
+ }
+
+ var returnData = data != null ? new T[] { data } : new T[] { };
+ var nextUrl = getNextUrl(response.Headers);
+
+ while (nextUrl is not null)
+ {
+ requestCount += 1;
+ RestRequest nextRequest = new RestRequest(nextUrl);
+ var (nextData, nextResponse) = await webRequestor.GetAsync(nextRequest);
+ if (nextData is not null)
+ returnData = returnData.Append(nextData).ToArray();
+ nextUrl = getNextUrl(nextResponse.Headers);
+ }
+
+ System.Console.WriteLine($"Requesting {typeof(T)} took {requestCount} requests");
+
+ return returnData;
+ }
+
+ protected static string? getNextUrl(IEnumerable? headers) =>
+ headers
+ ?.ToList()
+ .Find(h => h.Name == "Link")
+ ?.Value?.ToString()
+ ?.Split(",")
+ .Where(url => url.Contains("rel=\"next\""))
+ .FirstOrDefault()
+ ?.Split(";")
+ .FirstOrDefault()
+ ?.TrimEnd('>')
+ .TrimStart('<')
+ .Replace(" ", "")
+ .Replace(BaseUrl, "");
+}
\ No newline at end of file
diff --git a/Management/Services/CanvasService.cs b/Management/Services/CanvasService.cs
deleted file mode 100644
index 2ef08c8..0000000
--- a/Management/Services/CanvasService.cs
+++ /dev/null
@@ -1,175 +0,0 @@
-using CanvasModel;
-using CanvasModel.Assignments;
-using CanvasModel.Courses;
-using CanvasModel.EnrollmentTerms;
-using CanvasModel.Modules;
-using RestSharp;
-
-public interface ICanvasService
-{
- Task> GetCurrentTermsFor(DateTime? _queryDate = null);
- Task> GetTerms();
-}
-
-public class CanvasService : ICanvasService
-{
- private const string BaseUrl = "https://snow.instructure.com/api/v1/";
- private readonly IWebRequestor webRequestor;
-
- public CanvasService(IWebRequestor webRequestor)
- {
- this.webRequestor = webRequestor;
- }
-
- public async Task> GetTerms()
- {
- var url = $"accounts/10/terms";
-
- var request = new RestRequest(url);
- var termResponses = await PaginatedRequest(request);
- var terms = termResponses.Select(r => r.EnrollmentTerms).SelectMany(s => s).ToArray();
- return terms;
- }
-
- public async Task> GetCourses(ulong termId)
- {
- var url = $"courses";
- var request = new RestRequest(url);
- var coursesResponse = await PaginatedRequest>(request);
- return coursesResponse.SelectMany(c => c).Where(c => c.EnrollmentTermId == termId).ToArray();
- }
-
- public async Task GetCourse(ulong courseId)
- {
- var url = $"courses/{courseId}";
- var request = new RestRequest(url);
- var (data, response) = await webRequestor.GetAsync(request);
-
- if (data == null)
- {
- System.Console.WriteLine(response.Content);
- System.Console.WriteLine(response.ResponseUri);
- throw new Exception("error getting course from canvas");
- }
- return data;
- }
-
- public async Task> GetAssignments(ulong courseId)
- {
- var url = $"courses/{courseId}/assignments";
- var request = new RestRequest(url);
- var assignmentResponse = await PaginatedRequest>(request);
- return assignmentResponse.SelectMany(c => c);
- }
-
- public async Task CreateAssignment(
- ulong courseId,
- string name,
- IEnumerable submissionTypes,
- string? description,
- DateTime? dueAt,
- DateTime? lockAt,
- int? pointsPossible
- )
- {
- System.Console.WriteLine($"creating assignment: {name}");
- var url = $"courses/{courseId}/assignments";
- var request = new RestRequest(url);
- var body = new CanvasAssignmentCreationRequest()
- {
- name = name,
- submission_types = submissionTypes.Select(t => t.ToString()),
- description = description,
- due_at = dueAt,
- lock_at = lockAt,
- points_possible = pointsPossible
- };
- request.AddHeader("Content-Type", "application/json");
- var bodyObj = new { assignment = body };
- request.AddBody(bodyObj);
- var (canvasAssignment, response) = await webRequestor.PostAsync(request);
- if (canvasAssignment == null)
- throw new Exception("created canvas assignment was null");
- return canvasAssignment;
- }
-
- public async Task> GetModules(ulong courseId)
- {
- var url = $"courses/{courseId}/modules";
- var request = new RestRequest(url);
- var modules = await 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);
- request.AddParameter("module[name]", name);
-
- await webRequestor.PostAsync(request);
- }
-
- private async Task> PaginatedRequest(RestRequest request)
- {
- var requestCount = 1;
- request.AddQueryParameter("per_page", "100");
- var (data, response) = await webRequestor.GetAsync(request);
-
- if (response.ErrorMessage?.Length > 0)
- {
- System.Console.WriteLine("error in response");
- System.Console.WriteLine(response.ErrorMessage);
- throw new Exception("error in response");
- }
-
- var returnData = data != null ? new T[] { data } : new T[] { };
- var nextUrl = getNextUrl(response.Headers);
-
- while (nextUrl is not null)
- {
- requestCount += 1;
- RestRequest nextRequest = new RestRequest(nextUrl);
- var (nextData, nextResponse) = await webRequestor.GetAsync(nextRequest);
- if (nextData is not null)
- returnData = returnData.Append(nextData).ToArray();
- nextUrl = getNextUrl(nextResponse.Headers);
- }
-
- System.Console.WriteLine($"Requesting {typeof(T)} took {requestCount} requests");
-
- return returnData;
- }
-
- private static string? getNextUrl(IEnumerable? headers) =>
- headers
- ?.ToList()
- .Find(h => h.Name == "Link")
- ?.Value?.ToString()
- ?.Split(",")
- .Where(url => url.Contains("rel=\"next\""))
- .FirstOrDefault()
- ?.Split(";")
- .FirstOrDefault()
- ?.TrimEnd('>')
- .TrimStart('<')
- .Replace(" ", "")
- .Replace(BaseUrl, "");
-
- public async Task> GetCurrentTermsFor(
- DateTime? _queryDate = null
- )
- {
- DateTime queryDate = _queryDate ?? DateTime.Now;
-
- var terms = await GetTerms();
-
- var currentTerms = terms
- .Where(t => t.EndAt != null && t.EndAt > queryDate && t.EndAt < queryDate.AddYears(1))
- .Take(3)
- .OrderBy(t => t.StartAt);
-
- return currentTerms;
- }
-}
diff --git a/Management/Services/IWebRequestor.cs b/Management/Services/IWebRequestor.cs
index 7523348..9a36444 100644
--- a/Management/Services/IWebRequestor.cs
+++ b/Management/Services/IWebRequestor.cs
@@ -6,4 +6,6 @@ public interface IWebRequestor
Task<(T?, RestResponse)> GetAsync(RestRequest request);
Task PostAsync(RestRequest request);
Task<(T?, RestResponse)> PostAsync(RestRequest request);
+ Task PutAsync(RestRequest request);
+ Task<(T?, RestResponse)> PutAsync(RestRequest request);
}
diff --git a/Management/Services/WebRequestor.cs b/Management/Services/WebRequestor.cs
index 3eb3c8d..85c22a0 100644
--- a/Management/Services/WebRequestor.cs
+++ b/Management/Services/WebRequestor.cs
@@ -46,7 +46,26 @@ public class WebRequestor : IWebRequestor
return (Deserialize(response), response);
}
- public T? Deserialize(RestResponse response)
+ public async Task PutAsync(RestRequest request)
+ {
+ var response = await client.ExecutePutAsync(request);
+ if (!response.IsSuccessful)
+ {
+ System.Console.WriteLine(response.Content);
+ System.Console.WriteLine(response.ResponseUri);
+ System.Console.WriteLine("error with response");
+ throw new Exception("error with response");
+ }
+ return response;
+ }
+
+ public async Task<(T?, RestResponse)> PutAsync(RestRequest request)
+ {
+ var response = await client.ExecutePutAsync(request);
+ return (Deserialize(response), response);
+ }
+
+ private T? Deserialize(RestResponse response)
{
if (!response.IsSuccessful)
{