mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
updated assignment form to be markdown
This commit is contained in:
@@ -21,7 +21,7 @@ public class AssignmentMarkdownTests
|
|||||||
|
|
||||||
var assignmentMarkdown = assignment.ToMarkdown();
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
}
|
}
|
||||||
[Test]
|
[Test]
|
||||||
@@ -40,7 +40,7 @@ public class AssignmentMarkdownTests
|
|||||||
|
|
||||||
var assignmentMarkdown = assignment.ToMarkdown();
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
}
|
}
|
||||||
[Test]
|
[Test]
|
||||||
@@ -62,9 +62,10 @@ public class AssignmentMarkdownTests
|
|||||||
|
|
||||||
var assignmentMarkdown = assignment.ToMarkdown();
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AssignmentWithoutLockAtDate_CanBeParsed()
|
public void AssignmentWithoutLockAtDate_CanBeParsed()
|
||||||
{
|
{
|
||||||
@@ -84,9 +85,10 @@ public class AssignmentMarkdownTests
|
|||||||
|
|
||||||
var assignmentMarkdown = assignment.ToMarkdown();
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AssignmentWithoutDescription_CanBeParsed()
|
public void AssignmentWithoutDescription_CanBeParsed()
|
||||||
{
|
{
|
||||||
@@ -106,7 +108,7 @@ public class AssignmentMarkdownTests
|
|||||||
|
|
||||||
var assignmentMarkdown = assignment.ToMarkdown();
|
var assignmentMarkdown = assignment.ToMarkdown();
|
||||||
|
|
||||||
var parsedAssignment = LocalAssignment.FromMarkdown(assignmentMarkdown);
|
var parsedAssignment = LocalAssignment.ParseMarkdown(assignmentMarkdown);
|
||||||
parsedAssignment.Should().BeEquivalentTo(assignment);
|
parsedAssignment.Should().BeEquivalentTo(assignment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
@using Markdig
|
|
||||||
|
|
||||||
@inject CoursePlanner planner
|
|
||||||
@inject AssignmentEditorContext assignmentContext
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
assignmentContext.StateHasChanged += reload;
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
private void reload()
|
|
||||||
{
|
|
||||||
if (assignmentContext.Assignment != null)
|
|
||||||
{
|
|
||||||
if(description == string.Empty)
|
|
||||||
{
|
|
||||||
description = assignmentContext.Assignment.Description;
|
|
||||||
descriptionForPreview = description;
|
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
assignmentContext.StateHasChanged -= reload;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string description { get; set; } = string.Empty;
|
|
||||||
private string descriptionForPreview { get; set; } = string.Empty;
|
|
||||||
public bool? UseTemplate { get; set; } = null;
|
|
||||||
|
|
||||||
public string? TemplateId { get; set; }
|
|
||||||
|
|
||||||
public Dictionary<string, string> VariableValues { get; set; } = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
private AssignmentTemplate? selectedTemplate =>
|
|
||||||
planner
|
|
||||||
.LocalCourse?
|
|
||||||
.Settings
|
|
||||||
.AssignmentTemplates
|
|
||||||
.FirstOrDefault(t => t.Id == TemplateId);
|
|
||||||
|
|
||||||
private void handleNewDescription(string newDescription)
|
|
||||||
{
|
|
||||||
description = newDescription;
|
|
||||||
if (newDescription != string.Empty)
|
|
||||||
{
|
|
||||||
descriptionForPreview = newDescription;
|
|
||||||
if (assignmentContext.Assignment != null)
|
|
||||||
{
|
|
||||||
var newAssignment = assignmentContext.Assignment with
|
|
||||||
{
|
|
||||||
Description = newDescription
|
|
||||||
};
|
|
||||||
assignmentContext.SaveAssignment(newAssignment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private MarkupString preview { get => (MarkupString)Markdown.ToHtml(descriptionForPreview); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@if(assignmentContext.Assignment != null && planner.LocalCourse != null)
|
|
||||||
{
|
|
||||||
<div class="row h-100">
|
|
||||||
<div class="col-6">
|
|
||||||
@* <textarea
|
|
||||||
id="description"
|
|
||||||
class="form-control h-100"
|
|
||||||
rows=12
|
|
||||||
@bind="description"
|
|
||||||
@oninput="handleNewDescription"
|
|
||||||
/> *@
|
|
||||||
|
|
||||||
<MonacoTextArea Value="@description" OnChange="@handleNewDescription" />
|
|
||||||
</div>
|
|
||||||
<div class="col-6" @key="descriptionForPreview" >
|
|
||||||
@((MarkupString)Markdown.ToHtml(descriptionForPreview))
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
@@ -182,16 +182,16 @@
|
|||||||
SelectedOption="selectedAssignmentGroup"
|
SelectedOption="selectedAssignmentGroup"
|
||||||
/>
|
/>
|
||||||
<div class="m-1 flex-grow-1">
|
<div class="m-1 flex-grow-1">
|
||||||
<AssignmentDescriptionEditor />
|
<AssignmentMarkdownEditor />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
@* <div class="container">
|
||||||
<RubricMarkdownEditor />
|
<RubricMarkdownEditor />
|
||||||
<hr>
|
<hr>
|
||||||
<div class="mx-5 px-5">
|
<div class="mx-5 px-5">
|
||||||
<SubmissionTypeSelector />
|
<SubmissionTypeSelector />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> *@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
@using Markdig
|
||||||
|
|
||||||
|
@inject CoursePlanner planner
|
||||||
|
@inject AssignmentEditorContext assignmentContext
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
assignmentContext.StateHasChanged += reload;
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
private void reload()
|
||||||
|
{
|
||||||
|
if (assignmentContext.Assignment != null)
|
||||||
|
{
|
||||||
|
if(rawText == string.Empty)
|
||||||
|
{
|
||||||
|
rawText = assignmentContext.Assignment.ToMarkdown();
|
||||||
|
this.InvokeAsync(this.StateHasChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
assignmentContext.StateHasChanged -= reload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string rawText { get; set; } = string.Empty;
|
||||||
|
private string? error = null;
|
||||||
|
public bool? UseTemplate { get; set; } = null;
|
||||||
|
|
||||||
|
public string? TemplateId { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string> VariableValues { get; set; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
private AssignmentTemplate? selectedTemplate =>
|
||||||
|
planner
|
||||||
|
.LocalCourse?
|
||||||
|
.Settings
|
||||||
|
.AssignmentTemplates
|
||||||
|
.FirstOrDefault(t => t.Id == TemplateId);
|
||||||
|
|
||||||
|
private void handleChange(string newRawAssignment)
|
||||||
|
{
|
||||||
|
rawText = newRawAssignment;
|
||||||
|
if (newRawAssignment != string.Empty)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var parsed = LocalAssignment.ParseMarkdown(newRawAssignment);
|
||||||
|
error = null;
|
||||||
|
assignmentContext.SaveAssignment(parsed);
|
||||||
|
}
|
||||||
|
catch(AssignmentMarkdownParseException e)
|
||||||
|
{
|
||||||
|
error = e.Message;
|
||||||
|
}
|
||||||
|
catch(RubricMarkdownParseException e)
|
||||||
|
{
|
||||||
|
error = e.Message;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@* if (assignmentContext.Assignment != null)
|
||||||
|
{
|
||||||
|
var newAssignment = assignmentContext.Assignment with
|
||||||
|
{
|
||||||
|
Description = newRawAssignment
|
||||||
|
};
|
||||||
|
assignmentContext.SaveAssignment(newAssignment);
|
||||||
|
} *@
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MarkupString preview { get => (MarkupString)Markdown.ToHtml(assignmentContext.Assignment.Description); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(assignmentContext.Assignment != null && planner.LocalCourse != null)
|
||||||
|
{
|
||||||
|
<div class="row h-100">
|
||||||
|
<div class="col-6">
|
||||||
|
@* <textarea
|
||||||
|
id="description"
|
||||||
|
class="form-control h-100"
|
||||||
|
rows=12
|
||||||
|
@bind="description"
|
||||||
|
@oninput="handleNewDescription"
|
||||||
|
/> *@
|
||||||
|
|
||||||
|
<MonacoTextArea Value="@rawText" OnChange="@handleChange" />
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
@if (error != null)
|
||||||
|
{
|
||||||
|
<p class="text-danger text-truncate">Error: @error</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<div>Due At: @assignmentContext.Assignment.DueAt</div>
|
||||||
|
<div>Lock At: @assignmentContext.Assignment.LockAt</div>
|
||||||
|
<div>Assignment Group Name @assignmentContext.Assignment.LocalAssignmentGroupName</div>
|
||||||
|
<div>Submission Types</div>
|
||||||
|
<ul>
|
||||||
|
@foreach(var t in assignmentContext.Assignment.SubmissionTypes)
|
||||||
|
{
|
||||||
|
<li>@t</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
<div>
|
||||||
|
@(preview)
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<RubricDisplay />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
@using Management.Web.Shared.Components
|
||||||
|
|
||||||
|
@inject CoursePlanner planner
|
||||||
|
@inject AssignmentEditorContext assignmentContext
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private int rubricReloadKey = 0;
|
||||||
|
|
||||||
|
private string? error { get; set; } = null;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
assignmentContext.StateHasChanged += reload;
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
private void reload()
|
||||||
|
{
|
||||||
|
this.InvokeAsync(this.StateHasChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
assignmentContext.StateHasChanged -= reload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int requiredPoints => assignmentContext.Assignment.Rubric.Where(r => !r.IsExtraCredit).Select(r => r.Points).Sum();
|
||||||
|
private int extraCreditPoints => assignmentContext.Assignment.Rubric.Where(r => r.IsExtraCredit).Select(r => r.Points).Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<h4 class="text-center">Rubric</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (error != null)
|
||||||
|
{
|
||||||
|
<p class="text-danger text-truncate">Error: @error</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div class="row border-bottom">
|
||||||
|
<div class="col-6 text-end">Label</div>
|
||||||
|
<div class="col-3 text-center">Points</div>
|
||||||
|
<div class="col-3 text-center">Extra Credit</div>
|
||||||
|
</div>
|
||||||
|
@foreach (var item in assignmentContext.Assignment.Rubric)
|
||||||
|
{
|
||||||
|
<div class="row border-bottom">
|
||||||
|
<div class="col-6 text-end">@item.Label</div>
|
||||||
|
<div class="col-3 text-center">@item.Points</div>
|
||||||
|
<div class="col-3 text-center">@item.IsExtraCredit</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="text-end">
|
||||||
|
<div>
|
||||||
|
Required Points: @requiredPoints
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Extra Credit Points @extraCreditPoints
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
@using Management.Web.Shared.Components
|
|
||||||
|
|
||||||
@inject CoursePlanner planner
|
|
||||||
@inject AssignmentEditorContext assignmentContext
|
|
||||||
|
|
||||||
@code
|
|
||||||
{
|
|
||||||
private IEnumerable<RubricItem> displayRubric { get; set; } = new RubricItem[] { };
|
|
||||||
private string _rubricText = "";
|
|
||||||
private string rubricText
|
|
||||||
{
|
|
||||||
get => _rubricText;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_rubricText = value;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var parsedRubric = LocalAssignment.ParseRubricMarkdown(value);
|
|
||||||
displayRubric = parsedRubric;
|
|
||||||
error = null;
|
|
||||||
if (assignmentContext.Assignment != null)
|
|
||||||
{
|
|
||||||
var newAssignment = assignmentContext.Assignment with
|
|
||||||
{
|
|
||||||
Rubric = parsedRubric,
|
|
||||||
};
|
|
||||||
assignmentContext.SaveAssignment(newAssignment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (RubricMarkdownParseException parseError)
|
|
||||||
{
|
|
||||||
error = parseError.Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private int rubricReloadKey = 0;
|
|
||||||
|
|
||||||
private string? error { get; set; } = null;
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
assignmentContext.StateHasChanged += reload;
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
private void reload()
|
|
||||||
{
|
|
||||||
if (assignmentContext.Assignment != null)
|
|
||||||
{
|
|
||||||
if (rubricText == string.Empty)
|
|
||||||
{
|
|
||||||
rubricText = assignmentContext.Assignment.RubricToMarkdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
assignmentContext.StateHasChanged -= reload;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int requiredPoints => displayRubric.Where(r => !r.IsExtraCredit).Select(r => r.Points).Sum();
|
|
||||||
private int extraCreditPoints => displayRubric.Where(r => r.IsExtraCredit).Select(r => r.Points).Sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<h4 class="text-center">Rubric</h4>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-6">
|
|
||||||
@* <textarea id="description" class="form-control h-100" rows=12 @bind="rubricText" @bind:event="oninput" /> *@
|
|
||||||
<MonacoTextArea Value="@rubricText" OnChange="@((t) => rubricText = t)" />
|
|
||||||
</div>
|
|
||||||
<div class="col-6">
|
|
||||||
@if (error != null)
|
|
||||||
{
|
|
||||||
<p class="text-danger text-truncate">Error: @error</p>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="row border-bottom">
|
|
||||||
<div class="col-6 text-end">Label</div>
|
|
||||||
<div class="col-3 text-center">Points</div>
|
|
||||||
<div class="col-3 text-center">Extra Credit</div>
|
|
||||||
</div>
|
|
||||||
@foreach (var item in displayRubric)
|
|
||||||
{
|
|
||||||
<div class="row border-bottom">
|
|
||||||
<div class="col-6 text-end">@item.Label</div>
|
|
||||||
<div class="col-3 text-center">@item.Points</div>
|
|
||||||
<div class="col-3 text-center">@item.IsExtraCredit</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div class="text-end">
|
|
||||||
<div>
|
|
||||||
Required Points: @requiredPoints
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Extra Credit Points @extraCreditPoints
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
Description = "",
|
Description = "",
|
||||||
@* LockAtDueDate = true, *@
|
@* LockAtDueDate = true, *@
|
||||||
Rubric = new RubricItem[] { },
|
Rubric = new RubricItem[] { },
|
||||||
LockAt = DateTime.Now,
|
LockAt = null,
|
||||||
DueAt = DateTime.Now,
|
DueAt = DateTime.Now,
|
||||||
SubmissionTypes = new string[] { AssignmentSubmissionType.ONLINE_TEXT_ENTRY },
|
SubmissionTypes = new string[] { AssignmentSubmissionType.ONLINE_TEXT_ENTRY },
|
||||||
LocalAssignmentGroupName = selectedAssignmentGroup?.Name,
|
LocalAssignmentGroupName = selectedAssignmentGroup?.Name,
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public record LocalAssignment
|
|||||||
return yaml;
|
return yaml;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LocalAssignment FromMarkdown(string input)
|
public static LocalAssignment ParseMarkdown(string input)
|
||||||
{
|
{
|
||||||
var settingsString = input.Split("---")[0];
|
var settingsString = input.Split("---")[0];
|
||||||
var (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt) = parseSettings(settingsString);
|
var (name, localAssignmentGroupName, submissionTypes, dueAt, lockAt) = parseSettings(settingsString);
|
||||||
@@ -238,4 +238,8 @@ public record LocalAssignment
|
|||||||
public class RubricMarkdownParseException : Exception
|
public class RubricMarkdownParseException : Exception
|
||||||
{
|
{
|
||||||
public RubricMarkdownParseException(string message) : base(message) { }
|
public RubricMarkdownParseException(string message) : base(message) { }
|
||||||
|
}
|
||||||
|
public class AssignmentMarkdownParseException : Exception
|
||||||
|
{
|
||||||
|
public AssignmentMarkdownParseException(string message) : base(message) { }
|
||||||
}
|
}
|
||||||
16
README.md
16
README.md
@@ -17,3 +17,19 @@ Apparently the VSCode razor extension was compiled with a preview of dotnet 6...
|
|||||||
|
|
||||||
The issue can be tracked [here](https://github.com/dotnet/razor/issues/6241)
|
The issue can be tracked [here](https://github.com/dotnet/razor/issues/6241)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"Name: test assignment
|
||||||
|
LockAt: 1/1/0001 12:00:00 AM
|
||||||
|
DueAt: 1/1/0001 12:00:00 AM
|
||||||
|
AssignmentGroupName: Final Project
|
||||||
|
SubmissionTypes:
|
||||||
|
- online_upload
|
||||||
|
|
||||||
|
---
|
||||||
|
here is the description
|
||||||
|
## Rubric
|
||||||
|
- 4pts: do task 1
|
||||||
|
- 2pts: do task 2
|
||||||
|
"
|
||||||
Reference in New Issue
Block a user