added delete support for assignments

This commit is contained in:
2023-08-07 18:41:04 -06:00
parent 224664c7a3
commit 7a2ee58617
9 changed files with 208 additions and 40 deletions

12
.editorconfig Normal file
View File

@@ -0,0 +1,12 @@
# Top-most EditorConfig file
root = true
[*.cs]
dotnet_naming_rule.methods_must_be_camel_case.severity = warning
dotnet_naming_rule.methods_must_be_camel_case.symbols = private_methods
dotnet_naming_rule.methods_must_be_camel_case.style = camel_case_style
dotnet_naming_symbols.private_methods.applicable_kinds = method
dotnet_naming_symbols.private_methods.applicable_accessibilities = private
dotnet_naming_style.camel_case_style.capitalization = camel_case

View File

@@ -1,6 +1,7 @@
@using Management.Web.Shared.Components @using Management.Web.Shared.Components
@inject CoursePlanner planner @inject CoursePlanner planner
@inject CanvasService canvas
@code { @code {
@@ -106,6 +107,40 @@
submissionTypes = newTypes; submissionTypes = newTypes;
StateHasChanged(); StateHasChanged();
} }
private async Task HandleDelete()
{
if(planner.LocalCourse != null)
{
var assignment = Assignment;
var currentModule = planner
.LocalCourse
.Modules
.First(m =>
m.Assignments
.Select(a => a.Id)
.Contains(Assignment.Id)
) ?? throw new Exception("handling assignment delete, could not find module");
var newModules = planner.LocalCourse.Modules.Select(m =>
m.Name == currentModule.Name
? m with
{
Assignments = m.Assignments.Where(a => a.Id != assignment.Id).ToArray()
}
: m
).ToArray();
planner.LocalCourse = planner.LocalCourse with
{
Modules = newModules
};
if(assignment.CanvasId != null && planner.LocalCourse.CanvasId != null)
{
ulong courseId = planner.LocalCourse.CanvasId ?? throw new Exception("cannot delete if no course id");
await canvas.Assignments.Delete(courseId, assignment);
}
}
}
} }
<Modal @ref="AssignmentModal" OnHide="@(() => OnHide())"> <Modal @ref="AssignmentModal" OnHide="@(() => OnHide())">
@@ -156,6 +191,11 @@
</form> </form>
</Body> </Body>
<Footer> <Footer>
<ConfirmationModal
Label="Delete"
Class="btn btn-danger"
OnConfirmAsync="HandleDelete"
/>
<button class="btn btn-primary" @onclick="submitHandler"> <button class="btn btn-primary" @onclick="submitHandler">
Save Save
</button> </button>

View File

