mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
hooks
This commit is contained in:
@@ -26,4 +26,4 @@ public class DeserializationTests
|
|||||||
result.Should().NotBeNull();
|
result.Should().NotBeNull();
|
||||||
result?.EnrollmentTerms?.First().Id.Should().Be(1);
|
result?.EnrollmentTerms?.First().Id.Should().Be(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,4 +42,4 @@ public class CalendarMonthTests
|
|||||||
|
|
||||||
month.Weeks.Last().Should().BeEquivalentTo(expectedLastWeek);
|
month.Weeks.Last().Should().BeEquivalentTo(expectedLastWeek);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,4 +23,4 @@
|
|||||||
// config!.EndDate.Should().Be(endAt);
|
// config!.EndDate.Should().Be(endAt);
|
||||||
// config!.Days.Should().BeEquivalentTo(daysOfWeek);
|
// config!.Days.Should().BeEquivalentTo(daysOfWeek);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -37,4 +37,4 @@
|
|||||||
// manager.Modules.Count().Should().Be(4);
|
// manager.Modules.Count().Should().Be(4);
|
||||||
// manager.Modules.ElementAt(3).Assignments.Count().Should().Be(1);
|
// manager.Modules.ElementAt(3).Assignments.Count().Should().Be(1);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -94,4 +94,4 @@
|
|||||||
// var semester = new SemesterPlanner(config);
|
// var semester = new SemesterPlanner(config);
|
||||||
// semester.Days.Should().BeEquivalentTo(days);
|
// semester.Days.Should().BeEquivalentTo(days);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
var assignment = new LocalAssignment()
|
var assignment = new LocalAssignment()
|
||||||
{
|
{
|
||||||
Name="test assignment",
|
Name = "test assignment",
|
||||||
Description ="here is the description",
|
Description = "here is the description",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
@@ -29,13 +29,13 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
var assignment = new LocalAssignment()
|
var assignment = new LocalAssignment()
|
||||||
{
|
{
|
||||||
Name="test assignment",
|
Name = "test assignment",
|
||||||
Description ="here is the description",
|
Description = "here is the description",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
LocalAssignmentGroupName = "Final Project",
|
LocalAssignmentGroupName = "Final Project",
|
||||||
Rubric = new List<RubricItem>() {}
|
Rubric = new List<RubricItem>() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
var assignmentMarkdown = assignment.ToMarkdown();
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
@@ -48,8 +48,8 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
var assignment = new LocalAssignment()
|
var assignment = new LocalAssignment()
|
||||||
{
|
{
|
||||||
Name="test assignment",
|
Name = "test assignment",
|
||||||
Description ="here is the description",
|
Description = "here is the description",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
SubmissionTypes = [],
|
SubmissionTypes = [],
|
||||||
@@ -71,8 +71,8 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
var assignment = new LocalAssignment()
|
var assignment = new LocalAssignment()
|
||||||
{
|
{
|
||||||
Name="test assignment",
|
Name = "test assignment",
|
||||||
Description ="here is the description",
|
Description = "here is the description",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = null,
|
LockAt = null,
|
||||||
SubmissionTypes = [],
|
SubmissionTypes = [],
|
||||||
@@ -94,7 +94,7 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
var assignment = new LocalAssignment()
|
var assignment = new LocalAssignment()
|
||||||
{
|
{
|
||||||
Name="test assignment",
|
Name = "test assignment",
|
||||||
Description = "",
|
Description = "",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
@@ -116,13 +116,14 @@ public class AssignmentMarkdownTests
|
|||||||
{
|
{
|
||||||
var assignment = new LocalAssignment()
|
var assignment = new LocalAssignment()
|
||||||
{
|
{
|
||||||
Name="test assignment",
|
Name = "test assignment",
|
||||||
Description = "test assignment\n---\nsomestuff",
|
Description = "test assignment\n---\nsomestuff",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
SubmissionTypes = [],
|
SubmissionTypes = [],
|
||||||
LocalAssignmentGroupName = "Final Project",
|
LocalAssignmentGroupName = "Final Project",
|
||||||
Rubric = new List<RubricItem>() {
|
Rubric = new List<RubricItem>()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -72,8 +72,10 @@ public class FileStorageTests
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task CourseSettings_CanBeSavedAndLoaded()
|
public async Task CourseSettings_CanBeSavedAndLoaded()
|
||||||
{
|
{
|
||||||
LocalCourse testCourse = new() {
|
LocalCourse testCourse = new()
|
||||||
Settings = new() {
|
{
|
||||||
|
Settings = new()
|
||||||
|
{
|
||||||
AssignmentGroups = [],
|
AssignmentGroups = [],
|
||||||
Name = "Test Course with settings",
|
Name = "Test Course with settings",
|
||||||
DaysOfWeek = [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
DaysOfWeek = [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
||||||
@@ -96,13 +98,15 @@ public class FileStorageTests
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task EmptyCourseModules_CanBeSavedAndLoaded()
|
public async Task EmptyCourseModules_CanBeSavedAndLoaded()
|
||||||
{
|
{
|
||||||
LocalCourse testCourse = new() {
|
LocalCourse testCourse = new()
|
||||||
|
{
|
||||||
Settings = new() { Name = "Test Course with modules" },
|
Settings = new() { Name = "Test Course with modules" },
|
||||||
Modules = [
|
Modules = [
|
||||||
new() {
|
new()
|
||||||
Name="test module 1",
|
{
|
||||||
Assignments= [],
|
Name = "test module 1",
|
||||||
Quizzes=[]
|
Assignments = [],
|
||||||
|
Quizzes = []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -118,26 +122,29 @@ public class FileStorageTests
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task CourseModules_WithAssignments_CanBeSavedAndLoaded()
|
public async Task CourseModules_WithAssignments_CanBeSavedAndLoaded()
|
||||||
{
|
{
|
||||||
LocalCourse testCourse = new() {
|
LocalCourse testCourse = new()
|
||||||
|
{
|
||||||
Settings = new() { Name = "Test Course with modules and assignments" },
|
Settings = new() { Name = "Test Course with modules and assignments" },
|
||||||
Modules = [
|
Modules = [
|
||||||
new() {
|
new()
|
||||||
Name="test module 1 with assignments",
|
{
|
||||||
Assignments=[
|
Name = "test module 1 with assignments",
|
||||||
new () {
|
Assignments = [
|
||||||
Name="test assignment",
|
new()
|
||||||
Description ="here is the description",
|
{
|
||||||
|
Name = "test assignment",
|
||||||
|
Description = "here is the description",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
LocalAssignmentGroupName = "Final Project",
|
LocalAssignmentGroupName = "Final Project",
|
||||||
Rubric = [
|
Rubric = [
|
||||||
new() {Points = 4, Label="do task 1"},
|
new() { Points = 4, Label = "do task 1" },
|
||||||
new() {Points = 2, Label="do task 2"},
|
new() { Points = 2, Label = "do task 2" },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
Quizzes=[]
|
Quizzes = []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -156,14 +163,17 @@ public class FileStorageTests
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task CourseModules_WithQuizzes_CanBeSavedAndLoaded()
|
public async Task CourseModules_WithQuizzes_CanBeSavedAndLoaded()
|
||||||
{
|
{
|
||||||
LocalCourse testCourse = new() {
|
LocalCourse testCourse = new()
|
||||||
|
{
|
||||||
Settings = new() { Name = "Test Course with modules and quiz" },
|
Settings = new() { Name = "Test Course with modules and quiz" },
|
||||||
Modules = [
|
Modules = [
|
||||||
new() {
|
new()
|
||||||
Name="test module 1 with quiz",
|
{
|
||||||
Assignments=[],
|
Name = "test module 1 with quiz",
|
||||||
Quizzes=[
|
Assignments = [],
|
||||||
new() {
|
Quizzes = [
|
||||||
|
new()
|
||||||
|
{
|
||||||
Name = "Test Quiz",
|
Name = "Test Quiz",
|
||||||
Description = "quiz description",
|
Description = "quiz description",
|
||||||
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
LockAt = new DateTime(2022, 10, 3, 12, 5, 0),
|
||||||
@@ -171,8 +181,9 @@ public class FileStorageTests
|
|||||||
ShuffleAnswers = true,
|
ShuffleAnswers = true,
|
||||||
OneQuestionAtATime = true,
|
OneQuestionAtATime = true,
|
||||||
LocalAssignmentGroupName = "Assignments",
|
LocalAssignmentGroupName = "Assignments",
|
||||||
Questions=[
|
Questions = [
|
||||||
new () {
|
new()
|
||||||
|
{
|
||||||
Text = "test essay",
|
Text = "test essay",
|
||||||
QuestionType = QuestionType.ESSAY,
|
QuestionType = QuestionType.ESSAY,
|
||||||
Points = 1
|
Points = 1
|
||||||
@@ -196,8 +207,10 @@ public class FileStorageTests
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task MarkdownStorage_FullyPopulated_DoesNotLoseData()
|
public async Task MarkdownStorage_FullyPopulated_DoesNotLoseData()
|
||||||
{
|
{
|
||||||
LocalCourse testCourse = new() {
|
LocalCourse testCourse = new()
|
||||||
Settings = new () {
|
{
|
||||||
|
Settings = new()
|
||||||
|
{
|
||||||
AssignmentGroups = [],
|
AssignmentGroups = [],
|
||||||
Name = "Test Course with lots of data",
|
Name = "Test Course with lots of data",
|
||||||
DaysOfWeek = [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
DaysOfWeek = [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
||||||
@@ -206,24 +219,27 @@ public class FileStorageTests
|
|||||||
DefaultDueTime = new() { Hour = 1, Minute = 59 },
|
DefaultDueTime = new() { Hour = 1, Minute = 59 },
|
||||||
},
|
},
|
||||||
Modules = [
|
Modules = [
|
||||||
new() {
|
new()
|
||||||
Name= "new test module",
|
{
|
||||||
|
Name = "new test module",
|
||||||
Assignments = [
|
Assignments = [
|
||||||
new() {
|
new()
|
||||||
Name="test assignment",
|
{
|
||||||
Description ="here is the description",
|
Name = "test assignment",
|
||||||
|
Description = "here is the description",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
SubmissionTypes = [AssignmentSubmissionType.ONLINE_UPLOAD],
|
||||||
LocalAssignmentGroupName = "Final Project",
|
LocalAssignmentGroupName = "Final Project",
|
||||||
Rubric = [
|
Rubric = [
|
||||||
new() { Points = 4, Label="do task 1" },
|
new() { Points = 4, Label = "do task 1" },
|
||||||
new() { Points = 2, Label="do task 2" },
|
new() { Points = 2, Label = "do task 2" },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
Quizzes = [
|
Quizzes = [
|
||||||
new() {
|
new()
|
||||||
|
{
|
||||||
Name = "Test Quiz",
|
Name = "Test Quiz",
|
||||||
Description = "quiz description",
|
Description = "quiz description",
|
||||||
LockAt = new DateTime(),
|
LockAt = new DateTime(),
|
||||||
@@ -233,7 +249,8 @@ public class FileStorageTests
|
|||||||
LocalAssignmentGroupName = "someId",
|
LocalAssignmentGroupName = "someId",
|
||||||
AllowedAttempts = -1,
|
AllowedAttempts = -1,
|
||||||
Questions = [
|
Questions = [
|
||||||
new() {
|
new()
|
||||||
|
{
|
||||||
Text = "test short answer",
|
Text = "test short answer",
|
||||||
QuestionType = QuestionType.SHORT_ANSWER,
|
QuestionType = QuestionType.SHORT_ANSWER,
|
||||||
Points = 1
|
Points = 1
|
||||||
@@ -257,8 +274,10 @@ public class FileStorageTests
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task MarkdownStorage_CanPersistPages()
|
public async Task MarkdownStorage_CanPersistPages()
|
||||||
{
|
{
|
||||||
LocalCourse testCourse = new() {
|
LocalCourse testCourse = new()
|
||||||
Settings = new () {
|
{
|
||||||
|
Settings = new()
|
||||||
|
{
|
||||||
AssignmentGroups = [],
|
AssignmentGroups = [],
|
||||||
Name = "Test Course with page",
|
Name = "Test Course with page",
|
||||||
DaysOfWeek = [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
DaysOfWeek = [DayOfWeek.Monday, DayOfWeek.Wednesday],
|
||||||
@@ -267,10 +286,12 @@ public class FileStorageTests
|
|||||||
DefaultDueTime = new() { Hour = 1, Minute = 59 },
|
DefaultDueTime = new() { Hour = 1, Minute = 59 },
|
||||||
},
|
},
|
||||||
Modules = [
|
Modules = [
|
||||||
new(){
|
new()
|
||||||
|
{
|
||||||
Name = "page test module",
|
Name = "page test module",
|
||||||
Pages = [
|
Pages = [
|
||||||
new () {
|
new()
|
||||||
|
{
|
||||||
Name = "test page persistence",
|
Name = "test page persistence",
|
||||||
DueAt = new DateTime(),
|
DueAt = new DateTime(),
|
||||||
Text = "this is some\n## markdown\n"
|
Text = "this is some\n## markdown\n"
|
||||||
|
|||||||
@@ -80,4 +80,4 @@ Match the following terms & definitions
|
|||||||
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz);
|
||||||
quiz.Questions.First().Answers.First().Text.Should().Be("statement");
|
quiz.Questions.First().Answers.First().Text.Should().Be("statement");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ oneline question
|
|||||||
";
|
";
|
||||||
markdown.Should().Contain(expectedQuestionString);
|
markdown.Should().Contain(expectedQuestionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CanParseQuestionWithMultipleAnswers()
|
public void CanParseQuestionWithMultipleAnswers()
|
||||||
{
|
{
|
||||||
@@ -80,4 +80,4 @@ Which events are triggered when the user clicks on an input field?
|
|||||||
firstQuestion.Answers.ElementAt(3).Text.Should().Be("submit");
|
firstQuestion.Answers.ElementAt(3).Text.Should().Be("submit");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ endline
|
|||||||
*) true
|
*) true
|
||||||
) false
|
) false
|
||||||
";
|
";
|
||||||
var question = LocalQuizQuestion.ParseMarkdown(questionMarkdown, 0);
|
var question = LocalQuizQuestion.ParseMarkdown(questionMarkdown, 0);
|
||||||
question.Answers.Count().Should().Be(2);
|
question.Answers.Count().Should().Be(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Which events are triggered when the user clicks on an input field?
|
|||||||
short_answer";
|
short_answer";
|
||||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void EssayQuestionToMarkdown_IsCorrect()
|
public void EssayQuestionToMarkdown_IsCorrect()
|
||||||
{
|
{
|
||||||
@@ -111,4 +111,4 @@ Which events are triggered when the user clicks on an input field?
|
|||||||
essay";
|
essay";
|
||||||
questionMarkdown.Should().Contain(expectedMarkdown);
|
questionMarkdown.Should().Contain(expectedMarkdown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class RubricMarkdownTests
|
|||||||
rubric.ElementAt(1).Label.Should().Be("this is the other task");
|
rubric.ElementAt(1).Label.Should().Be("this is the other task");
|
||||||
rubric.ElementAt(1).Points.Should().Be(3);
|
rubric.ElementAt(1).Points.Should().Be(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCanParseSinglePoint()
|
public void TestCanParseSinglePoint()
|
||||||
{
|
{
|
||||||
@@ -68,4 +68,4 @@ public class RubricMarkdownTests
|
|||||||
rubric.First().IsExtraCredit.Should().BeTrue();
|
rubric.First().IsExtraCredit.Should().BeTrue();
|
||||||
rubric.First().Label.Should().Be("(Extra Credit) this is the task");
|
rubric.First().Label.Should().Be("(Extra Credit) this is the task");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
// };
|
// };
|
||||||
// Mock<IWebRequestor> mockRequestor = getTermsMock(expectedTerms);
|
// Mock<IWebRequestor> mockRequestor = getTermsMock(expectedTerms);
|
||||||
// var service = new CanvasService(mockRequestor.Object);
|
// var service = new CanvasService(mockRequestor.Object);
|
||||||
|
|
||||||
// var queryDate = new DateTime(2022, 6, 1);
|
// var queryDate = new DateTime(2022, 6, 1);
|
||||||
// var canvasTerms = await service.GetCurrentTermsFor(queryDate);
|
// var canvasTerms = await service.GetCurrentTermsFor(queryDate);
|
||||||
|
|
||||||
@@ -83,4 +83,4 @@
|
|||||||
// return mockRequestor;
|
// return mockRequestor;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
global using NUnit.Framework;
|
global using System.Text.Json;
|
||||||
global using FluentAssertions;
|
global using FluentAssertions;
|
||||||
global using System.Text.Json;
|
global using NUnit.Framework;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
public static class ConfigurationSetup
|
public static class ConfigurationSetup
|
||||||
{
|
{
|
||||||
public static void Canvas(WebApplicationBuilder builder)
|
public static void Canvas(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
var canvas_token = builder.Configuration["CANVAS_TOKEN"] ?? throw new Exception("CANVAS_TOKEN is null");
|
||||||
|
|
||||||
|
var canvas_url = builder.Configuration["CANVAS_URL"];
|
||||||
|
if (canvas_url == null)
|
||||||
{
|
{
|
||||||
var canvas_token = builder.Configuration["CANVAS_TOKEN"] ?? throw new Exception("CANVAS_TOKEN is null");
|
Console.WriteLine("CANVAS_URL is null, defaulting to https://snow.instructure.com");
|
||||||
|
builder.Configuration["CANVAS_URL"] = "https://snow.instructure.com";
|
||||||
var canvas_url = builder.Configuration["CANVAS_URL"];
|
|
||||||
if (canvas_url == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("CANVAS_URL is null, defaulting to https://snow.instructure.com");
|
|
||||||
builder.Configuration["CANVAS_URL"] = "https://snow.instructure.com";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ public class CustomConsoleExporter : BaseExporter<Activity>
|
|||||||
}
|
}
|
||||||
return ExportResult.Success;
|
return ExportResult.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,11 @@ public class DroppableQuiz : ComponentBase
|
|||||||
);
|
);
|
||||||
|
|
||||||
var NewQuizList = currentModule.Quizzes
|
var NewQuizList = currentModule.Quizzes
|
||||||
.Select(q =>
|
.Select(q =>
|
||||||
q.Name + q.Description != Quiz.Name + Quiz.Description
|
q.Name + q.Description != Quiz.Name + Quiz.Description
|
||||||
? q :
|
? q :
|
||||||
q with {
|
q with
|
||||||
|
{
|
||||||
DueAt = defaultDueTimeDate,
|
DueAt = defaultDueTimeDate,
|
||||||
LockAt = q.LockAt > defaultDueTimeDate ? q.LockAt : defaultDueTimeDate
|
LockAt = q.LockAt > defaultDueTimeDate ? q.LockAt : defaultDueTimeDate
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,20 +7,20 @@ namespace Management.Web.Pages;
|
|||||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||||
[IgnoreAntiforgeryToken]
|
[IgnoreAntiforgeryToken]
|
||||||
public class ErrorModel : PageModel
|
public class ErrorModel : PageModel
|
||||||
{
|
{
|
||||||
public string? RequestId { get; set; }
|
public string? RequestId { get; set; }
|
||||||
|
|
||||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||||
|
|
||||||
private readonly ILogger<ErrorModel> _logger;
|
private readonly ILogger<ErrorModel> _logger;
|
||||||
|
|
||||||
public ErrorModel(ILogger<ErrorModel> logger)
|
public ErrorModel(ILogger<ErrorModel> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnGet()
|
public void OnGet()
|
||||||
{
|
{
|
||||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,23 @@
|
|||||||
global using System.Text.Json.Serialization;
|
|
||||||
global using System.Text.Json;
|
|
||||||
global using System.ComponentModel.DataAnnotations;
|
global using System.ComponentModel.DataAnnotations;
|
||||||
global using Management.Services.Canvas;
|
global using System.Text.Json;
|
||||||
global using Management.Services;
|
global using System.Text.Json.Serialization;
|
||||||
global using CanvasModel.EnrollmentTerms;
|
|
||||||
global using CanvasModel.Courses;
|
|
||||||
global using CanvasModel;
|
global using CanvasModel;
|
||||||
|
global using CanvasModel.Courses;
|
||||||
|
global using CanvasModel.EnrollmentTerms;
|
||||||
global using LocalModels;
|
global using LocalModels;
|
||||||
global using Management.Planner;
|
global using Management.Planner;
|
||||||
global using Management.Web.Shared.Components;
|
global using Management.Services;
|
||||||
|
global using Management.Services.Canvas;
|
||||||
global using Management.Web.Shared;
|
global using Management.Web.Shared;
|
||||||
|
global using Management.Web.Shared.Components;
|
||||||
using dotenv.net;
|
using dotenv.net;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
|
using OpenTelemetry;
|
||||||
using OpenTelemetry.Logs;
|
using OpenTelemetry.Logs;
|
||||||
using OpenTelemetry.Metrics;
|
using OpenTelemetry.Metrics;
|
||||||
using OpenTelemetry.Resources;
|
using OpenTelemetry.Resources;
|
||||||
using OpenTelemetry.Trace;
|
using OpenTelemetry.Trace;
|
||||||
using OpenTelemetry;
|
|
||||||
|
|
||||||
DotEnv.Load();
|
DotEnv.Load();
|
||||||
|
|
||||||
|
|||||||
@@ -79,4 +79,4 @@ public class CalendarMonth
|
|||||||
Year = year;
|
Year = year;
|
||||||
Month = month;
|
Month = month;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using CanvasModel.EnrollmentTerms;
|
|
||||||
using CanvasModel.Courses;
|
|
||||||
using CanvasModel;
|
|
||||||
using LocalModels;
|
|
||||||
using CanvasModel.Assignments;
|
|
||||||
using CanvasModel.Modules;
|
|
||||||
using Management.Services.Canvas;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using CanvasModel.Quizzes;
|
using CanvasModel;
|
||||||
using Management.Services;
|
using CanvasModel.Assignments;
|
||||||
|
using CanvasModel.Courses;
|
||||||
|
using CanvasModel.EnrollmentTerms;
|
||||||
|
using CanvasModel.Modules;
|
||||||
using CanvasModel.Pages;
|
using CanvasModel.Pages;
|
||||||
|
using CanvasModel.Quizzes;
|
||||||
|
using LocalModels;
|
||||||
|
using Management.Services;
|
||||||
|
using Management.Services.Canvas;
|
||||||
|
|
||||||
namespace Management.Planner;
|
namespace Management.Planner;
|
||||||
|
|
||||||
@@ -181,13 +181,17 @@ public class CoursePlanner
|
|||||||
|
|
||||||
CanvasAssignmentGroups = await canvas.AssignmentGroups.GetAll(canvasCourseId);
|
CanvasAssignmentGroups = await canvas.AssignmentGroups.GetAll(canvasCourseId);
|
||||||
|
|
||||||
LocalCourse = LocalCourse with {Settings = LocalCourse.Settings with {
|
LocalCourse = LocalCourse with
|
||||||
AssignmentGroups = LocalCourse.Settings.AssignmentGroups.Select(g => {
|
{
|
||||||
var canvasGroup = CanvasAssignmentGroups.FirstOrDefault(c => c.Name == g.Name);
|
Settings = LocalCourse.Settings with
|
||||||
return canvasGroup == null
|
{
|
||||||
? g
|
AssignmentGroups = LocalCourse.Settings.AssignmentGroups.Select(g =>
|
||||||
: g with {CanvasId = canvasGroup.Id};
|
{
|
||||||
})
|
var canvasGroup = CanvasAssignmentGroups.FirstOrDefault(c => c.Name == g.Name);
|
||||||
|
return canvasGroup == null
|
||||||
|
? g
|
||||||
|
: g with { CanvasId = canvasGroup.Id };
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class PageEditorContext(
|
|||||||
|
|
||||||
var canvasModule = getCurrentCanvasModule(Page, planner.LocalCourse);
|
var canvasModule = getCurrentCanvasModule(Page, planner.LocalCourse);
|
||||||
|
|
||||||
if(canvasPage != null)
|
if (canvasPage != null)
|
||||||
{
|
{
|
||||||
await canvas.CreatePageModuleItem(
|
await canvas.CreatePageModuleItem(
|
||||||
(ulong)courseCanvasId,
|
(ulong)courseCanvasId,
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ public static partial class AssignmentGroupSyncronizationExtensions
|
|||||||
|
|
||||||
return assignmentGroups;
|
return assignmentGroups;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,13 +140,13 @@ public static partial class AssignmentSyncronizationExtensions
|
|||||||
second: localAssignment.LockAt.Value.Second
|
second: localAssignment.LockAt.Value.Second
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (canvasComparisonLockDate != localComparisonLockDate)
|
if (canvasComparisonLockDate != localComparisonLockDate)
|
||||||
{
|
{
|
||||||
var printableLocal = localComparisonLockDate?.ToString() ?? "null";
|
var printableLocal = localComparisonLockDate?.ToString() ?? "null";
|
||||||
var printableCanvas = canvasComparisonLockDate?.ToString() ?? "null";
|
var printableCanvas = canvasComparisonLockDate?.ToString() ?? "null";
|
||||||
var reason = $"Lock dates different for assignment {localAssignment.Name}, local: {printableLocal}, in canvas {printableCanvas}";
|
var reason = $"Lock dates different for assignment {localAssignment.Name}, local: {printableLocal}, in canvas {printableCanvas}";
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
// Console.WriteLine(JsonSerializer.Serialize(canvasAssignment));
|
// Console.WriteLine(JsonSerializer.Serialize(canvasAssignment));
|
||||||
|
|||||||
@@ -39,14 +39,15 @@ public static partial class ModuleSyncronizationExtensions
|
|||||||
{
|
{
|
||||||
var canvasModuleItems = await canvas.Modules.GetModuleItems(canvasId, moduleCanvasId);
|
var canvasModuleItems = await canvas.Modules.GetModuleItems(canvasId, moduleCanvasId);
|
||||||
var moduleItemsInCorrectOrder = canvasModuleItems
|
var moduleItemsInCorrectOrder = canvasModuleItems
|
||||||
.OrderBy(canvasItem => {
|
.OrderBy(canvasItem =>
|
||||||
|
{
|
||||||
|
|
||||||
if(canvasItem.Type == "Page")
|
if (canvasItem.Type == "Page")
|
||||||
{
|
{
|
||||||
var localPage = localModule.Pages.FirstOrDefault(p => p.Name == canvasItem.Title);
|
var localPage = localModule.Pages.FirstOrDefault(p => p.Name == canvasItem.Title);
|
||||||
Console.WriteLine(JsonSerializer.Serialize(localModule.Pages));
|
Console.WriteLine(JsonSerializer.Serialize(localModule.Pages));
|
||||||
|
|
||||||
if(localPage != null)
|
if (localPage != null)
|
||||||
return localPage.DueAt.Date;
|
return localPage.DueAt.Date;
|
||||||
}
|
}
|
||||||
return canvasItem.ContentDetails?.DueAt?.Date;
|
return canvasItem.ContentDetails?.DueAt?.Date;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
global using System.Text.Json.Serialization;
|
|
||||||
global using System.Text.Json;
|
global using System.Text.Json;
|
||||||
global using Microsoft.Extensions.Logging;
|
global using System.Text.Json.Serialization;
|
||||||
|
global using Microsoft.Extensions.Logging;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public record CanvasAssignment
|
|||||||
|
|
||||||
[property: JsonPropertyName("allowed_attempts")]
|
[property: JsonPropertyName("allowed_attempts")]
|
||||||
int AllowedAttempts,
|
int AllowedAttempts,
|
||||||
|
|
||||||
[property: JsonPropertyName("is_quiz_assignment")]
|
[property: JsonPropertyName("is_quiz_assignment")]
|
||||||
bool IsQuizAssignment,
|
bool IsQuizAssignment,
|
||||||
|
|
||||||
@@ -208,4 +208,4 @@ public record CanvasAssignment
|
|||||||
|
|
||||||
[property: JsonPropertyName("anonymous_grading")]
|
[property: JsonPropertyName("anonymous_grading")]
|
||||||
bool? AnonymousGrading = null
|
bool? AnonymousGrading = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ public record CanvasAssignmentDate
|
|||||||
|
|
||||||
[property: JsonPropertyName("lock_at")]
|
[property: JsonPropertyName("lock_at")]
|
||||||
DateTime? LockAt = null
|
DateTime? LockAt = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ public record CanvasAssignmentGroup
|
|||||||
|
|
||||||
// [JsonPropertyName("rules")]
|
// [JsonPropertyName("rules")]
|
||||||
// public object Rules { get; init; } // The specific type for 'Rules' is not detailed in the spec, so using object for now.
|
// public object Rules { get; init; } // The specific type for 'Rules' is not detailed in the spec, so using object for now.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ public record CanvasAssignmentOverride
|
|||||||
|
|
||||||
[property: JsonPropertyName("lock_at")]
|
[property: JsonPropertyName("lock_at")]
|
||||||
DateTime? LockAt = null
|
DateTime? LockAt = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ public record CanvasExternalToolTagAttributes
|
|||||||
|
|
||||||
[property: JsonPropertyName("new_tab")]
|
[property: JsonPropertyName("new_tab")]
|
||||||
bool? NewTab = null
|
bool? NewTab = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ public record CanvasLockInfo
|
|||||||
|
|
||||||
[property: JsonPropertyName("manually_locked")]
|
[property: JsonPropertyName("manually_locked")]
|
||||||
bool? ManuallyLocked = null
|
bool? ManuallyLocked = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ public record CanvasNeedsGradingCount
|
|||||||
|
|
||||||
[property: JsonPropertyName("needs_grading_count")]
|
[property: JsonPropertyName("needs_grading_count")]
|
||||||
uint NeedsGradingCount
|
uint NeedsGradingCount
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,4 +34,4 @@ public record CanvasRubric
|
|||||||
|
|
||||||
// assessments
|
// assessments
|
||||||
// associations
|
// associations
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ public record CanvasRubricAssociation
|
|||||||
[JsonPropertyName("hide_outcome-results")]
|
[JsonPropertyName("hide_outcome-results")]
|
||||||
public bool HideOUtcomeResult { get; set; }
|
public bool HideOUtcomeResult { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ public record CanvasRubricCriteria
|
|||||||
|
|
||||||
[property: JsonPropertyName("ignore_for_scoring")]
|
[property: JsonPropertyName("ignore_for_scoring")]
|
||||||
bool? IgnoreForScoring = null
|
bool? IgnoreForScoring = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ public record CanvasRubricRating
|
|||||||
|
|
||||||
[property: JsonPropertyName("long_description")]
|
[property: JsonPropertyName("long_description")]
|
||||||
string LongDescription
|
string LongDescription
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ public record CanvasTurnitinSettings
|
|||||||
|
|
||||||
[property: JsonPropertyName("exclude_small_matches_value")]
|
[property: JsonPropertyName("exclude_small_matches_value")]
|
||||||
uint? ExcludeSmallMatchesValue = null
|
uint? ExcludeSmallMatchesValue = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ namespace CanvasModel.Courses;
|
|||||||
public record CalendarLinkModel
|
public record CalendarLinkModel
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("ics")] string Ics
|
[property: JsonPropertyName("ics")] string Ics
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,15 +2,15 @@
|
|||||||
namespace CanvasModel.Courses;
|
namespace CanvasModel.Courses;
|
||||||
public record CourseProgressModel
|
public record CourseProgressModel
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("requirement_count")]
|
[property: JsonPropertyName("requirement_count")]
|
||||||
uint? RequirementCount = null,
|
uint? RequirementCount = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("requirement_completed_count")]
|
[property: JsonPropertyName("requirement_completed_count")]
|
||||||
uint? RequirementCompletedCount = null,
|
uint? RequirementCompletedCount = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("next_requirement_url")]
|
[property: JsonPropertyName("next_requirement_url")]
|
||||||
string? NextRequirementUrl = null,
|
string? NextRequirementUrl = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("completed_at")]
|
[property: JsonPropertyName("completed_at")]
|
||||||
DateTime? CompletedAt = null
|
DateTime? CompletedAt = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -108,4 +108,4 @@ public record DiscussionTopicModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("sort_by_rating")]
|
[property: JsonPropertyName("sort_by_rating")]
|
||||||
bool? SortByRating = null
|
bool? SortByRating = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ public record FileAttachmentModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("display_name")]
|
[property: JsonPropertyName("display_name")]
|
||||||
string DisplayName
|
string DisplayName
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,4 +37,4 @@ public record TopicEntryModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("has_more_replies")]
|
[property: JsonPropertyName("has_more_replies")]
|
||||||
bool? HasMoreReplies = null
|
bool? HasMoreReplies = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ public record TopicReplyModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("forced_read_state")]
|
[property: JsonPropertyName("forced_read_state")]
|
||||||
bool? ForcedReadState = null
|
bool? ForcedReadState = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ namespace CanvasModel.EnrollmentTerms;
|
|||||||
|
|
||||||
public record RedundantEnrollmentTermsResponse
|
public record RedundantEnrollmentTermsResponse
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("enrollment_terms")]
|
[property: JsonPropertyName("enrollment_terms")]
|
||||||
IEnumerable<EnrollmentTermModel> EnrollmentTerms
|
IEnumerable<EnrollmentTermModel> EnrollmentTerms
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -132,4 +132,4 @@ public record EnrollmentModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("current_period_unposted_final_grade")]
|
[property: JsonPropertyName("current_period_unposted_final_grade")]
|
||||||
string? CurrentPeriodUnpostedFinalGrade = null
|
string? CurrentPeriodUnpostedFinalGrade = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ public record GradeModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("unposted_final_score")]
|
[property: JsonPropertyName("unposted_final_score")]
|
||||||
string? UnpostedFinalScore = null
|
string? UnpostedFinalScore = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public record CanvasModule(
|
|||||||
[property: JsonPropertyName("items")]
|
[property: JsonPropertyName("items")]
|
||||||
IEnumerable<CanvasModuleItem>? Items,
|
IEnumerable<CanvasModuleItem>? Items,
|
||||||
[property: JsonPropertyName("state")] string? State, // todo make sure this,
|
[property: JsonPropertyName("state")] string? State, // todo make sure this,
|
||||||
// [OptIn]
|
// [OptIn]
|
||||||
[property: JsonPropertyName("completed_at")]
|
[property: JsonPropertyName("completed_at")]
|
||||||
DateTime? CompletedAt,
|
DateTime? CompletedAt,
|
||||||
[property: JsonPropertyName("publish_final_grade")] bool? PublishFinalGrade,
|
[property: JsonPropertyName("publish_final_grade")] bool? PublishFinalGrade,
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ public record CanvasModuleItemContentDetails(
|
|||||||
[property: JsonPropertyName("lock_at")] DateTime? LockAt,
|
[property: JsonPropertyName("lock_at")] DateTime? LockAt,
|
||||||
[property: JsonPropertyName("points_possible")] double PointsPossible,
|
[property: JsonPropertyName("points_possible")] double PointsPossible,
|
||||||
[property: JsonPropertyName("locked_for_user")] bool LockedForUser
|
[property: JsonPropertyName("locked_for_user")] bool LockedForUser
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
namespace CanvasModel.Pages;
|
namespace CanvasModel.Pages;
|
||||||
public record CanvasPage (
|
public record CanvasPage(
|
||||||
[property: JsonPropertyName("page_id")] ulong PageId,
|
[property: JsonPropertyName("page_id")] ulong PageId,
|
||||||
[property: JsonPropertyName("url")] string Url,
|
[property: JsonPropertyName("url")] string Url,
|
||||||
[property: JsonPropertyName("title")] string Title,
|
[property: JsonPropertyName("title")] string Title,
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ public record MediaCommentModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("url")]
|
[property: JsonPropertyName("url")]
|
||||||
string Url
|
string Url
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,4 +26,4 @@ public record SubmissionCommentModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("media_comment")]
|
[property: JsonPropertyName("media_comment")]
|
||||||
MediaCommentModel? MediaComment = null
|
MediaCommentModel? MediaComment = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -88,4 +88,4 @@ public record SubmissionModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("anonymous_id")]
|
[property: JsonPropertyName("anonymous_id")]
|
||||||
string? AnonymousId = null
|
string? AnonymousId = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -160,4 +160,4 @@ public record ActivityStreamObjectModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("assignment_request_id")]
|
[property: JsonPropertyName("assignment_request_id")]
|
||||||
ulong? AssignmentRequestId = null
|
ulong? AssignmentRequestId = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ public record ActivityStreamSummaryEntryModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("count")]
|
[property: JsonPropertyName("count")]
|
||||||
uint Count
|
uint Count
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ public record AnonymousUserDisplayModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("avatar_image_url")]
|
[property: JsonPropertyName("avatar_image_url")]
|
||||||
string AvatarImageUrl
|
string AvatarImageUrl
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,4 +25,4 @@ public record AvatarModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("size")]
|
[property: JsonPropertyName("size")]
|
||||||
ulong Size
|
ulong Size
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ public record CourseNicknameModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("nickname")]
|
[property: JsonPropertyName("nickname")]
|
||||||
string Nickname
|
string Nickname
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ public record PageViewLinksModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("account")]
|
[property: JsonPropertyName("account")]
|
||||||
ulong? Account = null
|
ulong? Account = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -50,4 +50,4 @@ public record PageViewModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("participated")]
|
[property: JsonPropertyName("participated")]
|
||||||
bool? Participated = null
|
bool? Participated = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,4 +43,4 @@ public record ProfileModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("locale")]
|
[property: JsonPropertyName("locale")]
|
||||||
string Locale
|
string Locale
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ public record UserDisplayModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("pronouns")]
|
[property: JsonPropertyName("pronouns")]
|
||||||
string? Pronouns = null
|
string? Pronouns = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -53,4 +53,4 @@ public record UserModel
|
|||||||
|
|
||||||
[property: JsonPropertyName("last_login")]
|
[property: JsonPropertyName("last_login")]
|
||||||
DateTime? LastLogin = null
|
DateTime? LastLogin = null
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ public class RubricMarkdownParseException : Exception
|
|||||||
public class AssignmentMarkdownParseException : Exception
|
public class AssignmentMarkdownParseException : Exception
|
||||||
{
|
{
|
||||||
public AssignmentMarkdownParseException(string message) : base(message) { }
|
public AssignmentMarkdownParseException(string message) : base(message) { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,5 +26,5 @@ public record AssignmentTemplate
|
|||||||
// }
|
// }
|
||||||
// return html;
|
// return html;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using YamlDotNet.Serialization;
|
|||||||
|
|
||||||
namespace LocalModels;
|
namespace LocalModels;
|
||||||
|
|
||||||
public record LocalAssignment: IModuleItem
|
public record LocalAssignment : IModuleItem
|
||||||
{
|
{
|
||||||
private string _name = "";
|
private string _name = "";
|
||||||
public string Name
|
public string Name
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ public record LocalAssignmentGroup
|
|||||||
public string Id { get; init; } = string.Empty;
|
public string Id { get; init; } = string.Empty;
|
||||||
public required string Name { get; init; }
|
public required string Name { get; init; }
|
||||||
public double Weight { get; init; }
|
public double Weight { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace LocalModels;
|
namespace LocalModels;
|
||||||
|
|
||||||
public record LocalCoursePage: IModuleItem
|
public record LocalCoursePage : IModuleItem
|
||||||
{
|
{
|
||||||
public required string Name { get; init; }
|
public required string Name { get; init; }
|
||||||
public required string Text { get; set; }
|
public required string Text { get; set; }
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using YamlDotNet.Serialization;
|
|||||||
|
|
||||||
namespace LocalModels;
|
namespace LocalModels;
|
||||||
|
|
||||||
public record LocalQuiz: IModuleItem
|
public record LocalQuiz : IModuleItem
|
||||||
{
|
{
|
||||||
|
|
||||||
public required string Name { get; init; }
|
public required string Name { get; init; }
|
||||||
@@ -171,7 +171,7 @@ Description: {Description}
|
|||||||
|
|
||||||
public class QuizMarkdownParseException : Exception
|
public class QuizMarkdownParseException : Exception
|
||||||
{
|
{
|
||||||
public QuizMarkdownParseException(string message): base(message)
|
public QuizMarkdownParseException(string message) : base(message)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public record LocalQuizQuestion
|
|||||||
|
|
||||||
return $"{questionTypeIndicator}{multilineMarkdownCompatibleText}";
|
return $"{questionTypeIndicator}{multilineMarkdownCompatibleText}";
|
||||||
}
|
}
|
||||||
else if(QuestionType == "matching")
|
else if (QuestionType == "matching")
|
||||||
{
|
{
|
||||||
return $"^ {answer.Text} - {answer.MatchedText}";
|
return $"^ {answer.Text} - {answer.MatchedText}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,10 +63,12 @@ public class CanvasModuleService
|
|||||||
if (items == null)
|
if (items == null)
|
||||||
throw new Exception($"Error getting canvas module items for {url}");
|
throw new Exception($"Error getting canvas module items for {url}");
|
||||||
return items.Select(i =>
|
return items.Select(i =>
|
||||||
i with {
|
i with
|
||||||
|
{
|
||||||
ContentDetails = i.ContentDetails == null
|
ContentDetails = i.ContentDetails == null
|
||||||
? null
|
? null
|
||||||
: i.ContentDetails with {
|
: i.ContentDetails with
|
||||||
|
{
|
||||||
DueAt = i.ContentDetails.DueAt?.ToLocalTime(),
|
DueAt = i.ContentDetails.DueAt?.ToLocalTime(),
|
||||||
LockAt = i.ContentDetails.LockAt?.ToLocalTime(),
|
LockAt = i.ContentDetails.LockAt?.ToLocalTime(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,14 +117,16 @@ public class CanvasQuizService(
|
|||||||
await Task.WhenAll(tasks);
|
await Task.WhenAll(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task hackFixQuestionOrdering(ulong canvasCourseId, ulong canvasQuizId, IEnumerable<(CanvasQuizQuestion question, int position)> questionAndPositions )
|
private async Task hackFixQuestionOrdering(ulong canvasCourseId, ulong canvasQuizId, IEnumerable<(CanvasQuizQuestion question, int position)> questionAndPositions)
|
||||||
{
|
{
|
||||||
using var activity = DiagnosticsConfig.Source.StartActivity("hack fixing question ordering with reorder");
|
using var activity = DiagnosticsConfig.Source.StartActivity("hack fixing question ordering with reorder");
|
||||||
activity?.SetCustomProperty("canvasQuizId", canvasQuizId);
|
activity?.SetCustomProperty("canvasQuizId", canvasQuizId);
|
||||||
activity?.SetTag("canvas syncronization", true);
|
activity?.SetTag("canvas syncronization", true);
|
||||||
|
|
||||||
var order = questionAndPositions.OrderBy(t => t.position).Select(tuple => {
|
var order = questionAndPositions.OrderBy(t => t.position).Select(tuple =>
|
||||||
return new {
|
{
|
||||||
|
return new
|
||||||
|
{
|
||||||
type = "question",
|
type = "question",
|
||||||
id = tuple.question.Id.ToString(),
|
id = tuple.question.Id.ToString(),
|
||||||
};
|
};
|
||||||
@@ -182,9 +184,10 @@ public class CanvasQuizService(
|
|||||||
|
|
||||||
private static object[] getAnswers(LocalQuizQuestion q)
|
private static object[] getAnswers(LocalQuizQuestion q)
|
||||||
{
|
{
|
||||||
if(q.QuestionType == QuestionType.MATCHING)
|
if (q.QuestionType == QuestionType.MATCHING)
|
||||||
return q.Answers
|
return q.Answers
|
||||||
.Select(a => new {
|
.Select(a => new
|
||||||
|
{
|
||||||
answer_match_left = a.Text,
|
answer_match_left = a.Text,
|
||||||
answer_match_right = a.MatchedText
|
answer_match_right = a.MatchedText
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using CanvasModel;
|
using CanvasModel;
|
||||||
using CanvasModel.Assignments;
|
using CanvasModel.Assignments;
|
||||||
using CanvasModel.Courses;
|
using CanvasModel.Courses;
|
||||||
using CanvasModel.EnrollmentTerms;
|
using CanvasModel.EnrollmentTerms;
|
||||||
using CanvasModel.Modules;
|
using CanvasModel.Modules;
|
||||||
using RestSharp;
|
|
||||||
using CanvasModel.Pages;
|
using CanvasModel.Pages;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using RestSharp;
|
||||||
|
|
||||||
namespace Management.Services.Canvas;
|
namespace Management.Services.Canvas;
|
||||||
|
|
||||||
|
|||||||
@@ -14,4 +14,4 @@ public class FileConfiguration(IConfiguration config)
|
|||||||
return basePath;
|
return basePath;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class FileStorageManager
|
|||||||
|
|
||||||
public IEnumerable<string> GetEmptyDirectories()
|
public IEnumerable<string> GetEmptyDirectories()
|
||||||
{
|
{
|
||||||
if(!Directory.Exists(_basePath))
|
if (!Directory.Exists(_basePath))
|
||||||
throw new DirectoryNotFoundException($"Cannot get empty directories, {_basePath} does not exist");
|
throw new DirectoryNotFoundException($"Cannot get empty directories, {_basePath} does not exist");
|
||||||
|
|
||||||
return Directory
|
return Directory
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class CourseMarkdownLoader
|
|||||||
})
|
})
|
||||||
.Select(async d => await LoadCourseByPath(d))
|
.Select(async d => await LoadCourseByPath(d))
|
||||||
);
|
);
|
||||||
return courses.OrderBy(c=>c.Settings.Name);
|
return courses.OrderBy(c => c.Settings.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LocalCourse> LoadCourseByPath(string courseDirectory)
|
public async Task<LocalCourse> LoadCourseByPath(string courseDirectory)
|
||||||
|
|||||||
@@ -45,12 +45,15 @@ public class WebRequestor : IWebRequestor
|
|||||||
|
|
||||||
var response = await client.ExecutePostAsync(request);
|
var response = await client.ExecutePostAsync(request);
|
||||||
|
|
||||||
if (isRateLimited(response)) {
|
if (isRateLimited(response))
|
||||||
if(retryCount < rateLimitRetryCount){
|
{
|
||||||
|
if (retryCount < rateLimitRetryCount)
|
||||||
|
{
|
||||||
logger.LogInformation($"hit rate limit on post, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
logger.LogInformation($"hit rate limit on post, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
||||||
Console.WriteLine($"hit rate limit on post, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
Console.WriteLine($"hit rate limit on post, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
||||||
Thread.Sleep(rateLimitSleepInterval);
|
Thread.Sleep(rateLimitSleepInterval);
|
||||||
return await rateLimitAwarePostAsync(request, retryCount + 1);}
|
return await rateLimitAwarePostAsync(request, retryCount + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.IsSuccessful)
|
if (!response.IsSuccessful)
|
||||||
@@ -63,7 +66,7 @@ public class WebRequestor : IWebRequestor
|
|||||||
|
|
||||||
private static bool isRateLimited(RestResponse response)
|
private static bool isRateLimited(RestResponse response)
|
||||||
{
|
{
|
||||||
if(response.Content == null)
|
if (response.Content == null)
|
||||||
return false;
|
return false;
|
||||||
return response.StatusCode == HttpStatusCode.Forbidden
|
return response.StatusCode == HttpStatusCode.Forbidden
|
||||||
&& response.Content.Contains("403 Forbidden (Rate Limit Exceeded)");
|
&& response.Content.Contains("403 Forbidden (Rate Limit Exceeded)");
|
||||||
@@ -110,7 +113,7 @@ public class WebRequestor : IWebRequestor
|
|||||||
{
|
{
|
||||||
if (e.StatusCode == HttpStatusCode.Forbidden) // && response.Content == "403 Forbidden (Rate Limit Exceeded)"
|
if (e.StatusCode == HttpStatusCode.Forbidden) // && response.Content == "403 Forbidden (Rate Limit Exceeded)"
|
||||||
{
|
{
|
||||||
if(retryCount < rateLimitRetryCount)
|
if (retryCount < rateLimitRetryCount)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"hit rate limit in delete, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
logger.LogInformation($"hit rate limit in delete, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
||||||
Console.WriteLine($"hit rate limit in delete, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
Console.WriteLine($"hit rate limit in delete, retry count is {retryCount} / {rateLimitRetryCount}, retrying");
|
||||||
|
|||||||
Reference in New Issue
Block a user