mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-25 23:28:33 -06:00
got debounced saving working. some of the assignment saving logic is real time
This commit is contained in:
@@ -8,7 +8,7 @@ global using CanvasModel;
|
|||||||
global using LocalModels;
|
global using LocalModels;
|
||||||
global using Management.Planner;
|
global using Management.Planner;
|
||||||
global using Management.Web.Shared.Components;
|
global using Management.Web.Shared.Components;
|
||||||
global using Management.Web.Shared.Course;
|
global using Management.Web.Shared;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
@@ -39,6 +39,7 @@ builder.Services.AddScoped<CanvasService, CanvasService>();
|
|||||||
|
|
||||||
builder.Services.AddScoped<YamlManager>();
|
builder.Services.AddScoped<YamlManager>();
|
||||||
builder.Services.AddScoped<CoursePlanner>();
|
builder.Services.AddScoped<CoursePlanner>();
|
||||||
|
builder.Services.AddScoped<AssignmentEditorContext>();
|
||||||
builder.Services.AddScoped<DragContainer>();
|
builder.Services.AddScoped<DragContainer>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
protected override void OnInitialized()
|
@* protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
planner.StateHasChanged += reload;
|
planner.StateHasChanged += reload;
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
planner.StateHasChanged -= reload;
|
planner.StateHasChanged -= reload;
|
||||||
}
|
} *@
|
||||||
|
|
||||||
|
|
||||||
[Parameter, EditorRequired]
|
[Parameter, EditorRequired]
|
||||||
@@ -41,7 +41,6 @@
|
|||||||
{
|
{
|
||||||
UseTemplate = Assignment.TemplateId != null && Assignment.TemplateId != "";
|
UseTemplate = Assignment.TemplateId != null && Assignment.TemplateId != "";
|
||||||
}
|
}
|
||||||
Console.WriteLine(Description)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
: m
|
: m
|
||||||
).ToArray();
|
).ToArray();
|
||||||
|
|
||||||
planner.LocalCourse = planner.LocalCourse with
|
planner.LocalCourse = planner.LocalCourse with
|
||||||
{
|
{
|
||||||
Modules=updatedModules
|
Modules=updatedModules
|
||||||
@@ -85,41 +84,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Timer _debounceTimer;
|
|
||||||
|
|
||||||
private void SaveDescription()
|
|
||||||
{
|
|
||||||
|
|
||||||
Console.WriteLine("saving description");
|
|
||||||
_debounceTimer?.Dispose();
|
|
||||||
SaveAssignment(Assignment with { Description = currentDescription });
|
|
||||||
}
|
|
||||||
|
|
||||||
private string? currentDescription { get; set; } = null;
|
private string? currentDescription { get; set; } = null;
|
||||||
private void OnInputChanged(ChangeEventArgs e)
|
private void OnInputChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
// Dispose of any existing timer
|
SaveAssignment(Assignment with { Description = e.Value?.ToString() ?? "" });
|
||||||
_debounceTimer?.Dispose();
|
|
||||||
|
|
||||||
// Create a new timer that waits for 500ms before executing SaveData
|
|
||||||
_debounceTimer = new Timer(
|
|
||||||
(_) => SaveDescription(),
|
|
||||||
null,
|
|
||||||
500,
|
|
||||||
Timeout.Infinite
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input
|
<input
|
||||||
class="form-check-input"
|
class="form-check-input"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
role="switch"
|
role="switch"
|
||||||
id="useTemplateForDescription"
|
id="useTemplateForDescription"
|
||||||
@bind="UseTemplate"
|
@bind="UseTemplate"
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" for="useTemplateForDescription">
|
<label class="form-check-label" for="useTemplateForDescription">
|
||||||
use template for description
|
use template for description
|
||||||
|
|||||||
@@ -2,32 +2,30 @@
|
|||||||
|
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
@inject CanvasService canvas
|
@inject CanvasService canvas
|
||||||
|
@inject AssignmentEditorContext assignmentContext
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
planner.StateHasChanged += reload;
|
assignmentContext.StateHasChanged += reload;
|
||||||
}
|
}
|
||||||
private void reload()
|
private void reload()
|
||||||
{
|
{
|
||||||
|
if (assignmentContext.Assignment != null)
|
||||||
|
{
|
||||||
|
AssignmentModal?.Show();
|
||||||
|
name = assignmentContext.Assignment.Name;
|
||||||
|
lockAtDueDate = assignmentContext.Assignment.LockAtDueDate;
|
||||||
|
rubric = assignmentContext.Assignment.Rubric;
|
||||||
|
submissionTypes = assignmentContext.Assignment.SubmissionTypes;
|
||||||
|
}
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
this.InvokeAsync(this.StateHasChanged);
|
||||||
}
|
}
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
planner.StateHasChanged -= reload;
|
assignmentContext.StateHasChanged -= reload;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
[EditorRequired]
|
|
||||||
public LocalAssignment Assignment
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
} = default!;
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
[EditorRequired]
|
|
||||||
public bool Show { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Action OnHide { get; set; } = () => { };
|
public Action OnHide { get; set; } = () => { };
|
||||||
@@ -37,26 +35,16 @@
|
|||||||
private IEnumerable<RubricItem> rubric { get; set; } = Enumerable.Empty<RubricItem>();
|
private IEnumerable<RubricItem> rubric { get; set; } = Enumerable.Empty<RubricItem>();
|
||||||
private IEnumerable<string> submissionTypes { get; set; } = Enumerable.Empty<string>();
|
private IEnumerable<string> submissionTypes { get; set; } = Enumerable.Empty<string>();
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
|
||||||
{
|
|
||||||
if (Show)
|
|
||||||
{
|
|
||||||
AssignmentModal?.Show();
|
|
||||||
}
|
|
||||||
name = Assignment.Name;
|
|
||||||
lockAtDueDate = Assignment.LockAtDueDate;
|
|
||||||
rubric = Assignment.Rubric;
|
|
||||||
submissionTypes = Assignment.SubmissionTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void submitHandler()
|
private void submitHandler()
|
||||||
{
|
{
|
||||||
var totalRubricPoints = rubric
|
if(assignmentContext.Assignment != null)
|
||||||
.Where(r => !r.Label.Contains(RubricItem.extraCredit))
|
{
|
||||||
.Select(s => s.Points)
|
var totalRubricPoints = rubric
|
||||||
.Sum();
|
.Where(r => !r.Label.Contains(RubricItem.extraCredit))
|
||||||
|
.Select(s => s.Points)
|
||||||
|
.Sum();
|
||||||
|
|
||||||
var newAssignment = Assignment with
|
var newAssignment = assignmentContext.Assignment with
|
||||||
{
|
{
|
||||||
Name = name,
|
Name = name,
|
||||||
LockAtDueDate = lockAtDueDate,
|
LockAtDueDate = lockAtDueDate,
|
||||||
@@ -65,34 +53,36 @@
|
|||||||
SubmissionTypes = submissionTypes,
|
SubmissionTypes = submissionTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (planner.LocalCourse != null)
|
if (planner.LocalCourse != null)
|
||||||
{
|
{
|
||||||
var currentModule = planner
|
var currentModule = planner
|
||||||
.LocalCourse
|
.LocalCourse
|
||||||
.Modules
|
.Modules
|
||||||
.First(m =>
|
.First(m =>
|
||||||
m.Assignments
|
m.Assignments
|
||||||
.Select(a => a.Id)
|
.Select(a => a.Id)
|
||||||
.Contains(Assignment.Id)
|
.Contains(newAssignment.Id)
|
||||||
) ?? throw new Exception("could not find current module in assignment form");
|
) ?? throw new Exception("could not find current module in assignment form");
|
||||||
var updatedModules = planner.LocalCourse.Modules.Select(m =>
|
var updatedModules = planner.LocalCourse.Modules.Select(m =>
|
||||||
m.Name == currentModule.Name
|
m.Name == currentModule.Name
|
||||||
? currentModule with
|
? currentModule with
|
||||||
{
|
{
|
||||||
Assignments = currentModule.Assignments.Select(a =>
|
Assignments = currentModule.Assignments.Select(a =>
|
||||||
a.Id == newAssignment.Id
|
a.Id == newAssignment.Id
|
||||||
? newAssignment
|
? newAssignment
|
||||||
: a
|
: a
|
||||||
).ToArray()
|
).ToArray()
|
||||||
}
|
}
|
||||||
: m
|
: m
|
||||||
).ToArray();
|
).ToArray();
|
||||||
planner.LocalCourse = planner.LocalCourse with
|
planner.LocalCourse = planner.LocalCourse with
|
||||||
{
|
{
|
||||||
Modules = updatedModules
|
Modules = updatedModules
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
AssignmentModal?.Hide();
|
||||||
|
assignmentContext.Assignment = null;
|
||||||
}
|
}
|
||||||
AssignmentModal?.Hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRubric(IEnumerable<RubricItem> newRubric)
|
private void updateRubric(IEnumerable<RubricItem> newRubric)
|
||||||
@@ -108,16 +98,17 @@
|
|||||||
|
|
||||||
private async Task HandleDelete()
|
private async Task HandleDelete()
|
||||||
{
|
{
|
||||||
if (planner.LocalCourse != null)
|
if (planner.LocalCourse != null && assignmentContext.Assignment != null)
|
||||||
{
|
{
|
||||||
var assignment = Assignment;
|
var assignment = assignmentContext.Assignment;
|
||||||
|
|
||||||
var currentModule = planner
|
var currentModule = planner
|
||||||
.LocalCourse
|
.LocalCourse
|
||||||
.Modules
|
.Modules
|
||||||
.First(m =>
|
.First(m =>
|
||||||
m.Assignments
|
m.Assignments
|
||||||
.Select(a => a.Id)
|
.Select(a => a.Id)
|
||||||
.Contains(Assignment.Id)
|
.Contains(assignment.Id)
|
||||||
) ?? throw new Exception("handling assignment delete, could not find module");
|
) ?? throw new Exception("handling assignment delete, could not find module");
|
||||||
var newModules = planner.LocalCourse.Modules.Select(m =>
|
var newModules = planner.LocalCourse.Modules.Select(m =>
|
||||||
m.Name == currentModule.Name
|
m.Name == currentModule.Name
|
||||||
@@ -143,34 +134,40 @@
|
|||||||
|
|
||||||
<Modal @ref="AssignmentModal" OnHide="@(() => OnHide())">
|
<Modal @ref="AssignmentModal" OnHide="@(() => OnHide())">
|
||||||
<Title>
|
<Title>
|
||||||
@Assignment.Name
|
@assignmentContext.Assignment?.Name
|
||||||
</Title>
|
</Title>
|
||||||
|
|
||||||
<Body>
|
<Body>
|
||||||
<form @onsubmit:preventDefault="true" @onsubmit="submitHandler">
|
@if(assignmentContext.Assignment != null)
|
||||||
<div class="m-1">
|
{
|
||||||
<label class="form-label">
|
<form @onsubmit:preventDefault="true">
|
||||||
Name
|
<div class="m-1">
|
||||||
</label>
|
<label class="form-label">
|
||||||
<input class="form-control" @bind="name" />
|
Name
|
||||||
</div>
|
</label>
|
||||||
<div class="m-1">
|
<input class="form-control" @bind="name" />
|
||||||
<AssignmentDescriptionEditor @key="Assignment" Assignment="Assignment" />
|
</div>
|
||||||
</div>
|
<div class="m-1">
|
||||||
|
<AssignmentDescriptionEditor Assignment="assignmentContext.Assignment" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-check m-1">
|
<div class="form-check m-1">
|
||||||
<input class="form-check-input" id="lockAtDueDate" type="checkbox" />
|
<input class="form-check-input" id="lockAtDueDate" type="checkbox" />
|
||||||
<label class="form-check-label" for="lockAtDueDate" @bind="lockAtDueDate">
|
<label class="form-check-label" for="lockAtDueDate" @bind="lockAtDueDate">
|
||||||
Lock At Due Date
|
Lock At Due Date
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<RubricEditor Rubric="rubric" SetRubric="updateRubric" />
|
<RubricEditor Rubric="rubric" SetRubric="updateRubric" />
|
||||||
<SubmissionTypeSelector Types="submissionTypes" SetTypes="SetTypes" />
|
<SubmissionTypeSelector Types="submissionTypes" SetTypes="SetTypes" />
|
||||||
</form>
|
</form>
|
||||||
|
}
|
||||||
</Body>
|
</Body>
|
||||||
<Footer>
|
<Footer>
|
||||||
<ConfirmationModal Label="Delete" Class="btn btn-danger" OnConfirmAsync="HandleDelete" />
|
<ConfirmationModal Label="Delete" Class="btn btn-danger" OnConfirmAsync="HandleDelete" />
|
||||||
<button class="btn btn-primary" @onclick="@(() => AssignmentModal?.Hide())">
|
<button class="btn btn-primary" @onclick="@(() => {
|
||||||
|
AssignmentModal?.Hide();
|
||||||
|
assignmentContext.Assignment = null;
|
||||||
|
})">
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
</Footer>
|
</Footer>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
private bool showBackdrop = false;
|
private bool showBackdrop = false;
|
||||||
public void Show()
|
public void Show()
|
||||||
{
|
{
|
||||||
|
|
||||||
modalClass = "show-modal";
|
modalClass = "show-modal";
|
||||||
showBackdrop = true;
|
showBackdrop = true;
|
||||||
OnShow();
|
OnShow();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@using CanvasModel.EnrollmentTerms
|
@using CanvasModel.EnrollmentTerms
|
||||||
@using Management.Web.Shared.Module
|
@using Management.Web.Shared.Module
|
||||||
@using Management.Web.Shared.Semester
|
@using Management.Web.Shared.Semester
|
||||||
|
@using Management.Web.Shared.Components.AssignmentForm
|
||||||
|
|
||||||
@inject CanvasService canvas
|
@inject CanvasService canvas
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
@@ -55,4 +56,6 @@
|
|||||||
<div class="col-4 overflow-y-auto" style="max-height: 95vh;">
|
<div class="col-4 overflow-y-auto" style="max-height: 95vh;">
|
||||||
<Modules />
|
<Modules />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<AssignmentForm />
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
@inject DragContainer dragContainer
|
@inject DragContainer dragContainer
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
|
@inject AssignmentEditorContext assignmentContext
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@@ -128,7 +129,7 @@
|
|||||||
draggable="true"
|
draggable="true"
|
||||||
@ondragstart="HandleDragStart"
|
@ondragstart="HandleDragStart"
|
||||||
@ondragend="HandleDragEnd"
|
@ondragend="HandleDragEnd"
|
||||||
@onclick="@(() => showUpdateForm = true)"
|
@onclick="@(() => assignmentContext.Assignment = Assignment)"
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@@ -249,9 +250,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AssignmentForm
|
|
||||||
Assignment="Assignment"
|
|
||||||
Show="showUpdateForm"
|
|
||||||
OnHide="@(() => showUpdateForm = false)"
|
|
||||||
/>
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
@inject DragContainer dragContainer
|
@inject DragContainer dragContainer
|
||||||
@inject CoursePlanner planner
|
@inject CoursePlanner planner
|
||||||
|
@inject AssignmentEditorContext assignmentContext
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@@ -14,12 +15,12 @@
|
|||||||
private void reload()
|
private void reload()
|
||||||
{
|
{
|
||||||
this.InvokeAsync(this.StateHasChanged);
|
this.InvokeAsync(this.StateHasChanged);
|
||||||
|
@* Console.WriteLine("on initialized " + showUpdateForm + " " + Assignment.Name); *@
|
||||||
}
|
}
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
planner.StateHasChanged -= reload;
|
planner.StateHasChanged -= reload;
|
||||||
}
|
}
|
||||||
private bool showUpdateForm = false;
|
|
||||||
|
|
||||||
private void dropOnDate(DateTime dropDate)
|
private void dropOnDate(DateTime dropDate)
|
||||||
{
|
{
|
||||||
@@ -114,14 +115,8 @@
|
|||||||
draggable="true"
|
draggable="true"
|
||||||
@ondragstart="HandleDragStart"
|
@ondragstart="HandleDragStart"
|
||||||
@ondragend="HandleDragEnd"
|
@ondragend="HandleDragEnd"
|
||||||
@onclick="@(() => showUpdateForm = true)"
|
@onclick="@(() => assignmentContext.Assignment = Assignment)"
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
@Assignment.Name
|
@Assignment.Name
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AssignmentForm
|
|
||||||
Assignment="Assignment"
|
|
||||||
Show="showUpdateForm"
|
|
||||||
OnHide="@(() => showUpdateForm = false)"
|
|
||||||
/>
|
|
||||||
52
Management/Features/Configuration/AssignmentEditorContext.cs
Normal file
52
Management/Features/Configuration/AssignmentEditorContext.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using LocalModels;
|
||||||
|
using Management.Planner;
|
||||||
|
|
||||||
|
public class AssignmentEditorContext
|
||||||
|
{
|
||||||
|
public event Action? StateHasChanged;
|
||||||
|
private CoursePlanner planner { get; }
|
||||||
|
|
||||||
|
public AssignmentEditorContext(CoursePlanner planner)
|
||||||
|
{
|
||||||
|
this.planner = planner;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalAssignment? _assignment;
|
||||||
|
public LocalAssignment? Assignment
|
||||||
|
{
|
||||||
|
get { return _assignment; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_assignment = value;
|
||||||
|
StateHasChanged?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveAssignment(LocalAssignment newAssignment)
|
||||||
|
{
|
||||||
|
if (planner.LocalCourse != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine(newAssignment.Description);
|
||||||
|
var currentModule =
|
||||||
|
planner.LocalCourse.Modules.First(
|
||||||
|
m => m.Assignments.Select(a => a.Id).Contains(newAssignment.Id)
|
||||||
|
) ?? throw new Exception("could not find current module in assignment description form");
|
||||||
|
|
||||||
|
var updatedModules = planner.LocalCourse.Modules
|
||||||
|
.Select(
|
||||||
|
m =>
|
||||||
|
m.Name == currentModule.Name
|
||||||
|
? currentModule with
|
||||||
|
{
|
||||||
|
Assignments = currentModule.Assignments
|
||||||
|
.Select(a => a.Id == newAssignment.Id ? newAssignment : a)
|
||||||
|
.ToArray()
|
||||||
|
}
|
||||||
|
: m
|
||||||
|
)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
planner.LocalCourse = planner.LocalCourse with { Modules = updatedModules };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,8 @@ public class CoursePlanner
|
|||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Timer _debounceTimer;
|
||||||
|
private int _debounceInterval = 1000;
|
||||||
private LocalCourse? _localCourse { get; set; }
|
private LocalCourse? _localCourse { get; set; }
|
||||||
public LocalCourse? LocalCourse
|
public LocalCourse? LocalCourse
|
||||||
{
|
{
|
||||||
@@ -36,15 +38,30 @@ public class CoursePlanner
|
|||||||
|
|
||||||
var verifiedCourse = value.GeneralCourseCleanup();
|
var verifiedCourse = value.GeneralCourseCleanup();
|
||||||
|
|
||||||
// ignore initial load of course
|
_debounceTimer?.Dispose();
|
||||||
if (_localCourse != null)
|
_debounceTimer = new Timer(
|
||||||
{
|
(_) => saveCourseToFile(),
|
||||||
yamlManager.SaveCourse(verifiedCourse);
|
null,
|
||||||
}
|
_debounceInterval,
|
||||||
|
Timeout.Infinite
|
||||||
|
);
|
||||||
|
|
||||||
_localCourse = verifiedCourse;
|
_localCourse = verifiedCourse;
|
||||||
StateHasChanged?.Invoke();
|
StateHasChanged?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveCourseToFile()
|
||||||
|
{
|
||||||
|
_debounceTimer?.Dispose();
|
||||||
|
// ignore initial load of course
|
||||||
|
if (LocalCourse != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Saving file");
|
||||||
|
yamlManager.SaveCourse(LocalCourse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public event Action? StateHasChanged;
|
public event Action? StateHasChanged;
|
||||||
|
|
||||||
public IEnumerable<CanvasAssignment>? CanvasAssignments { get; internal set; }
|
public IEnumerable<CanvasAssignment>? CanvasAssignments { get; internal set; }
|
||||||
|
|||||||
Reference in New Issue
Block a user