@@ -4,17 +4,19 @@
{ {
private IEnumerable<string> _types { get; set; } = Enumerable.Empty<string>(); private IEnumerable<string> _types { get; set; } = Enumerable.Empty<string>();
[Parameter, EditorRequired] [Parameter, EditorRequired]
public IEnumerable<string> Types { public IEnumerable<string> Types { get; set; } = Enumerable.Empty<string>();
get => _types;
set [Parameter, EditorRequired]
public Action<IEnumerable<string>> SetTypes { get; set; } = (_) => {};
protected override void OnParametersSet()
{
if (!Types.SequenceEqual(_types))
{ {
_types = value; _types = Types;
renderKey++; renderKey++;
} }
} }
[Parameter, EditorRequired]
public Action<IEnumerable<string>> SetTypes { get; set; } = (_) => {};
private string getLabel(string type) private string getLabel(string type)
{ {
return type.ToString().Replace("_", "") + "switch"; return type.ToString().Replace("_", "") + "switch";
@@ -23,8 +25,8 @@
private bool discussionIsSelected private bool discussionIsSelected
{ {
get => Types.FirstOrDefault( get => Types.FirstOrDefault(
t => t == SubmissionType.DISCUSSION_TOPIC t => t == SubmissionType.DISCUSSION_TOPIC
) != null; ) != null;
} }
private int renderKey {get; set; } = 1; private int renderKey {get; set; } = 1;
} }

View File

@@ -0,0 +1,81 @@
@using Management.Web.Shared.Components
@namespace Management.Web.Shared.Components
@code {
[Parameter]
public Action? OnConfirm { get; init; }
[Parameter]
public Action? OnDeny { get; init; }
[Parameter]
public Func<Task>? OnConfirmAsync { get; init; }
[Parameter]
public Func<Task>? OnDenyAsync { get; init; }
[Parameter]
[EditorRequired]
public string Label { get; set; } = "";
[Parameter]
[EditorRequired]
public string Class { get; set; } = "";
private Modal? modal { get; set; } = null;
private bool doingAsyncThings { get; set; } = false;
private async Task HandleDeny()
{
if(OnDeny != null)
OnDeny();
if(OnDenyAsync != null)
{
doingAsyncThings = true;
await OnDenyAsync();
doingAsyncThings = false;
}
modal?.Hide();
}
private async Task HandleConfirm()
{
if(OnConfirm != null)
OnConfirm();
if(OnConfirmAsync != null)
{
doingAsyncThings = true;
await OnConfirmAsync();
doingAsyncThings = false;
}
modal?.Hide();
}
}
<button
class="btn btn-danger"
@onclick="() => modal?.Show()"
>
@Label
</button>
<Modal @ref="modal">
<Title>Are you sure you want to @Label?</Title>
<Body>
<div class="text-center">
<button
class="btn btn-secondary"
@onclick="HandleDeny"
>
no
</button>
<button
class="btn btn-primary"
@onclick="HandleConfirm"
>
yes
</button>
</div>
</Body>
<Footer>
@if(doingAsyncThings)
{
<Spinnner />
}
</Footer>
</Modal>

View File

@@ -127,9 +127,14 @@ public static partial class CoursePlannerSyncronizationExtensions
if (!quiet) if (!quiet)
{ {
if (!dueDatesSame) if (!dueDatesSame)
{
Console.WriteLine( Console.WriteLine(
$"Due dates different for {localAssignment.Name}, local: {localAssignment.DueAt}, in canvas {canvasAssignment.DueAt}" $"Due dates different for {localAssignment.Name}, local: {localAssignment.DueAt}, in canvas {canvasAssignment.DueAt}"
); );
Console.WriteLine(JsonSerializer.Serialize(localAssignment.DueAt));
Console.WriteLine(JsonSerializer.Serialize(canvasAssignment.DueAt));
}
if (!descriptionSame) if (!descriptionSame)
{ {

View File

@@ -16,8 +16,10 @@ public static class CoursePlannerExtensions
.OrderBy(a => a.DueAt) .OrderBy(a => a.DueAt)
.DistinctBy(a => a.Id) .DistinctBy(a => a.Id)
.Select(a => a.validateSubmissionTypes()) .Select(a => a.validateSubmissionTypes())
.Select(a => a.validateDates())
.ToArray()
} }
); ).ToArray();
var cleanStartDay = new DateTime( var cleanStartDay = new DateTime(
incomingCourse.StartDate.Year, incomingCourse.StartDate.Year,
@@ -109,4 +111,13 @@ public static class CoursePlannerExtensions
}; };
return assignment; return assignment;
} }
public static LocalAssignment validateDates(this LocalAssignment assignment)
{
return assignment with
{
DueAt=assignment.DueAt.AddMilliseconds(0).AddMilliseconds(0),
LockAt=assignment.LockAt?.AddMilliseconds(0).AddMilliseconds(0)
};
}
} }

View File

