diff --git a/Management.Test/Markdown/FileStorageTests.cs b/Management.Test/Markdown/FileStorageTests.cs index d732980..f0f0fad 100644 --- a/Management.Test/Markdown/FileStorageTests.cs +++ b/Management.Test/Markdown/FileStorageTests.cs @@ -272,7 +272,7 @@ public class FileStorageTests Pages = [ new () { Name = "test page persistence", - DueDateForOrdering = new DateTime(), + DueAt = new DateTime(), Text = "this is some\n## markdown\n" } ] diff --git a/Management.Test/Markdown/PageMarkdownTests.cs b/Management.Test/Markdown/PageMarkdownTests.cs index d37c40f..cd5a802 100644 --- a/Management.Test/Markdown/PageMarkdownTests.cs +++ b/Management.Test/Markdown/PageMarkdownTests.cs @@ -9,7 +9,7 @@ public class PageMarkdownTests { Name = "test title", Text = "test text content", - DueDateForOrdering = new DateTime() + DueAt = new DateTime() }; var pageMarkdown = page.ToMarkdown(); diff --git a/Management.Web/Pages/AssignmentForm/AssignmentFormPage.razor b/Management.Web/Pages/AssignmentForm/AssignmentFormPage.razor index 1f2fdc9..4cec309 100644 --- a/Management.Web/Pages/AssignmentForm/AssignmentFormPage.razor +++ b/Management.Web/Pages/AssignmentForm/AssignmentFormPage.razor @@ -4,7 +4,7 @@ @using CanvasModel.Courses @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @using LocalModels -@using Management.Web.Pages.Course.Module.Assignment +@using Management.Web.Pages.Course.Module.ModuleItems @using Management.Web.Shared.Components @inject FileStorageManager fileStorageManager diff --git a/Management.Web/Pages/Course/Course.razor b/Management.Web/Pages/Course/Course.razor index aa194e0..1e55414 100644 --- a/Management.Web/Pages/Course/Course.razor +++ b/Management.Web/Pages/Course/Course.razor @@ -3,7 +3,7 @@ @using CanvasModel.Courses @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @using LocalModels -@using Management.Web.Pages.Course.Module.Assignment +@using Management.Web.Pages.Course.Module.ModuleItems @using Management.Web.Shared.Components @inject FileStorageManager fileStorageManager diff --git a/Management.Web/Pages/Course/CourseCalendar/Day/AssignmentInDay.razor b/Management.Web/Pages/Course/CourseCalendar/Day/AssignmentInDay.razor index ca6285c..c437145 100644 --- a/Management.Web/Pages/Course/CourseCalendar/Day/AssignmentInDay.razor +++ b/Management.Web/Pages/Course/CourseCalendar/Day/AssignmentInDay.razor @@ -1,4 +1,4 @@ -@using Management.Web.Course.Module.Assignment +@using Management.Web.Course.Module.ModuleItems @inject DragContainer dragContainer @inject NavigationManager Navigation diff --git a/Management.Web/Pages/Course/CourseCalendar/Day/Day.razor b/Management.Web/Pages/Course/CourseCalendar/Day/Day.razor index a673bdd..be2492c 100644 --- a/Management.Web/Pages/Course/CourseCalendar/Day/Day.razor +++ b/Management.Web/Pages/Course/CourseCalendar/Day/Day.razor @@ -3,12 +3,12 @@ @inject CoursePlanner planner -@code +@code { [Parameter, EditorRequired] public DateTime? date { get; set; } = - default!; - + default!; + private bool isWeekDay { get => date?.DayOfWeek != null; } @@ -25,8 +25,8 @@ { planner.StateHasChanged -= reload; } - - private IEnumerable TodaysAssignments + + private IEnumerable TodaysAssignments { get { @@ -39,7 +39,7 @@ } } - private IEnumerable todaysQuizzes + private IEnumerable todaysQuizzes { get { @@ -51,11 +51,25 @@ .Where(q => q.DueAt.Date == date?.Date); } } + + private IEnumerable todaysPages + { + get + { + if(planner.LocalCourse == null || date == null) + return Enumerable.Empty(); + else + return planner.LocalCourse.Modules + .SelectMany(m => m.Pages) + .Where(q => q.DueAt.Date == date?.Date); + } + } + private string calculatedClass { get { - var baseClasses = "col border rounded rounded-3 p-2 pb-4 m-1 "; + var baseClasses = "col border rounded rounded-3 p-2 pb-4 m-1 "; if(dragging) return baseClasses + " bg-secondary text-light "; @@ -66,15 +80,15 @@ { DayOfWeek? weekDay = date?.DayOfWeek; DayOfWeek notNullDay = weekDay ?? default; - + var isClassDay = planner.LocalCourse?.Settings.DaysOfWeek.Contains(notNullDay) ?? false; - var dayInSemester = + var dayInSemester = isClassDay && date <= planner.LocalCourse?.Settings.EndDate && date >= planner.LocalCourse?.Settings.StartDate; - - var totalClasses = dayInSemester - ? "bg-light-subtle text-light " + baseClasses + + var totalClasses = dayInSemester + ? "bg-light-subtle text-light " + baseClasses : " " + baseClasses; return totalClasses; @@ -105,9 +119,9 @@ dragContainer.DropCallback?.Invoke(d, null); } } -} +} -
@foreach (var assignment in TodaysAssignments) { - @* Console.WriteLine($"assignment: {assignment.Name}"); *@ - + } @foreach(var quiz in todaysQuizzes) { } + + @foreach(var page in todaysPages) + { + + }
diff --git a/Management.Web/Pages/Course/CourseCalendar/Day/PageInDay.razor b/Management.Web/Pages/Course/CourseCalendar/Day/PageInDay.razor new file mode 100644 index 0000000..035cbb8 --- /dev/null +++ b/Management.Web/Pages/Course/CourseCalendar/Day/PageInDay.razor @@ -0,0 +1,55 @@ +@using Management.Web.Course.Module.ModuleItems + +@inject DragContainer dragContainer +@inject NavigationManager Navigation +@inject PageEditorContext pageContext + +@inject MyLogger logger + +@inherits DroppablePage + +@code { + protected override void OnInitialized() + { + planner.StateHasChanged += reload; + } + private void reload() + { + this.InvokeAsync(this.StateHasChanged); + } + public void Dispose() + { + planner.StateHasChanged -= reload; + } + + private void HandleDragStart() + { + dragContainer.DropCallback = dropCallback; + } + + private void HandleDragEnd() + { + dragContainer.DropCallback = null; + } + + private void OnClick() + { + if(planner.LocalCourse != null) + { + pageContext.Page = Page; + Navigation.NavigateTo("/course/" + planner.LocalCourse.Settings.Name + "/page/" + Page.Name); + logger.Log("navigating to coursePage page"); + } + } +} + + +
  • + @Page.Name +
  • diff --git a/Management.Web/Pages/Course/Module/Assignment/AssignmentListItem.razor b/Management.Web/Pages/Course/Module/Assignment/AssignmentListItem.razor deleted file mode 100644 index f5452ea..0000000 --- a/Management.Web/Pages/Course/Module/Assignment/AssignmentListItem.razor +++ /dev/null @@ -1,201 +0,0 @@ -@using Management.Web.Shared.Components -@using Management.Web.Course.Module.Assignment -@using CanvasModel.Assignments - -@inject DragContainer dragContainer -@inject NavigationManager Navigation -@inject AssignmentEditorContext assignmentContext - -@inherits DroppableAssignment - -@code { - [Parameter] - [EditorRequired] - public LocalModule Module { get; set; } = new(); - protected override void OnInitialized() - { - planner.StateHasChanged += reload; - } - private void reload() - { - this.InvokeAsync(this.StateHasChanged); - } - public void Dispose() - { - planner.StateHasChanged -= reload; - } - private bool showAll { get; set; } = false; - - - private void HandleDragStart() - { - dragContainer.DropCallback = DropCallback; - } - - private void HandleDragEnd() - { - dragContainer.DropCallback = null; - } - - private CanvasAssignment? assignmentInCanvas => planner - .CanvasAssignments? - .FirstOrDefault( - a => a.Name == Assignment.Name - ); - - private bool existsInCanvas => - assignmentInCanvas != null; - private void OnClick() - { - assignmentContext.Assignment = Assignment; - Navigation.NavigateTo("/course/" + planner.LocalCourse?.Settings.Name + "/assignment/" + Assignment.Name); - } - - private bool NeedsToBeUpdatedInCanvas => planner.LocalCourse != null - && planner.LocalCourse.Settings.CanvasId != null - && planner.CanvasAssignments != null - && planner.CanvasModules != null - && assignmentInCanvas != null - && Assignment.NeedsUpdates( - (CanvasAssignment)assignmentInCanvas, - Assignment.GetCanvasAssignmentGroupId(planner.LocalCourse.Settings.AssignmentGroups) - ); -} - -
    -
    -
    -
    -
    -
    -

    - @Assignment.Name -

    -
    -
    - @if(existsInCanvas) - { - @if(NeedsToBeUpdatedInCanvas) - { - - } - else - { - - } - } - else - { - - } -
    -
    -
    - - @if( - planner.LocalCourse != null - && existsInCanvas - && NeedsToBeUpdatedInCanvas - && assignmentInCanvas != null - ) - { -
    - @Assignment.GetUpdateReason( - (CanvasAssignment)assignmentInCanvas, - Assignment.GetCanvasAssignmentGroupId(planner.LocalCourse.Settings.AssignmentGroups)) -
    - } - @if(!existsInCanvas) - { -
    - no assignment with same name in canvas -
    - } - - @if(!showAll) - { -
    -
    Points: @Assignment.PointsPossible
    -
    Due At: @Assignment.DueAt
    -
    - } - else - { -
    -
    - - @((MarkupString) @Assignment.GetDescriptionHtml()) -
    - -
    -
    Points: @Assignment.PointsPossible
    -
    Due At: @Assignment.DueAt
    -
    Lock At: @Assignment.LockAt
    -
    Submission Types:
    -
      - @foreach(var type in Assignment.SubmissionTypes) - { -
    • - @type -
    • - } -
    -
    -
    - } - - - @if(!showAll) - { -
    - - - -
    - } - else - { -
    - - - -
    - } - -
    -
    -
    diff --git a/Management.Web/Pages/Course/Module/ModuleDetail.razor b/Management.Web/Pages/Course/Module/ModuleDetail.razor index 50b13c0..0d34832 100644 --- a/Management.Web/Pages/Course/Module/ModuleDetail.razor +++ b/Management.Web/Pages/Course/Module/ModuleDetail.razor @@ -1,6 +1,8 @@ @using Management.Web.Shared.Components @using Management.Web.Shared.Components.Quiz @using Management.Web.Pages.Course.Module +@using Management.Web.Pages.Course.Module.ModuleItems +@using Management.Web.Pages.Course.Module.NewItemsButtons @using LocalModels @using BlazorMonaco @using BlazorMonaco.Editor @@ -153,6 +155,10 @@
    Assignments
    + @foreach(var p in Module.Pages) + { + + } @foreach (var a in Module.Assignments) { diff --git a/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor b/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor new file mode 100644 index 0000000..5ca0d3e --- /dev/null +++ b/Management.Web/Pages/Course/Module/ModuleItems/AssignmentListItem.razor @@ -0,0 +1,137 @@ +@using Management.Web.Shared.Components +@using Management.Web.Course.Module.ModuleItems +@using CanvasModel.Assignments + +@inject DragContainer dragContainer +@inject NavigationManager Navigation +@inject AssignmentEditorContext assignmentContext + +@inherits DroppableAssignment + +@code { + [Parameter] + [EditorRequired] + public LocalModule Module { get; set; } = new(); + protected override void OnInitialized() + { + planner.StateHasChanged += reload; + } + private void reload() + { + this.InvokeAsync(this.StateHasChanged); + } + public void Dispose() + { + planner.StateHasChanged -= reload; + } + private bool showAll { get; set; } = false; + + + private void HandleDragStart() + { + dragContainer.DropCallback = DropCallback; + } + + private void HandleDragEnd() + { + dragContainer.DropCallback = null; + } + + private CanvasAssignment? assignmentInCanvas => planner + .CanvasAssignments? + .FirstOrDefault( + a => a.Name == Assignment.Name + ); + + private bool existsInCanvas => + assignmentInCanvas != null; + private void OnClick() + { + assignmentContext.Assignment = Assignment; + Navigation.NavigateTo("/course/" + planner.LocalCourse?.Settings.Name + "/assignment/" + Assignment.Name); + } + + private bool NeedsToBeUpdatedInCanvas => planner.LocalCourse != null + && planner.LocalCourse.Settings.CanvasId != null + && planner.CanvasAssignments != null + && planner.CanvasModules != null + && assignmentInCanvas != null + && Assignment.NeedsUpdates( + (CanvasAssignment)assignmentInCanvas, + Assignment.GetCanvasAssignmentGroupId(planner.LocalCourse.Settings.AssignmentGroups) + ); +} + +
    + + @if( + planner.LocalCourse != null + && existsInCanvas + && NeedsToBeUpdatedInCanvas + && assignmentInCanvas != null + ) + { +
    + @Assignment.GetUpdateReason( + (CanvasAssignment)assignmentInCanvas, + Assignment.GetCanvasAssignmentGroupId(planner.LocalCourse.Settings.AssignmentGroups)) +
    + } + @if(!existsInCanvas) + { +
    + no assignment with same name in canvas +
    + } + + @if(!showAll) + { +
    +
    Points: @Assignment.PointsPossible
    +
    Due At: @Assignment.DueAt
    +
    + } + else + { +
    +
    + + @((MarkupString) @Assignment.GetDescriptionHtml()) +
    + +
    +
    Points: @Assignment.PointsPossible
    +
    Due At: @Assignment.DueAt
    +
    Lock At: @Assignment.LockAt
    +
    Submission Types:
    +
      + @foreach(var type in Assignment.SubmissionTypes) + { +
    • + @type +
    • + } +
    +
    +
    + } + + +
    + +
    + +
    +
    diff --git a/Management.Web/Pages/Course/Module/Assignment/DroppableAssignment.razor.cs b/Management.Web/Pages/Course/Module/ModuleItems/DroppableAssignment.razor.cs similarity index 97% rename from Management.Web/Pages/Course/Module/Assignment/DroppableAssignment.razor.cs rename to Management.Web/Pages/Course/Module/ModuleItems/DroppableAssignment.razor.cs index cc93651..248f7f7 100644 --- a/Management.Web/Pages/Course/Module/Assignment/DroppableAssignment.razor.cs +++ b/Management.Web/Pages/Course/Module/ModuleItems/DroppableAssignment.razor.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Components; -namespace Management.Web.Course.Module.Assignment; +namespace Management.Web.Course.Module.ModuleItems; public class DroppableAssignment : ComponentBase { [Inject] diff --git a/Management.Web/Pages/Course/Module/ModuleItems/DroppablePage.razor.cs b/Management.Web/Pages/Course/Module/ModuleItems/DroppablePage.razor.cs new file mode 100644 index 0000000..38a9b23 --- /dev/null +++ b/Management.Web/Pages/Course/Module/ModuleItems/DroppablePage.razor.cs @@ -0,0 +1,85 @@ +using Microsoft.AspNetCore.Components; + +namespace Management.Web.Course.Module.ModuleItems; +public class DroppablePage : ComponentBase +{ + [Inject] + protected CoursePlanner planner { get; set; } = default!; + + [Parameter, EditorRequired] + public LocalCoursePage Page { get; set; } = default!; + private void dropOnDate(DateTime dropDate) + { + if (planner.LocalCourse == null) return; + var currentModule = planner + .LocalCourse + .Modules + .First(m => + m.Pages.Contains(Page) + ) ?? throw new Exception("in drop page callback, could not find module"); + + + var defaultDueTimeDate = new DateTime( + year: dropDate.Year, + month: dropDate.Month, + day: dropDate.Day, + hour: planner.LocalCourse.Settings.DefaultDueTime.Hour, + minute: planner.LocalCourse.Settings.DefaultDueTime.Minute, + second: 0 + ); + + var moduleWithUpdatedPage = currentModule with + { + Pages = currentModule.Pages.Select(p => + p.Name != Page.Name // we are only changing the due date, so the name should be the same + ? p + : p with { DueAt = defaultDueTimeDate } + ) + }; + var updatedModules = planner.LocalCourse.Modules + .Select(m => + m.Name == moduleWithUpdatedPage.Name + ? moduleWithUpdatedPage + : m + ); + var newCourse = planner.LocalCourse with + { + Modules = updatedModules + }; + planner.LocalCourse = newCourse; + } + private void dropOnModule(LocalModule module) + { + if (planner.LocalCourse == null) return; + var newModules = planner.LocalCourse.Modules.Select(m => + m.Name != module.Name + ? m with + { + Pages = m.Pages.Where(p => p.Name != Page.Name).DistinctBy(p => p.Name) + } + : m with + { + Pages = m.Pages.Append(Page).DistinctBy(a => a.Name) + } + ); + + var newCourse = planner.LocalCourse with + { + Modules = newModules + }; + planner.LocalCourse = newCourse; + } + + protected void dropCallback(DateTime? dropDate, LocalModule? module) + { + if (module == null) + { + dropOnDate(dropDate ?? Page.DueAt); + } + else + { + dropOnModule(module); + } + } + +} diff --git a/Management.Web/Pages/Course/Quiz/DroppableQuiz.razor.cs b/Management.Web/Pages/Course/Module/ModuleItems/DroppableQuiz.razor.cs similarity index 100% rename from Management.Web/Pages/Course/Quiz/DroppableQuiz.razor.cs rename to Management.Web/Pages/Course/Module/ModuleItems/DroppableQuiz.razor.cs diff --git a/Management.Web/Pages/Course/Module/ModuleItems/ModuleItemLayout.razor b/Management.Web/Pages/Course/Module/ModuleItems/ModuleItemLayout.razor new file mode 100644 index 0000000..810a966 --- /dev/null +++ b/Management.Web/Pages/Course/Module/ModuleItems/ModuleItemLayout.razor @@ -0,0 +1,32 @@ +@using Management.Web.Shared.Components + + +@code { + [Parameter] + public RenderFragment ChildContent { get; set; } = default!; + + [Parameter, EditorRequired] + public string Name { get; set; } = default!; + + [Parameter, EditorRequired] + public bool IsSyncedWithCanvas { get; set; } = default!; +} + + +
    +
    +
    +

    @Name

    + @if(IsSyncedWithCanvas) + { + + } + else + { + + } +
    + @ChildContent +
    + +
    diff --git a/Management.Web/Pages/Course/Module/ModuleItems/PageListItem.razor b/Management.Web/Pages/Course/Module/ModuleItems/PageListItem.razor new file mode 100644 index 0000000..c6d87b7 --- /dev/null +++ b/Management.Web/Pages/Course/Module/ModuleItems/PageListItem.razor @@ -0,0 +1,48 @@ +@using Management.Web.Shared.Components +@using Management.Web.Course.Module.ModuleItems + +@inject DragContainer dragContainer +@inject NavigationManager Navigation +@inject PageEditorContext pageContext + +@inherits DroppablePage + +@code { + private void HandleDragStart() + { + dragContainer.DropCallback = dropCallback; + } + + private void HandleDragEnd() + { + dragContainer.DropCallback = null; + } + private bool existsInCanvas => false; + + + private void OnClick() + { + pageContext.Page = Page; + Navigation.NavigateTo("/course/" + planner.LocalCourse?.Settings.Name + "/page/" + Page.Name); + } +} + +
    + + @if(!existsInCanvas) + { +
    + no page with same name in canvas +
    + } +
    +
    Due At: @Page.DueAt
    +
    +
    +
    diff --git a/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor b/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor new file mode 100644 index 0000000..a159c91 --- /dev/null +++ b/Management.Web/Pages/Course/Module/ModuleItems/QuizListItem.razor @@ -0,0 +1,54 @@ +@using Management.Web.Shared.Components +@using Management.Web.Shared.Components.Quiz + +@inject DragContainer dragContainer +@inject QuizEditorContext quizContext +@inject NavigationManager Navigation + +@inherits DroppableQuiz + +@code { + private void HandleDragStart() + { + dragContainer.DropCallback = dropCallback; + } + + private void HandleDragEnd() + { + dragContainer.DropCallback = null; + } + private bool existsInCanvas => + planner.CanvasQuizzes != null + ? Quiz.QuizIsCreated(planner.CanvasQuizzes) + : false; + + + private void OnClick() + { + quizContext.Quiz = Quiz; + Navigation.NavigateTo("/course/" + planner.LocalCourse?.Settings.Name + "/quiz/" + Quiz.Name); + } +} + + + +
    + + @if(!existsInCanvas) + { +
    + no quiz with same name in canvas +
    + } + +
    +
    Due At: @Quiz.DueAt
    +
    +
    +
    diff --git a/Management.Web/Pages/Course/Module/Modules.razor b/Management.Web/Pages/Course/Module/Modules.razor index 8e41530..898b3e1 100644 --- a/Management.Web/Pages/Course/Module/Modules.razor +++ b/Management.Web/Pages/Course/Module/Modules.razor @@ -1,5 +1,6 @@ @using Management.Web.Pages.Course.Module @using System.Linq +@using Management.Web.Pages.Course.Module.NewItemsButtons @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @inject CoursePlanner planner diff --git a/Management.Web/Pages/Course/Module/NewAssignment.razor b/Management.Web/Pages/Course/Module/NewItemsButtons/NewAssignment.razor similarity index 100% rename from Management.Web/Pages/Course/Module/NewAssignment.razor rename to Management.Web/Pages/Course/Module/NewItemsButtons/NewAssignment.razor diff --git a/Management.Web/Pages/Course/Module/NewModule.razor b/Management.Web/Pages/Course/Module/NewItemsButtons/NewModule.razor similarity index 100% rename from Management.Web/Pages/Course/Module/NewModule.razor rename to Management.Web/Pages/Course/Module/NewItemsButtons/NewModule.razor diff --git a/Management.Web/Pages/Course/Module/NewPage.razor b/Management.Web/Pages/Course/Module/NewItemsButtons/NewPage.razor similarity index 97% rename from Management.Web/Pages/Course/Module/NewPage.razor rename to Management.Web/Pages/Course/Module/NewItemsButtons/NewPage.razor index 12332c1..580e44b 100644 --- a/Management.Web/Pages/Course/Module/NewPage.razor +++ b/Management.Web/Pages/Course/Module/NewItemsButtons/NewPage.razor @@ -26,7 +26,7 @@ { Name = Name, Text = "", - DueDateForOrdering = DateTime.Now + DueAt = DateTime.Now }; var newModules =planner.LocalCourse.Modules.Select(m => diff --git a/Management.Web/Pages/Course/Module/NewQuiz.razor b/Management.Web/Pages/Course/Module/NewItemsButtons/NewQuiz.razor similarity index 100% rename from Management.Web/Pages/Course/Module/NewQuiz.razor rename to Management.Web/Pages/Course/Module/NewItemsButtons/NewQuiz.razor diff --git a/Management.Web/Pages/Course/Module/QuizListItem.razor b/Management.Web/Pages/Course/Module/QuizListItem.razor deleted file mode 100644 index 644e080..0000000 --- a/Management.Web/Pages/Course/Module/QuizListItem.razor +++ /dev/null @@ -1,68 +0,0 @@ -@using Management.Web.Shared.Components -@using Management.Web.Shared.Components.Quiz - -@inject DragContainer dragContainer -@inject QuizEditorContext quizContext -@inject NavigationManager Navigation - -@inherits DroppableQuiz - -@code { - private void HandleDragStart() - { - dragContainer.DropCallback = dropCallback; - } - - private void HandleDragEnd() - { - dragContainer.DropCallback = null; - } - private bool existsInCanvas => - planner.CanvasQuizzes != null - ? Quiz.QuizIsCreated(planner.CanvasQuizzes) - : false; - - - private void OnClick() - { - quizContext.Quiz = Quiz; - Navigation.NavigateTo("/course/" + planner.LocalCourse?.Settings.Name + "/quiz/" + Quiz.Name); - } -} - - - -
    -
    -
    -
    -

    @Quiz.Name

    - @if(existsInCanvas) - { - - } - else - { - - } -
    - @if(!existsInCanvas) - { -
    - no quiz with same name in canvas -
    - } - -
    -
    Due At: @Quiz.DueAt
    -
    -
    - -
    -
    \ No newline at end of file diff --git a/Management.Web/Pages/Index.razor b/Management.Web/Pages/Index.razor index 3a04903..e6b11a3 100644 --- a/Management.Web/Pages/Index.razor +++ b/Management.Web/Pages/Index.razor @@ -3,7 +3,7 @@ @using CanvasModel.Courses @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @using LocalModels -@using Management.Web.Pages.Course.Module.Assignment +@using Management.Web.Pages.Course.Module.ModuleItems @using Management.Web.Shared.Components @inject CanvasService canvas diff --git a/Management.Web/Pages/QuizForm/QuizFormPage.razor b/Management.Web/Pages/QuizForm/QuizFormPage.razor index 6d48f7a..e2c1200 100644 --- a/Management.Web/Pages/QuizForm/QuizFormPage.razor +++ b/Management.Web/Pages/QuizForm/QuizFormPage.razor @@ -6,7 +6,7 @@ @using CanvasModel.Courses @using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage @using LocalModels -@using Management.Web.Pages.Course.Module.Assignment +@using Management.Web.Pages.Course.Module.ModuleItems @inject FileStorageManager fileStorageManager @inject CanvasService canvas diff --git a/Management.Web/Program.cs b/Management.Web/Program.cs index aa7a823..f1fe951 100644 --- a/Management.Web/Program.cs +++ b/Management.Web/Program.cs @@ -85,6 +85,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Management.Web/Shared/Components/MeatballsIcon.razor b/Management.Web/Shared/Components/MeatballsIcon.razor new file mode 100644 index 0000000..eb8ee13 --- /dev/null +++ b/Management.Web/Shared/Components/MeatballsIcon.razor @@ -0,0 +1,11 @@ + + + diff --git a/Management/Features/Configuration/PageEditorContext.cs b/Management/Features/Configuration/PageEditorContext.cs new file mode 100644 index 0000000..fbf67b0 --- /dev/null +++ b/Management/Features/Configuration/PageEditorContext.cs @@ -0,0 +1,148 @@ +using CanvasModel.Modules; +using LocalModels; +using Management.Planner; +using Management.Services; +using Management.Services.Canvas; + +public class PageEditorContext( + CoursePlanner planner, + CanvasService canvas, + MyLogger logger) +{ + public event Action? StateHasChanged; + private CoursePlanner planner { get; } = planner; + private CanvasService canvas { get; } = canvas; + private readonly MyLogger logger = logger; + + + private LocalCoursePage? _page; + + private LocalModule? _module; + + + public LocalCoursePage? Page + { + get => _page; + set + { + if (_page == null && value != null && planner != null && planner.LocalCourse != null) + { + _module = getCurrentLocalModule(value, planner.LocalCourse); + } + _page = value; + StateHasChanged?.Invoke(); + } + } + + public void SavePage(LocalCoursePage newPage) + { + if (planner.LocalCourse != null && _module != null && Page != null) + { + // use Page not newPage because it is the version that was last stored + + var updatedModules = planner.LocalCourse.Modules + .Select( + m => + m.Name == _module.Name + ? m with + { + Pages = m.Pages + .Select(p => p == Page ? newPage : p) + .ToArray() + } + : m + ) + .ToArray(); + + planner.LocalCourse = planner.LocalCourse with { Modules = updatedModules }; + Page = newPage; + } + } + + public void DeletePage() + { + if (planner.LocalCourse != null && Page != null && _module != null) + { + // not dealing with canvas rn + var updatedModules = planner.LocalCourse.Modules + .Select(m => m.Name != _module.Name + ? m + : m with + { + Pages = m.Pages.Where(p => p == Page).ToArray() + } + ) + .ToArray(); + + planner.LocalCourse = planner.LocalCourse with { Modules = updatedModules }; + Page = null; + } + } + + + public async Task AddPageToCanvas() + { + // logger.Log("started to add quiz to canvas"); + // if (Quiz == null) + // { + // logger.Log("cannot add null quiz to canvas"); + // return; + // } + // await planner.LoadCanvasData(); + // if (planner.CanvasQuizzes == null) + // { + // logger.Log("cannot add quiz to canvas, failed to retrieve current quizzes"); + // return; + // } + // if (planner.LocalCourse == null) + // { + // logger.Log("cannot add quiz to canvas, no course stored in planner"); + // return; + // } + // var canvasQuizId = await planner.LocalCourse.AddQuizToCanvas(Quiz, canvas); + + + + // var courseCanvasId = planner.LocalCourse.Settings.CanvasId; + // if (courseCanvasId == null) + // { + // logger.Log("was able to add quiz to canvas, but errored while making module item. CourseCanvasId is null"); + // return; + // } + + // var canvasModule = getCurrentCanvasModule(Quiz, planner.LocalCourse); + + // await canvas.CreateModuleItem( + // (ulong)courseCanvasId, + // canvasModule.Id, + // Quiz.Name, + // "Quiz", + // (ulong)canvasQuizId + // ); + + // await planner.LocalCourse.Modules.First().SortModuleItems( + // (ulong)courseCanvasId, + // canvasModule.Id, + // canvas + // ); + // logger.Log($"finished adding quiz {Quiz.Name} to canvas"); + } + + + + private static LocalModule getCurrentLocalModule(LocalCoursePage page, LocalCourse course) + { + return course.Modules.FirstOrDefault( + m => m.Pages.Contains(page) + ) + ?? throw new Exception("could not find current module in page editor context"); + } + + private CanvasModule getCurrentCanvasModule(LocalCoursePage quiz, LocalCourse course) + { + var localModule = getCurrentLocalModule(quiz, course); + var canvasModule = planner.CanvasModules?.FirstOrDefault(m => m.Name == localModule.Name) + ?? throw new Exception($"error in page context, canvas module with name {localModule.Name} not found in planner"); + return canvasModule; + } +} diff --git a/Management/Features/Configuration/QuizEditorContext.cs b/Management/Features/Configuration/QuizEditorContext.cs index f17c5d0..7090676 100644 --- a/Management/Features/Configuration/QuizEditorContext.cs +++ b/Management/Features/Configuration/QuizEditorContext.cs @@ -5,26 +5,20 @@ using Management.Planner; using Management.Services; using Management.Services.Canvas; -public class QuizEditorContext +public class QuizEditorContext( + CoursePlanner planner, + CanvasService canvas, + MyLogger logger) { - public QuizEditorContext( - CoursePlanner planner, - CanvasService canvas, - MyLogger logger) - { - this.planner = planner; - this.canvas = canvas; - this.logger = logger; - } public event Action? StateHasChanged; - private CoursePlanner planner { get; } - private CanvasService canvas { get; } + private CoursePlanner planner { get; } = planner; + private CanvasService canvas { get; } = canvas; + private readonly MyLogger logger = logger; private LocalQuiz? _quiz; private LocalModule? _module; - private readonly MyLogger logger; public LocalQuiz? Quiz { diff --git a/Management/Models/Local/Assignment/LocalAssignment.cs b/Management/Models/Local/Assignment/LocalAssignment.cs index 2a482cf..0731d45 100644 --- a/Management/Models/Local/Assignment/LocalAssignment.cs +++ b/Management/Models/Local/Assignment/LocalAssignment.cs @@ -6,7 +6,7 @@ using YamlDotNet.Serialization; namespace LocalModels; -public record LocalAssignment +public record LocalAssignment: IModuleItem { private string _name = ""; public string Name @@ -28,6 +28,7 @@ public record LocalAssignment public IEnumerable Rubric { get; init; } = Array.Empty(); public int PointsPossible => Rubric.Sum(r => r.IsExtraCredit ? 0 : r.Points); + public string GetDescriptionHtml() { return Markdig.Markdown.ToHtml(Description); diff --git a/Management/Models/Local/IModuleItem.cs b/Management/Models/Local/IModuleItem.cs new file mode 100644 index 0000000..269e4bd --- /dev/null +++ b/Management/Models/Local/IModuleItem.cs @@ -0,0 +1,9 @@ + +namespace LocalModels; + +public interface IModuleItem +{ + public string Name { get; init; } + public DateTime DueAt { get; init; } + +} diff --git a/Management/Models/Local/LocalCoursePage.cs b/Management/Models/Local/LocalCoursePage.cs index 79891bc..353432a 100644 --- a/Management/Models/Local/LocalCoursePage.cs +++ b/Management/Models/Local/LocalCoursePage.cs @@ -1,14 +1,14 @@ namespace LocalModels; -public record LocalCoursePage +public record LocalCoursePage: IModuleItem { public required string Name { get; init; } public required string Text { get; set; } - public DateTime? DueDateForOrdering { get; init; } + public DateTime DueAt { get; init; } public string ToMarkdown() { - var printableDueDate = DueDateForOrdering.ToString()?.Replace('\u202F', ' '); + var printableDueDate = DueAt.ToString()?.Replace('\u202F', ' '); var settingsMarkdown = $"Name: {Name}\n" + $"DueDateForOrdering: {printableDueDate}\n" + "---\n"; @@ -20,9 +20,9 @@ public record LocalCoursePage var name = MarkdownUtils.ExtractLabelValue(rawSettings, "Name"); var rawDate = MarkdownUtils.ExtractLabelValue(rawSettings, "DueDateForOrdering"); - DateTime? parsedDate = DateTime.TryParse(rawDate, out DateTime parsedDueAt) + DateTime parsedDate = DateTime.TryParse(rawDate, out DateTime parsedDueAt) ? parsedDueAt - : null; + : throw new LocalPageMarkdownParseException($"could not parse due date: {rawDate}"); var text = pageMarkdown.Split("---\n")[1]; @@ -30,7 +30,7 @@ public record LocalCoursePage return new LocalCoursePage { Name = name, - DueDateForOrdering = parsedDate, + DueAt = parsedDate, Text = text }; } diff --git a/Management/Models/Local/Quiz/LocalQuiz.cs b/Management/Models/Local/Quiz/LocalQuiz.cs index de3c81f..8deb817 100644 --- a/Management/Models/Local/Quiz/LocalQuiz.cs +++ b/Management/Models/Local/Quiz/LocalQuiz.cs @@ -3,7 +3,7 @@ using YamlDotNet.Serialization; namespace LocalModels; -public record LocalQuiz +public record LocalQuiz: IModuleItem { public required string Name { get; init; } public required string Description { get; init; } @@ -27,7 +27,7 @@ public record LocalQuiz .CanvasId; public string GetDescriptionHtml() => Markdig.Markdown.ToHtml(Description); - + public string ToYaml() { var serializer = new SerializerBuilder().DisableAliases().Build(); @@ -100,7 +100,7 @@ Description: {Description} var rawLockAt = extractLabelValue(settings, "LockAt"); - DateTime? lockAt = DateTime.TryParse(rawLockAt, out DateTime parsedLockAt) + DateTime? lockAt = DateTime.TryParse(rawLockAt, out DateTime parsedLockAt) ? parsedLockAt : null; @@ -153,6 +153,6 @@ public class QuizMarkdownParseException : Exception { public QuizMarkdownParseException(string message): base(message) { - + } -} \ No newline at end of file +} diff --git a/Management/Services/Files/LoadMarkdownCourse.cs b/Management/Services/Files/LoadMarkdownCourse.cs index 24f701a..c076d5f 100644 --- a/Management/Services/Files/LoadMarkdownCourse.cs +++ b/Management/Services/Files/LoadMarkdownCourse.cs @@ -131,6 +131,7 @@ public class CourseMarkdownLoader } private async Task> loadPagesFromPath(string modulePath) { + using var activity = DiagnosticsConfig.Source?.StartActivity("loading Pages from file"); var pagesPath = $"{modulePath}/pages"; if (!Directory.Exists(pagesPath)) {