mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 15:18:32 -06:00
started creating module ui, workign on assignments
This commit is contained in:
40
Management.Test/Features/ModuleTests.cs
Normal file
40
Management.Test/Features/ModuleTests.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
public class ModuleTests
|
||||
{
|
||||
[Test]
|
||||
public void CanAddModule()
|
||||
{
|
||||
var manager = new ModuleManager();
|
||||
var module = new CourseModule("First Module", new LocalAssignment[] { });
|
||||
manager.AddModule(module);
|
||||
|
||||
manager.Modules.Count().Should().Be(1);
|
||||
manager.Modules.First().Should().Be(module);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanAddAssignmentToCorrectModule()
|
||||
{
|
||||
var manager = new ModuleManager();
|
||||
manager.AddModule(new CourseModule("First Module", new LocalAssignment[] { }));
|
||||
manager.AddModule(new CourseModule("Second Module", new LocalAssignment[] { }));
|
||||
manager.AddModule(new CourseModule("Third Module", new LocalAssignment[] { }));
|
||||
manager.AddModule(new CourseModule("Fourth Module", new LocalAssignment[] { }));
|
||||
|
||||
var assignment = new LocalAssignment
|
||||
{
|
||||
name = "testname",
|
||||
description = "testDescription",
|
||||
published = false,
|
||||
lock_at_due_date = true,
|
||||
rubric = new RubricItem[] { },
|
||||
lock_at = null,
|
||||
due_at = DateTime.Now,
|
||||
points_possible = 10,
|
||||
submission_types = new SubmissionType[] { SubmissionType.online_text_entry }
|
||||
};
|
||||
|
||||
manager.AddAssignment(3, assignment);
|
||||
manager.Modules.Count().Should().Be(4);
|
||||
manager.Modules.ElementAt(3).Assignments.Count().Should().Be(1);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,31 @@
|
||||
@page "/modules"
|
||||
@using Management.Web.Shared.Module
|
||||
@using System.Linq
|
||||
@inject IModuleManager moduleManager
|
||||
|
||||
@code {
|
||||
private bool showNewModule { get; set; } = false;
|
||||
|
||||
}
|
||||
|
||||
<PageTitle>Weather forecast</PageTitle>
|
||||
|
||||
@if (!showNewModule)
|
||||
{
|
||||
<button class="btn btn-secondary" @onclick="() => showNewModule = true">New Module</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btn btn-secondary" @onclick="() => showNewModule = false">Hide New Module</button>
|
||||
}
|
||||
|
||||
@if (showNewModule)
|
||||
{
|
||||
<NewModule OnSubmit="() => showNewModule = false" />
|
||||
}
|
||||
|
||||
@foreach (var i in moduleManager.Modules.Select((_value, i) => i))
|
||||
{
|
||||
<hr>
|
||||
<ModuleDetail ModuleIndex="i" />
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
global using System.Text.Json.Serialization;
|
||||
global using System.Text.Json;
|
||||
global using System.ComponentModel.DataAnnotations;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
@@ -15,6 +16,7 @@ builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddSingleton<IWebRequestor, WebRequestor>();
|
||||
builder.Services.AddSingleton<ICanvasService, CanvasService>();
|
||||
builder.Services.AddSingleton<IConfigurationManagement, ConfigurationManagement>();
|
||||
builder.Services.AddSingleton<IModuleManager, ModuleManager>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
|
||||
38
Management.Web/Shared/Module/Assignment/NewAssignment.razor
Normal file
38
Management.Web/Shared/Module/Assignment/NewAssignment.razor
Normal file
@@ -0,0 +1,38 @@
|
||||
@inject IModuleManager moduleManager
|
||||
|
||||
@code {
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public int ModuleIndex { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnSubmit { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(50, ErrorMessage = "Name too long (50 character limit).")]
|
||||
private string Name { get; set; } = "";
|
||||
|
||||
private async Task submitHandler()
|
||||
{
|
||||
var newAssignment = new LocalAssignment
|
||||
{
|
||||
name = Name,
|
||||
description = "testDescription",
|
||||
published = false,
|
||||
lock_at_due_date = true,
|
||||
rubric = new RubricItem[] { },
|
||||
lock_at = null,
|
||||
due_at = DateTime.Now,
|
||||
points_possible = 10,
|
||||
submission_types = new SubmissionType[] { SubmissionType.online_text_entry }
|
||||
};
|
||||
moduleManager.AddAssignment(ModuleIndex, newAssignment);
|
||||
await OnSubmit.InvokeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
<form @onsubmit:preventDefault="true" @onsubmit="submitHandler">
|
||||
<label for="Assignment Name">Name</label>
|
||||
<input id="moduleName" class="form-control" @bind="Name" />
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</form>
|
||||
40
Management.Web/Shared/Module/ModuleDetail.razor
Normal file
40
Management.Web/Shared/Module/ModuleDetail.razor
Normal file
@@ -0,0 +1,40 @@
|
||||
@using Management.Web.Shared.Module.Assignment
|
||||
|
||||
|
||||
@inject IModuleManager moduleManager
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired]
|
||||
public int ModuleIndex { get; set; }
|
||||
|
||||
private bool showAddAssignment { get; set; } = false;
|
||||
|
||||
private CourseModule? module
|
||||
{
|
||||
get
|
||||
{
|
||||
return moduleManager.Modules.ElementAtOrDefault(ModuleIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if (module != null)
|
||||
{
|
||||
<h3 class="text-center">@module.Name</h3>
|
||||
<button class="btn btn-primary" @onclick="() => showAddAssignment = true">Add Assignment</button>
|
||||
@if (showAddAssignment)
|
||||
{
|
||||
<div class="ms-5 ">
|
||||
<div class="bg-light border rounded m-3 p-3">
|
||||
<NewAssignment ModuleIndex="ModuleIndex" OnSubmit="() => showAddAssignment = false" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<h5>Assignments</h5>
|
||||
@foreach (var assignment in module.Assignments)
|
||||
{
|
||||
<div>@assignment.name</div>
|
||||
}
|
||||
|
||||
}
|
||||
27
Management.Web/Shared/Module/NewModule.razor
Normal file
27
Management.Web/Shared/Module/NewModule.razor
Normal file
@@ -0,0 +1,27 @@
|
||||
@inject IModuleManager moduleManager
|
||||
|
||||
@code {
|
||||
|
||||
[Required]
|
||||
[StringLength(50, ErrorMessage = "Name too long (50 character limit).")]
|
||||
private string Name { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnSubmit { get; set; }
|
||||
|
||||
private async Task submitHandler()
|
||||
{
|
||||
var module = new CourseModule(Name: Name, Assignments: new LocalAssignment[] { });
|
||||
moduleManager.AddModule(module);
|
||||
Name = "";
|
||||
await OnSubmit.InvokeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
<h1>New Module</h1>
|
||||
|
||||
<form @onsubmit:preventDefault="true" @onsubmit="submitHandler">
|
||||
<label for="moduleName">Name:</label>
|
||||
<input id="moduleName" class="form-control" @bind="Name" />
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</form>
|
||||
6
Management/Features/Modules/IModuleManager.cs
Normal file
6
Management/Features/Modules/IModuleManager.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
public interface IModuleManager
|
||||
{
|
||||
IEnumerable<CourseModule> Modules { get; }
|
||||
public void AddModule(CourseModule newModule);
|
||||
public void AddAssignment(int moduleIndex, LocalAssignment assignment);
|
||||
}
|
||||
22
Management/Features/Modules/ModuleManager.cs
Normal file
22
Management/Features/Modules/ModuleManager.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
public class ModuleManager : IModuleManager
|
||||
{
|
||||
public IEnumerable<CourseModule> Modules { get; internal set; } = new CourseModule[] { };
|
||||
|
||||
public void AddAssignment(int moduleIndex, LocalAssignment assignment)
|
||||
{
|
||||
var newAssignments = Modules.ElementAt(moduleIndex).Assignments.Append(assignment);
|
||||
var newModule = Modules.ElementAt(moduleIndex) with { Assignments = newAssignments };
|
||||
if (newModule == null)
|
||||
throw new Exception($"cannot get module at index {moduleIndex}");
|
||||
|
||||
Modules = Modules
|
||||
.Take(moduleIndex)
|
||||
.Append(newModule)
|
||||
.Concat(Modules.Skip(moduleIndex + 1));
|
||||
}
|
||||
|
||||
public void AddModule(CourseModule newModule)
|
||||
{
|
||||
Modules = Modules.Append(newModule);
|
||||
}
|
||||
}
|
||||
11
Management/Models/CourseModule.cs
Normal file
11
Management/Models/CourseModule.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
public record CourseModule(
|
||||
[property: Required]
|
||||
[property: StringLength(50, ErrorMessage = "Name too long (50 character limit).")]
|
||||
string Name,
|
||||
IEnumerable<LocalAssignment>? Assignments
|
||||
)
|
||||
{
|
||||
public IEnumerable<LocalAssignment> Assignments = Assignments ?? new LocalAssignment[] { };
|
||||
}
|
||||
31
Management/Models/LocalAssignment.cs
Normal file
31
Management/Models/LocalAssignment.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
public record RubricItem(
|
||||
int Points,
|
||||
string Label
|
||||
);
|
||||
|
||||
public enum SubmissionType
|
||||
{
|
||||
online_quiz,
|
||||
none,
|
||||
on_paper,
|
||||
discussion_topic,
|
||||
external_tool,
|
||||
online_upload,
|
||||
online_text_entry,
|
||||
online_url,
|
||||
media_recording,
|
||||
student_annotation,
|
||||
}
|
||||
|
||||
public record LocalAssignment
|
||||
{
|
||||
public string name { get; init; } = "";
|
||||
public string description { get; init; } = "";
|
||||
public bool published { get; init; }
|
||||
public bool lock_at_due_date { get; init; }
|
||||
public IEnumerable<RubricItem> rubric { get; init; } = new RubricItem[] { };
|
||||
public DateTime? lock_at { get; init; }
|
||||
public DateTime due_at { get; init; }
|
||||
public int points_possible { get; init; }
|
||||
public IEnumerable<SubmissionType> submission_types { get; init; } = new SubmissionType[] { };
|
||||
}
|
||||
12
README.md
12
README.md
@@ -5,4 +5,14 @@ install specflow template `dotnet new install Specflow.Templates.DotNet`
|
||||
|
||||
view templates with `dotnet new -l`
|
||||
|
||||
find outdated packages `dotnet list package --outdated`
|
||||
find outdated packages `dotnet list package --outdated`
|
||||
|
||||
|
||||
Development command: `dotnet watch --project Management.Web/`
|
||||
|
||||
|
||||
# Razor Hack
|
||||
|
||||
Apparently the VSCode razor extension was compiled with a preview of dotnet 6... and only uses openssl 1.1. After installing openssl1.1 you can tell vscode to provide it with `export CLR_OPENSSL_VERSION_OVERRIDE=1.1; code ~/projects/canvasManagement`.
|
||||
|
||||
The issue can be tracked [here](https://github.com/dotnet/razor/issues/6241)
|
||||
Reference in New Issue
Block a user