@@ -6,7 +6,7 @@ namespace Management.Services.Canvas;
public class CanvasAssignmentService public class CanvasAssignmentService
{ {
private IWebRequestor webRequestor; private readonly IWebRequestor webRequestor;
private readonly CanvasServiceUtils utils; private readonly CanvasServiceUtils utils;
public CanvasAssignmentService(IWebRequestor webRequestor, CanvasServiceUtils utils) public CanvasAssignmentService(IWebRequestor webRequestor, CanvasServiceUtils utils)
@@ -34,7 +34,7 @@ public class CanvasAssignmentService
string htmlDescription string htmlDescription
) )
{ {
System.Console.WriteLine($"creating assignment: {localAssignment.Name}"); Console.WriteLine($"creating assignment: {localAssignment.Name}");
var url = $"courses/{courseId}/assignments"; var url = $"courses/{courseId}/assignments";
var request = new RestRequest(url); var request = new RestRequest(url);
var body = new CanvasAssignmentCreationRequest() var body = new CanvasAssignmentCreationRequest()
@@ -62,7 +62,7 @@ public class CanvasAssignmentService
public async Task Update(ulong courseId, LocalAssignment localAssignment, string htmlDescription) public async Task Update(ulong courseId, LocalAssignment localAssignment, string htmlDescription)
{ {
System.Console.WriteLine($"updating assignment: {localAssignment.Name}"); Console.WriteLine($"updating assignment: {localAssignment.Name}");
var url = $"courses/{courseId}/assignments/{localAssignment.CanvasId}"; var url = $"courses/{courseId}/assignments/{localAssignment.CanvasId}";
var request = new RestRequest(url); var request = new RestRequest(url);
var body = new CanvasAssignmentCreationRequest() var body = new CanvasAssignmentCreationRequest()
@@ -82,6 +82,19 @@ public class CanvasAssignmentService
await CreateRubric(courseId, localAssignment); await CreateRubric(courseId, localAssignment);
} }
public async Task Delete(ulong courseId, LocalAssignment assignment)
{
Console.WriteLine($"deleting assignment from canvas {assignment.Name}");
var url = $"courses/{courseId}/assignments/{assignment.CanvasId}";
var request = new RestRequest(url);
var response = await webRequestor.DeleteAsync(request);
if (!response.IsSuccessful)
{
Console.WriteLine(url);
throw new Exception("Failed to delete assignment");
}
}
public async Task CreateRubric(ulong courseId, LocalAssignment localAssignment) public async Task CreateRubric(ulong courseId, LocalAssignment localAssignment)
{ {
if (localAssignment.CanvasId == null) if (localAssignment.CanvasId == null)
@@ -101,7 +114,7 @@ public class CanvasAssignmentService
{ {
description = rubricItem.Label, description = rubricItem.Label,
points = rubricItem.Points, points = rubricItem.Points,
ratings = ratings ratings
}; };
i++; i++;
} }
@@ -130,9 +143,9 @@ public class CanvasAssignmentService
var rubricCreationRequest = new RestRequest(creationUrl); var rubricCreationRequest = new RestRequest(creationUrl);
rubricCreationRequest.AddBody(body); rubricCreationRequest.AddBody(body);
rubricCreationRequest.AddHeader("Content-Type", "application/json"); rubricCreationRequest.AddHeader("Content-Type", "application/json");
var (rubricCreationResponse, _) = await webRequestor.PostAsync<CanvasRubricCreationResponse>(
var (rubricCreationResponse, creationResponse) = rubricCreationRequest
await webRequestor.PostAsync<CanvasRubricCreationResponse>(rubricCreationRequest); );
if (rubricCreationResponse == null) if (rubricCreationResponse == null)
throw new Exception("failed to create rubric before association"); throw new Exception("failed to create rubric before association");
@@ -145,8 +158,6 @@ public class CanvasAssignmentService
var pointAdjustmentRequest = new RestRequest(adjustmentUrl); var pointAdjustmentRequest = new RestRequest(adjustmentUrl);
pointAdjustmentRequest.AddBody(assignmentPointCorrectionBody); pointAdjustmentRequest.AddBody(assignmentPointCorrectionBody);
pointAdjustmentRequest.AddHeader("Content-Type", "application/json"); pointAdjustmentRequest.AddHeader("Content-Type", "application/json");
var (updatedAssignment, adjustmentResponse) = await webRequestor.PutAsync<CanvasAssignment>( var (_, _) = await webRequestor.PutAsync<CanvasAssignment>(pointAdjustmentRequest);
pointAdjustmentRequest
);
} }
} }

View File

@@ -8,4 +8,5 @@ public interface IWebRequestor
Task<(T?, RestResponse)> PostAsync<T>(RestRequest request); Task<(T?, RestResponse)> PostAsync<T>(RestRequest request);
Task<RestResponse> PutAsync(RestRequest request); Task<RestResponse> PutAsync(RestRequest request);
Task<(T?, RestResponse)> PutAsync<T>(RestRequest request); Task<(T?, RestResponse)> PutAsync<T>(RestRequest request);
Task<RestResponse> DeleteAsync(RestRequest request);
} }

View File

