mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
working on canvas sync
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ bin/
|
|||||||
.env
|
.env
|
||||||
*.env
|
*.env
|
||||||
storage/
|
storage/
|
||||||
|
tmp.json
|
||||||
@@ -70,13 +70,20 @@
|
|||||||
{
|
{
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<button
|
<button
|
||||||
@onclick="@(() => planner.LocalCourse = null)"
|
@onclick="planner.Clear"
|
||||||
class="btn btn-primary"
|
class="btn btn-primary"
|
||||||
>
|
>
|
||||||
Select New Course
|
Select New Course
|
||||||
</button>
|
</button>
|
||||||
<CourseSettings />
|
<CourseSettings />
|
||||||
<AssignmentTemplateManagement />
|
<AssignmentTemplateManagement />
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-primary"
|
||||||
|
@onclick="planner.SyncWithCanvas"
|
||||||
|
>
|
||||||
|
Sync With Canvas
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<CourseDetails />
|
<CourseDetails />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ builder.Services.AddRazorPages();
|
|||||||
builder.Services.AddServerSideBlazor();
|
builder.Services.AddServerSideBlazor();
|
||||||
builder.Services.AddScoped<IWebRequestor, WebRequestor>();
|
builder.Services.AddScoped<IWebRequestor, WebRequestor>();
|
||||||
builder.Services.AddScoped<CanvasService, CanvasService>();
|
builder.Services.AddScoped<CanvasService, CanvasService>();
|
||||||
builder.Services.AddSingleton<YamlManager>();
|
builder.Services.AddScoped<YamlManager>();
|
||||||
builder.Services.AddSingleton<CoursePlanner>();
|
builder.Services.AddScoped<CoursePlanner>();
|
||||||
builder.Services.AddSingleton<AssignmentDragContainer>();
|
builder.Services.AddScoped<AssignmentDragContainer>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
@using Management.Web.Shared.Module
|
@using Management.Web.Shared.Module
|
||||||
@using Management.Web.Shared.Semester
|
@using Management.Web.Shared.Semester
|
||||||
|
|
||||||
|
@inject CanvasService canvas
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
|
|
||||||
@code
|
@code
|
||||||
@@ -11,6 +12,22 @@
|
|||||||
{
|
{
|
||||||
planner.StateHasChanged += reload;
|
planner.StateHasChanged += reload;
|
||||||
}
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
private void reload()
|
private void reload()
|
||||||
{
|
{
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
this.InvokeAsync(this.StateHasChanged);
|
||||||
@@ -21,8 +38,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col overflow-y-auto border rounded " style="max-height: 95vh;">
|
<div class="col overflow-y-auto border rounded " style="max-height: 95vh;">
|
||||||
@if (planner.LocalCourse != null)
|
@if (planner.LocalCourse != null)
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
minute: planner.LocalCourse.DefaultDueTime.Minute,
|
minute: planner.LocalCourse.DefaultDueTime.Minute,
|
||||||
second: 0
|
second: 0
|
||||||
);
|
);
|
||||||
|
|
||||||
var moduleWithUpdatedAssignment = currentModule with
|
var moduleWithUpdatedAssignment = currentModule with
|
||||||
{
|
{
|
||||||
Assignments = currentModule.Assignments.Select(a =>
|
Assignments = currentModule.Assignments.Select(a =>
|
||||||
@@ -114,6 +115,13 @@
|
|||||||
dragContainer.DropCallback = null;
|
dragContainer.DropCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool isSyncedWithCanvas =>
|
||||||
|
planner
|
||||||
|
.CanvasAssignments?
|
||||||
|
.FirstOrDefault(
|
||||||
|
a => a.Id == Assignment.canvasId
|
||||||
|
) != null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -130,6 +138,14 @@
|
|||||||
<h4 class="text-center">
|
<h4 class="text-center">
|
||||||
@Assignment.name
|
@Assignment.name
|
||||||
</h4>
|
</h4>
|
||||||
|
@if(isSyncedWithCanvas)
|
||||||
|
{
|
||||||
|
<div>Synced With Canvas</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div>Not Synced with Canvas</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-text">
|
<div class="card-text">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|||||||
@@ -44,6 +44,12 @@
|
|||||||
}
|
}
|
||||||
dragContainer.DropCallback?.Invoke(null, Module);
|
dragContainer.DropCallback?.Invoke(null, Module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool isSyncedWithCanvas => planner
|
||||||
|
.CanvasModules?
|
||||||
|
.FirstOrDefault(
|
||||||
|
cm => cm.Id == Module.CanvasId
|
||||||
|
) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -53,18 +59,29 @@
|
|||||||
@ondragleave="OnDragLeave"
|
@ondragleave="OnDragLeave"
|
||||||
ondragover="event.preventDefault();"
|
ondragover="event.preventDefault();"
|
||||||
>
|
>
|
||||||
|
<h2 class="accordion-header">
|
||||||
<h2 class="@("accordion-header ")">
|
|
||||||
<button
|
<button
|
||||||
class="accordion-button"
|
class="accordion-button"
|
||||||
type="button"
|
type="button"
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
data-bs-target="@("#" + accordionId)"
|
data-bs-target="@("#" + accordionId)"
|
||||||
aria-expanded="true"
|
|
||||||
aria-controls="@accordionId"
|
aria-controls="@accordionId"
|
||||||
>
|
>
|
||||||
|
<div class="w-100 d-flex justify-content-between pe-3">
|
||||||
|
<div>
|
||||||
@Module.Name
|
@Module.Name
|
||||||
|
</div>
|
||||||
|
@if(isSyncedWithCanvas)
|
||||||
|
{
|
||||||
|
<div>in canvas</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div>not in canvas</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<div
|
||||||
id="@accordionId"
|
id="@accordionId"
|
||||||
|
|||||||
@@ -2,14 +2,18 @@ using CanvasModel.EnrollmentTerms;
|
|||||||
using CanvasModel.Courses;
|
using CanvasModel.Courses;
|
||||||
using CanvasModel;
|
using CanvasModel;
|
||||||
using LocalModels;
|
using LocalModels;
|
||||||
|
using CanvasModel.Assignments;
|
||||||
|
using CanvasModel.Modules;
|
||||||
|
|
||||||
public class CoursePlanner
|
public class CoursePlanner
|
||||||
{
|
{
|
||||||
private readonly YamlManager yamlManager;
|
private readonly YamlManager yamlManager;
|
||||||
|
private readonly CanvasService canvas;
|
||||||
|
|
||||||
public CoursePlanner(YamlManager yamlManager)
|
public CoursePlanner(YamlManager yamlManager, CanvasService canvas)
|
||||||
{
|
{
|
||||||
this.yamlManager = yamlManager;
|
this.yamlManager = yamlManager;
|
||||||
|
this.canvas = canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalCourse? _localCourse { get; set; }
|
private LocalCourse? _localCourse { get; set; }
|
||||||
@@ -43,6 +47,100 @@ public class CoursePlanner
|
|||||||
module => module with { Assignments = module.Assignments.DistinctBy(a => a.id) }
|
module => module with { Assignments = module.Assignments.DistinctBy(a => a.id) }
|
||||||
);
|
);
|
||||||
|
|
||||||
return incomingCourse with { Modules = modulesWithUniqueAssignments };
|
return incomingCourse with
|
||||||
|
{
|
||||||
|
Modules = modulesWithUniqueAssignments
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CanvasAssignment>? CanvasAssignments { get; set; } = null;
|
||||||
|
public IEnumerable<CanvasModule>? CanvasModules { get; set; } = null;
|
||||||
|
|
||||||
|
public async Task SyncWithCanvas()
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
LocalCourse == null
|
||||||
|
|| LocalCourse.CanvasId == null
|
||||||
|
|| CanvasAssignments == null
|
||||||
|
|| CanvasModules == null
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task reloadModules_UpdateLocalModulesWithNewId(ulong canvasId)
|
||||||
|
{
|
||||||
|
if (LocalCourse == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CanvasModules = await canvas.GetModules(canvasId);
|
||||||
|
LocalCourse = LocalCourse with
|
||||||
|
{
|
||||||
|
Modules = LocalCourse.Modules.Select(m =>
|
||||||
|
{
|
||||||
|
var canvasModule = CanvasModules.FirstOrDefault(cm => cm.Name == m.Name);
|
||||||
|
return canvasModule == null ? m : m with { CanvasId = canvasModule.Id };
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ensureAllModulesCreated(ulong canvasId)
|
||||||
|
{
|
||||||
|
if (LocalCourse == null || CanvasModules == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var module in LocalCourse.Modules)
|
||||||
|
{
|
||||||
|
var canvasModule = CanvasModules.FirstOrDefault(cm => cm.Id == module.CanvasId);
|
||||||
|
if (canvasModule == null)
|
||||||
|
{
|
||||||
|
await canvas.CreateModule(canvasId, module.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ensureAllAssignmentsCreated_updateIds(ulong canvasId)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
LocalCourse == null
|
||||||
|
|| LocalCourse.CanvasId == null
|
||||||
|
|| CanvasAssignments == null
|
||||||
|
|| CanvasModules == null
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var moduleTasks = LocalCourse.Modules.Select(async m =>
|
||||||
|
{
|
||||||
|
var assignmentTasks = m.Assignments.Select(ensureAssignmentInCanvas_returnUpdated);
|
||||||
|
var assignments = await Task.WhenAll(assignmentTasks);
|
||||||
|
return m with { Assignments = assignments };
|
||||||
|
});
|
||||||
|
|
||||||
|
var modules = await Task.WhenAll(moduleTasks);
|
||||||
|
LocalCourse = LocalCourse with
|
||||||
|
{
|
||||||
|
Modules = modules
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<LocalAssignment> ensureAssignmentInCanvas_returnUpdated(
|
||||||
|
LocalAssignment localAssignment
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// var canvasAssignment = await canvas.
|
||||||
|
return localAssignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
LocalCourse = null;
|
||||||
|
CanvasAssignments = null;
|
||||||
|
CanvasModules = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using CanvasModel.Submissions;
|
|||||||
|
|
||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record AssignmentModel
|
public record CanvasAssignment
|
||||||
(
|
(
|
||||||
|
|
||||||
[property: JsonPropertyName("id")]
|
[property: JsonPropertyName("id")]
|
||||||
@@ -88,7 +88,7 @@ public record AssignmentModel
|
|||||||
DateTime? UnlockAt = null,
|
DateTime? UnlockAt = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("all_dates")]
|
[property: JsonPropertyName("all_dates")]
|
||||||
IEnumerable<AssignmentDateModel>? AllDates = null,
|
IEnumerable<CanvasAssignmentDate>? AllDates = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("allowed_extensions")]
|
[property: JsonPropertyName("allowed_extensions")]
|
||||||
IEnumerable<string>? AllowedExtensions = null,
|
IEnumerable<string>? AllowedExtensions = null,
|
||||||
@@ -100,13 +100,13 @@ public record AssignmentModel
|
|||||||
bool? VeriCiteEnabled = null,
|
bool? VeriCiteEnabled = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("turnitin_settings")]
|
[property: JsonPropertyName("turnitin_settings")]
|
||||||
TurnitinSettingsModel? TurnitinSettings = null,
|
CanvasTurnitinSettings? TurnitinSettings = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("grade_group_students_individually")]
|
[property: JsonPropertyName("grade_group_students_individually")]
|
||||||
bool? GradeGroupStudentsIndividually = null,
|
bool? GradeGroupStudentsIndividually = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("external_tool_tag_attributes")]
|
[property: JsonPropertyName("external_tool_tag_attributes")]
|
||||||
ExternalToolTagAttributesModel? ExternalToolTagAttributes = null,
|
CanvasExternalToolTagAttributes? ExternalToolTagAttributes = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("peer_review_count")]
|
[property: JsonPropertyName("peer_review_count")]
|
||||||
uint? PeerReviewCount = null,
|
uint? PeerReviewCount = null,
|
||||||
@@ -124,7 +124,7 @@ public record AssignmentModel
|
|||||||
uint? NeedsGradingCount = null,
|
uint? NeedsGradingCount = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("needs_grading_count_be_section")]
|
[property: JsonPropertyName("needs_grading_count_be_section")]
|
||||||
IEnumerable<NeedsGradingCountModel>? NeedsGradingCountBySection = null,
|
IEnumerable<CanvasNeedsGradingCount>? NeedsGradingCountBySection = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("post_to_sis")]
|
[property: JsonPropertyName("post_to_sis")]
|
||||||
bool? PostToSis = null,
|
bool? PostToSis = null,
|
||||||
@@ -148,7 +148,7 @@ public record AssignmentModel
|
|||||||
ulong? GradingStandardId = null,
|
ulong? GradingStandardId = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("lock_info")]
|
[property: JsonPropertyName("lock_info")]
|
||||||
LockInfoModel? LockInfo = null,
|
CanvasLockInfo? LockInfo = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("lock_explanation")]
|
[property: JsonPropertyName("lock_explanation")]
|
||||||
string? LockExplanation = null,
|
string? LockExplanation = null,
|
||||||
@@ -181,13 +181,13 @@ public record AssignmentModel
|
|||||||
object? RubricSettings = null,
|
object? RubricSettings = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("rubric")]
|
[property: JsonPropertyName("rubric")]
|
||||||
IEnumerable<RubricCriteriaModel>? Rubric = null,
|
IEnumerable<CanvasRubricCriteria>? Rubric = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("assignment_visibility")]
|
[property: JsonPropertyName("assignment_visibility")]
|
||||||
IEnumerable<ulong>? AssignmentVisibility = null,
|
IEnumerable<ulong>? AssignmentVisibility = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("overrides")]
|
[property: JsonPropertyName("overrides")]
|
||||||
IEnumerable<AssignmentOverrideModel>? Overrides = null,
|
IEnumerable<CanvasAssignmentOverride>? Overrides = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("omit_from_final_grade")]
|
[property: JsonPropertyName("omit_from_final_grade")]
|
||||||
bool? OmitFromFinalGrade = null,
|
bool? OmitFromFinalGrade = null,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record AssignmentDateModel
|
public record CanvasAssignmentDate
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("title")]
|
[property: JsonPropertyName("title")]
|
||||||
string Title,
|
string Title,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record AssignmentOverrideModel
|
public record CanvasAssignmentOverride
|
||||||
(
|
(
|
||||||
|
|
||||||
[property: JsonPropertyName("id")]
|
[property: JsonPropertyName("id")]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record ExternalToolTagAttributesModel
|
public record CanvasExternalToolTagAttributes
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("url")]
|
[property: JsonPropertyName("url")]
|
||||||
string Url,
|
string Url,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record LockInfoModel
|
public record CanvasLockInfo
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("asset_string")]
|
[property: JsonPropertyName("asset_string")]
|
||||||
string AssetString,
|
string AssetString,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record NeedsGradingCountModel
|
public record CanvasNeedsGradingCount
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("section_id")]
|
[property: JsonPropertyName("section_id")]
|
||||||
string SectionId,
|
string SectionId,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record RubricCriteriaModel
|
public record CanvasRubricCriteria
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("id")]
|
[property: JsonPropertyName("id")]
|
||||||
string Id,
|
string Id,
|
||||||
@@ -23,7 +23,7 @@ public record RubricCriteriaModel
|
|||||||
bool? CriterionUseRange = null,
|
bool? CriterionUseRange = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("ratings")]
|
[property: JsonPropertyName("ratings")]
|
||||||
IEnumerable<RubricRatingModel>? Ratings = null,
|
IEnumerable<CanvasRubricRating>? Ratings = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("ignore_for_scoring")]
|
[property: JsonPropertyName("ignore_for_scoring")]
|
||||||
bool? IgnoreForScoring = null
|
bool? IgnoreForScoring = null
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record RubricRatingModel
|
public record CanvasRubricRating
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("points")]
|
[property: JsonPropertyName("points")]
|
||||||
double Points,
|
double Points,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace CanvasModel.Assignments;
|
namespace CanvasModel.Assignments;
|
||||||
|
|
||||||
public record TurnitinSettingsModel
|
public record CanvasTurnitinSettings
|
||||||
(
|
(
|
||||||
[property: JsonPropertyName("originality_report_visibility")]
|
[property: JsonPropertyName("originality_report_visibility")]
|
||||||
string OriginalityReportVisibility,
|
string OriginalityReportVisibility,
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace CanvasModel;
|
|
||||||
|
|
||||||
public record CourseModule(
|
|
||||||
[property: JsonPropertyName("id")] ulong Id,
|
|
||||||
[property: JsonPropertyName("name")] string Name
|
|
||||||
// [property: JsonPropertyName("start_at")] DateTime StartAt,
|
|
||||||
// [property: JsonPropertyName("end_at")] DateTime EndAt,
|
|
||||||
// [property: JsonPropertyName("description")] string Description
|
|
||||||
);
|
|
||||||
23
Management/Models/CanvasModels/Modules/CanvasModule.cs
Normal file
23
Management/Models/CanvasModels/Modules/CanvasModule.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
namespace CanvasModel.Modules;
|
||||||
|
|
||||||
|
public record CanvasModule(
|
||||||
|
[property: JsonPropertyName("id")] ulong Id,
|
||||||
|
[property: JsonPropertyName("workflow_state")] string WorkflowState,
|
||||||
|
[property: JsonPropertyName("position")] uint Position,
|
||||||
|
[property: JsonPropertyName("name")] string Name,
|
||||||
|
[property: JsonPropertyName("unlock_at")] DateTime? UnlockAt,
|
||||||
|
[property: JsonPropertyName("require_sequential_progress")] bool? RequireSequentialProgress,
|
||||||
|
[property: JsonPropertyName("prerequisite_module_ids")] IEnumerable<ulong>? PrerequisiteModuleIds,
|
||||||
|
[property: JsonPropertyName("items_count")] uint ItemsCount,
|
||||||
|
[property: JsonPropertyName("items_url")] string ItemsUrl,
|
||||||
|
// [OptIn]
|
||||||
|
// [Enigmatic] // can be null if "the module is deemed too large", even if opted-in
|
||||||
|
[property: JsonPropertyName("items")]
|
||||||
|
IEnumerable<CanvasModuleItem>? Items,
|
||||||
|
[property: JsonPropertyName("state")] string? State, // todo make sure this,
|
||||||
|
// [OptIn]
|
||||||
|
[property: JsonPropertyName("completed_at")]
|
||||||
|
DateTime? CompletedAt,
|
||||||
|
[property: JsonPropertyName("publish_final_grade")] bool? PublishFinalGrade,
|
||||||
|
[property: JsonPropertyName("published")] bool? Published
|
||||||
|
);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace CanvasModel.Modules;
|
||||||
|
|
||||||
|
public record CanvasCompletionRequirement(
|
||||||
|
[property: JsonPropertyName("type")] string Type,
|
||||||
|
[property: JsonPropertyName("min_score")] double? MinScore,
|
||||||
|
[property: JsonPropertyName("completed")] bool? Completed
|
||||||
|
);
|
||||||
20
Management/Models/CanvasModels/Modules/CanvasModuleItem.cs
Normal file
20
Management/Models/CanvasModels/Modules/CanvasModuleItem.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
namespace CanvasModel.Modules;
|
||||||
|
|
||||||
|
public record CanvasModuleItem(
|
||||||
|
[property: JsonPropertyName("id")] ulong Id,
|
||||||
|
[property: JsonPropertyName("module_id")] ulong ModuleId,
|
||||||
|
[property: JsonPropertyName("position")] uint Position,
|
||||||
|
[property: JsonPropertyName("title")] string Title,
|
||||||
|
[property: JsonPropertyName("indent")] uint? Indent,
|
||||||
|
[property: JsonPropertyName("type")] string Type,
|
||||||
|
[property: JsonPropertyName("content_id")] ulong? ContentId,
|
||||||
|
[property: JsonPropertyName("html_url")] string HtmlUrl,
|
||||||
|
[property: JsonPropertyName("url")] string? Url,
|
||||||
|
[property: JsonPropertyName("page_url")] string? PageUrl,
|
||||||
|
[property: JsonPropertyName("external_url")] string? ExternalUrl,
|
||||||
|
[property: JsonPropertyName("new_tab")] bool NewTab,
|
||||||
|
// [OptIn]
|
||||||
|
[property: JsonPropertyName("completion_requirement")]
|
||||||
|
CanvasCompletionRequirement? CompletionRequirement,
|
||||||
|
[property: JsonPropertyName("published")] bool? Published
|
||||||
|
);
|
||||||
@@ -33,7 +33,7 @@ public record SubmissionModel
|
|||||||
string LatePolicyStatus,
|
string LatePolicyStatus,
|
||||||
|
|
||||||
[property: JsonPropertyName("assignment")]
|
[property: JsonPropertyName("assignment")]
|
||||||
AssignmentModel? Assignment = null,
|
CanvasAssignment? Assignment = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("course")]
|
[property: JsonPropertyName("course")]
|
||||||
CourseModel? Course = null,
|
CourseModel? Course = null,
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public record ActivityStreamObjectModel
|
|||||||
ulong? AssignmentId = null,
|
ulong? AssignmentId = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("assignment")]
|
[property: JsonPropertyName("assignment")]
|
||||||
AssignmentModel? Assignment = null,
|
CanvasAssignment? Assignment = null,
|
||||||
|
|
||||||
[property: JsonPropertyName("course")]
|
[property: JsonPropertyName("course")]
|
||||||
CourseModel? Course = null,
|
CourseModel? Course = null,
|
||||||
|
|||||||
@@ -5,4 +5,6 @@ public record LocalModule
|
|||||||
public string Name { get; init; } = string.Empty;
|
public string Name { get; init; } = string.Empty;
|
||||||
public IEnumerable<LocalAssignment> Assignments { get; init; } =
|
public IEnumerable<LocalAssignment> Assignments { get; init; } =
|
||||||
Enumerable.Empty<LocalAssignment>();
|
Enumerable.Empty<LocalAssignment>();
|
||||||
|
|
||||||
|
public ulong? CanvasId { get; set; } = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using CanvasModel;
|
using CanvasModel;
|
||||||
|
using CanvasModel.Assignments;
|
||||||
using CanvasModel.Courses;
|
using CanvasModel.Courses;
|
||||||
using CanvasModel.EnrollmentTerms;
|
using CanvasModel.EnrollmentTerms;
|
||||||
|
using CanvasModel.Modules;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
|
||||||
public interface ICanvasService
|
public interface ICanvasService
|
||||||
@@ -13,11 +15,9 @@ public class CanvasService : ICanvasService
|
|||||||
{
|
{
|
||||||
private const string BaseUrl = "https://snow.instructure.com/api/v1/";
|
private const string BaseUrl = "https://snow.instructure.com/api/v1/";
|
||||||
private readonly IWebRequestor webRequestor;
|
private readonly IWebRequestor webRequestor;
|
||||||
private string courseid { get; }
|
|
||||||
|
|
||||||
public CanvasService(IWebRequestor webRequestor)
|
public CanvasService(IWebRequestor webRequestor)
|
||||||
{
|
{
|
||||||
courseid = "774898";
|
|
||||||
this.webRequestor = webRequestor;
|
this.webRequestor = webRequestor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +54,26 @@ public class CanvasService : ICanvasService
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<CourseModule>> GetModules(ulong courseId)
|
public async Task<IEnumerable<CanvasAssignment>> GetAssignments(ulong courseId)
|
||||||
|
{
|
||||||
|
var url = $"courses/{courseId}/assignments ";
|
||||||
|
var request = new RestRequest(url);
|
||||||
|
var assignmentResponse = await PaginatedRequest<IEnumerable<CanvasAssignment>>(request);
|
||||||
|
return assignmentResponse.SelectMany(c => c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public async Task<CanvasAssignment> CreateAssignment(
|
||||||
|
|
||||||
|
// )
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
public async Task<IEnumerable<CanvasModule>> GetModules(ulong courseId)
|
||||||
{
|
{
|
||||||
var url = $"courses/{courseId}/modules";
|
var url = $"courses/{courseId}/modules";
|
||||||
var request = new RestRequest(url);
|
var request = new RestRequest(url);
|
||||||
var modules = await PaginatedRequest<IEnumerable<CourseModule>>(request);
|
var modules = await PaginatedRequest<IEnumerable<CanvasModule>>(request);
|
||||||
return modules.SelectMany(c => c).ToArray();
|
return modules.SelectMany(c => c).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
104
requests/assignment.http
Normal file
104
requests/assignment.http
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
###
|
||||||
|
get https://snow.instructure.com/api/v1/courses
|
||||||
|
Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
GET https://snow.instructure.com/api/v1/courses/705168
|
||||||
|
Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
|
||||||
|
|
||||||
|
###
|
||||||
|
POST https://snow.instructure.com/api/v1/courses/872095/assignments
|
||||||
|
Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
|
||||||
|
|
||||||
|
{"assignment":{"name:":"New Assignment","description:":"This is a new assignment"}}
|
||||||
|
|
||||||
|
###
|
||||||
|
POST https://snow.instructure.com/api/v1/courses/705168/assignments
|
||||||
|
Authorization: Bearer {{$dotenv CANVAS_TOKEN}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"assignment": {
|
||||||
|
"due_at":null,
|
||||||
|
"points_possible":0,
|
||||||
|
"assignment_group_id":"1805234",
|
||||||
|
"post_to_sis":false,
|
||||||
|
"graders_anonymous_to_graders":false,
|
||||||
|
"grader_comments_visible_to_graders":true,
|
||||||
|
"grader_names_visible_to_final_grader":true,
|
||||||
|
"annotatable_attachment_id":"",
|
||||||
|
"secure_params":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsdGlfYXNzaWdubWVudF9pZCI6ImIxZWNhNjFjLWJlZWQtNGJjMC1hNTBiLWJkYmNiOTA3MjNiOSIsImx0aV9hc3NpZ25tZW50X2Rlc2NyaXB0aW9uIjpudWxsfQ.jzOL4gSSsNkq7m3S7kl9RbbqsdjK7FzhhepqyHWuTAk",
|
||||||
|
"lti_context_id":null,
|
||||||
|
"course_id":"872095",
|
||||||
|
"name":"test1",
|
||||||
|
"submission_types":["online_text_entry"],
|
||||||
|
"has_submitted_submissions":false,
|
||||||
|
"due_date_required":false,
|
||||||
|
"max_name_length":255,
|
||||||
|
"allowed_attempts":"-1",
|
||||||
|
"in_closed_grading_period":false,
|
||||||
|
"graded_submissions_exist":false,
|
||||||
|
"omit_from_final_grade":"0",
|
||||||
|
"hide_in_gradebook":false,
|
||||||
|
"turnitin_enabled":"0",
|
||||||
|
"turnitin_settings": {
|
||||||
|
"s_paper_check":true,
|
||||||
|
"originality_report_visibility":"immediate",
|
||||||
|
"internet_check":true,
|
||||||
|
"exclude_biblio":true,
|
||||||
|
"exclude_quoted":true,
|
||||||
|
"journal_check":true,
|
||||||
|
"exclude_small_matches_type":null,
|
||||||
|
"exclude_small_matches_value":0,
|
||||||
|
"submit_papers_to":true
|
||||||
|
},
|
||||||
|
"is_quiz_assignment":false,
|
||||||
|
"can_duplicate":true,
|
||||||
|
"original_course_id":null,
|
||||||
|
"original_assignment_id":null,
|
||||||
|
"original_lti_resource_link_id":null,
|
||||||
|
"original_assignment_name":null,
|
||||||
|
"original_quiz_id":null,
|
||||||
|
"workflow_state":"unpublished",
|
||||||
|
"important_dates":false,
|
||||||
|
"assignment_overrides":[],
|
||||||
|
"publishable":true,
|
||||||
|
"hidden":false,
|
||||||
|
"unpublishable":true,
|
||||||
|
"grading_type":"points",
|
||||||
|
"submission_type":"online",
|
||||||
|
"only_visible_to_overrides":false,
|
||||||
|
"description":"",
|
||||||
|
"grading_standard_id":"",
|
||||||
|
"allowed_extensions":null,
|
||||||
|
"vericite_enabled":"0",
|
||||||
|
"external_tool_tag_attributes": {
|
||||||
|
"external_data":"",
|
||||||
|
"custom_params":"",
|
||||||
|
"line_item":"",
|
||||||
|
"link_settings": {
|
||||||
|
"selection_width":"",
|
||||||
|
"selection_height":""
|
||||||
|
},
|
||||||
|
"url":"",
|
||||||
|
"content_type":"",
|
||||||
|
"content_id":"",
|
||||||
|
"new_tab":"0"
|
||||||
|
},
|
||||||
|
"similarityDetectionTool":"None",
|
||||||
|
"configuration_tool_type":"",
|
||||||
|
"grade_group_students_individually":false,
|
||||||
|
"group_category_id":null,
|
||||||
|
"peer_reviews":"0",
|
||||||
|
"automatic_peer_reviews":"0",
|
||||||
|
"peer_review_count":0,
|
||||||
|
"peer_reviews_assign_at":null,
|
||||||
|
"intra_group_peer_reviews":"0",
|
||||||
|
"anonymous_peer_reviews":"0",
|
||||||
|
"notify_of_update":"0",
|
||||||
|
"lock_at":null,
|
||||||
|
"unlock_at":null
|
||||||
|
}
|
||||||
|
}
|
||||||
35
tmp.json
35
tmp.json
@@ -1,35 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": 753,
|
|
||||||
"name": "Summer 2023",
|
|
||||||
"sis_term_id": null,
|
|
||||||
"sis_import_id": null,
|
|
||||||
"start_at": "2023-05-10T06:00:00Z",
|
|
||||||
"end_at": "2023-07-29T05:59:59Z",
|
|
||||||
"grading_period_group_id": null,
|
|
||||||
"workflow_state": "active",
|
|
||||||
"overrides": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 751,
|
|
||||||
"name": "Fall 2023",
|
|
||||||
"sis_term_id": null,
|
|
||||||
"sis_import_id": null,
|
|
||||||
"start_at": "2023-08-21T06:00:00Z",
|
|
||||||
"end_at": "2023-12-15T06:59:59Z",
|
|
||||||
"grading_period_group_id": null,
|
|
||||||
"workflow_state": "active",
|
|
||||||
"overrides": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 773,
|
|
||||||
"name": "Spring 2024",
|
|
||||||
"sis_term_id": null,
|
|
||||||
"sis_import_id": null,
|
|
||||||
"start_at": "2024-01-02T00:00:00Z",
|
|
||||||
"end_at": "2024-04-26T00:00:00Z",
|
|
||||||
"grading_period_group_id": null,
|
|
||||||
"workflow_state": "active",
|
|
||||||
"overrides": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Reference in New Issue
Block a user