@@ -18,13 +18,13 @@ public class WebRequestor : IWebRequestor
public async Task<(T[]?, RestResponse)> GetManyAsync<T>(RestRequest request) public async Task<(T[]?, RestResponse)> GetManyAsync<T>(RestRequest request)
{ {
var response = await client.ExecuteGetAsync(request); var response = await client.ExecuteGetAsync(request);
return (Deserialize<T[]>(response), response); return (deserialize<T[]>(response), response);
} }
public async Task<(T?, RestResponse)> GetAsync<T>(RestRequest request) public async Task<(T?, RestResponse)> GetAsync<T>(RestRequest request)
{ {
var response = await client.ExecuteGetAsync(request); var response = await client.ExecuteGetAsync(request);
return (Deserialize<T>(response), response); return (deserialize<T>(response), response);
} }
public async Task<RestResponse> PostAsync(RestRequest request) public async Task<RestResponse> PostAsync(RestRequest request)
@@ -32,9 +32,9 @@ public class WebRequestor : IWebRequestor
var response = await client.ExecutePostAsync(request); var response = await client.ExecutePostAsync(request);
if (!response.IsSuccessful) if (!response.IsSuccessful)
{ {
System.Console.WriteLine(response.Content); Console.WriteLine(response.Content);
System.Console.WriteLine(response.ResponseUri); Console.WriteLine(response.ResponseUri);
System.Console.WriteLine("error with response"); Console.WriteLine("error with response");
throw new Exception("error with response"); throw new Exception("error with response");
} }
return response; return response;
@@ -43,7 +43,7 @@ public class WebRequestor : IWebRequestor
public async Task<(T?, RestResponse)> PostAsync<T>(RestRequest request) public async Task<(T?, RestResponse)> PostAsync<T>(RestRequest request)
{ {
var response = await client.ExecutePostAsync(request); var response = await client.ExecutePostAsync(request);
return (Deserialize<T>(response), response); return (deserialize<T>(response), response);
} }
public async Task<RestResponse> PutAsync(RestRequest request) public async Task<RestResponse> PutAsync(RestRequest request)
@@ -51,9 +51,9 @@ public class WebRequestor : IWebRequestor
var response = await client.ExecutePutAsync(request); var response = await client.ExecutePutAsync(request);
// if (!response.IsSuccessful) // if (!response.IsSuccessful)
// { // {
// System.Console.WriteLine(response.Content); // Console.WriteLine(response.Content);
// System.Console.WriteLine(response.ResponseUri); // Console.WriteLine(response.ResponseUri);
// System.Console.WriteLine("error with response"); // Console.WriteLine("error with response");
// throw new Exception("error with response"); // throw new Exception("error with response");
// } // }
return response; return response;
@@ -62,17 +62,22 @@ public class WebRequestor : IWebRequestor
public async Task<(T?, RestResponse)> PutAsync<T>(RestRequest request) public async Task<(T?, RestResponse)> PutAsync<T>(RestRequest request)
{ {
var response = await client.ExecutePutAsync(request); var response = await client.ExecutePutAsync(request);
return (Deserialize<T>(response), response); return (deserialize<T>(response), response);
} }
private T? Deserialize<T>(RestResponse response) public async Task<RestResponse> DeleteAsync(RestRequest request)
{
return await client.DeleteAsync(request);
}
private static T? deserialize<T>(RestResponse response)
{ {
if (!response.IsSuccessful) if (!response.IsSuccessful)
{ {
System.Console.WriteLine(response.Content); Console.WriteLine(response.Content);
System.Console.WriteLine(response.ResponseUri); Console.WriteLine(response.ResponseUri);
System.Console.WriteLine(response.ErrorMessage); Console.WriteLine(response.ErrorMessage);
System.Console.WriteLine("error with response"); Console.WriteLine("error with response");
// Console.WriteLine(JsonSerializer.Serialize(response)); // Console.WriteLine(JsonSerializer.Serialize(response));
Console.WriteLine(JsonSerializer.Serialize(response.Request?.Parameters)); Console.WriteLine(JsonSerializer.Serialize(response.Request?.Parameters));
throw new Exception($"error with response to {response.ResponseUri} {response.StatusCode}"); throw new Exception($"error with response to {response.ResponseUri} {response.StatusCode}");
@@ -83,21 +88,21 @@ public class WebRequestor : IWebRequestor
if (data == null) if (data == null)
{ {
System.Console.WriteLine(response.Content); Console.WriteLine(response.Content);
System.Console.WriteLine(response.ResponseUri); Console.WriteLine(response.ResponseUri);
System.Console.WriteLine("could not parse response, got empty object"); Console.WriteLine("could not parse response, got empty object");
} }
return data; return data;
} }
catch (System.NotSupportedException ) catch (NotSupportedException)
{ {
Console.WriteLine(response.Content); Console.WriteLine(response.Content);
throw; throw;
} }
catch (JsonException) catch (JsonException)
{ {
System.Console.WriteLine(response.ResponseUri); Console.WriteLine(response.ResponseUri);
System.Console.WriteLine(response.Content); Console.WriteLine(response.Content);
Console.WriteLine($"An error occurred during deserialization"); Console.WriteLine($"An error occurred during deserialization");
throw; throw;
} }