diff --git a/.editorconfig b/.editorconfig index 7edc7c4..45e8641 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,4 +14,190 @@ dotnet_diagnostic.CA2254.severity = none [*.razor] indent_style = ignore -indent_size = ignore \ No newline at end of file +indent_size = ignore + + +# Default settings: +# A newline ending every file +# Use 4 spaces as indentation +[*] +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[project.json] +indent_size = 2 + +# Generated code +[*{_AssemblyInfo.cs,.notsupported.cs}] +generated_code = true + +# C# files +[*.cs] +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# Types: use keywords instead of BCL types, and permit var only when the type is clear +# csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:none +# csharp_style_var_elsewhere = false:suggestion +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# static fields should have s_ prefix +# dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion +# dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +# dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +# dotnet_naming_symbols.static_fields.applicable_kinds = field +# dotnet_naming_symbols.static_fields.required_modifiers = static +# dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected +# dotnet_naming_style.static_prefix_style.required_prefix = s_ +# dotnet_naming_style.static_prefix_style.capitalization = camel_case + +# internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# Code style defaults +csharp_using_directive_placement = outside_namespace:suggestion +dotnet_sort_system_directives_first = true +csharp_prefer_braces = true:silent +csharp_preserve_single_line_blocks = true:none +csharp_preserve_single_line_statements = false:none +csharp_prefer_static_local_function = true:suggestion +csharp_prefer_simple_using_statement = false:none +csharp_style_prefer_switch_expression = true:suggestion +dotnet_style_readonly_field = true:suggestion + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +csharp_prefer_simple_default_expression = true:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_constructors = true:silent +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = true:silent + +# Pattern matching +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Other features +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_pattern_local_over_anonymous_function = false:none + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# C++ Files +[*.{cpp,h,in}] +curly_bracket_next_line = true +indent_brace_style = Allman + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +[*.{csproj,vbproj,proj,nativeproj,locproj}] +charset = utf-8 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# YAML config files +[*.{yml,yaml}] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf +[*.{cmd,bat}] +end_of_line = crlf \ No newline at end of file diff --git a/Management.Web/Pages/Course.razor b/Management.Web/Pages/Course.razor index 30342b0..b0fd274 100644 --- a/Management.Web/Pages/Course.razor +++ b/Management.Web/Pages/Course.razor @@ -57,9 +57,9 @@ - + *@ View In Canvas diff --git a/Management.Web/Shared/Module/ModuleDetail.razor b/Management.Web/Shared/Module/ModuleDetail.razor index dea9a58..6d06808 100644 --- a/Management.Web/Shared/Module/ModuleDetail.razor +++ b/Management.Web/Shared/Module/ModuleDetail.razor @@ -83,7 +83,7 @@ private bool isSyncedWithCanvas => planner .CanvasModules? .FirstOrDefault( - cm => cm.Id == Module.CanvasId + cm => cm.Name == Module.Name ) != null; } diff --git a/Management/Features/Configuration/AssignmentEditorContext.cs b/Management/Features/Configuration/AssignmentEditorContext.cs index 5e315d5..f24cd53 100644 --- a/Management/Features/Configuration/AssignmentEditorContext.cs +++ b/Management/Features/Configuration/AssignmentEditorContext.cs @@ -1,3 +1,4 @@ +using CanvasModel.Modules; using LocalModels; using Management.Planner; using Management.Services; @@ -39,7 +40,7 @@ public class AssignmentEditorContext if (planner.LocalCourse != null) { // run discovery on Assignment, it was the last stored version of the assignment - var currentModule = getCurrentModule(Assignment, planner.LocalCourse); + var currentModule = getCurrentLocalModule(Assignment, planner.LocalCourse); var updatedModules = planner.LocalCourse.Modules .Select( @@ -146,16 +147,11 @@ public class AssignmentEditorContext canvas: canvas ); - var currentModule = getCurrentModule(Assignment, planner.LocalCourse); - if (currentModule.CanvasId == null) - { - logger.Log("was able to add assignment to canvas, but errored while making module item. module canvasId is null"); - return; - } + var canvasModule = getCurrentCanvasModule(Assignment, planner.LocalCourse); await canvas.CreateModuleItem( (ulong)courseCanvasId, - (ulong)currentModule.CanvasId, + canvasModule.Id, Assignment.Name, "Assignment", createdAssignmentCanvasId @@ -163,17 +159,25 @@ public class AssignmentEditorContext await planner.LocalCourse.Modules.First().SortModuleItems( (ulong)courseCanvasId, - (ulong)currentModule.CanvasId, + canvasModule.Id, canvas ); logger.Log($"finished adding assignment {Assignment.Name} to canvas"); } - private static LocalModule getCurrentModule(LocalAssignment assignment, LocalCourse course) + private static LocalModule getCurrentLocalModule(LocalAssignment assignment, LocalCourse course) { return course.Modules.FirstOrDefault( m => m.Assignments.Select(a => a.Name).Contains(assignment.Name) ) ?? throw new Exception("could not find current module in assignment editor context"); } + + private CanvasModule getCurrentCanvasModule(LocalAssignment assignment, LocalCourse course) + { + var localModule = getCurrentLocalModule(assignment, course); + var canvasModule = planner.CanvasModules?.FirstOrDefault(m => m.Name == localModule.Name) + ?? throw new Exception($"error in assignment context, canvas module with name {localModule.Name} not found in planner"); + return canvasModule; + } } diff --git a/Management/Features/Configuration/CoursePlanner.cs b/Management/Features/Configuration/CoursePlanner.cs index 826dc11..52cb443 100644 --- a/Management/Features/Configuration/CoursePlanner.cs +++ b/Management/Features/Configuration/CoursePlanner.cs @@ -76,12 +76,12 @@ public class CoursePlanner public IEnumerable? CanvasAssignmentGroups { get; internal set; } public IEnumerable? CanvasQuizzes { get; internal set; } public IEnumerable? CanvasModules { get; internal set; } - public Dictionary>? CanvasModulesItems { get; internal set; } + public Dictionary>? CanvasModulesItems { get; internal set; } public async Task<( IEnumerable CanvasAssignments, IEnumerable CanvasModules, - Dictionary> CanvasModulesItems, + Dictionary> CanvasModulesItems, IEnumerable canvasQuizzes, IEnumerable canvasAssignmentGroups )> LoadCanvasData() @@ -155,12 +155,11 @@ public class CoursePlanner }; - var newModules = await LocalCourse.CreateAllModules( + await LocalCourse.CreateAllModules( canvasId, CanvasModules, canvas ); - LocalCourse = LocalCourse with { Modules = newModules }; CanvasModules = await canvas.Modules.GetModules(canvasId); await LocalCourse.SortCanvasModulesByLocalOrder(canvasId, CanvasModules, canvas); diff --git a/Management/Features/Configuration/CoursePlannerValidationExtensions.cs b/Management/Features/Configuration/CoursePlannerValidationExtensions.cs index 2d78d76..8b9527d 100644 --- a/Management/Features/Configuration/CoursePlannerValidationExtensions.cs +++ b/Management/Features/Configuration/CoursePlannerValidationExtensions.cs @@ -87,7 +87,7 @@ public static class CoursePlannerExtensions IEnumerable canvasQuizzes ) { - var moduleIdInCanvas = canvasModules.FirstOrDefault(m => m.Id == module.CanvasId) != null; + var moduleIdInCanvas = canvasModules.FirstOrDefault(m => m.Name == module.Name) != null; var moduleWithAssignments = module with { Assignments = module.Assignments @@ -100,7 +100,7 @@ public static class CoursePlannerExtensions Console.WriteLine( $"no id in canvas for module, removing old canvas id: {moduleWithAssignments.Name}" ); - return moduleWithAssignments with { CanvasId = null }; + return moduleWithAssignments; } return moduleWithAssignments; } diff --git a/Management/Features/Configuration/QuizEditorContext.cs b/Management/Features/Configuration/QuizEditorContext.cs index 69b1da1..34f6729 100644 --- a/Management/Features/Configuration/QuizEditorContext.cs +++ b/Management/Features/Configuration/QuizEditorContext.cs @@ -1,4 +1,5 @@ using System.Reflection.Metadata.Ecma335; +using CanvasModel.Modules; using LocalModels; using Management.Planner; using Management.Services; @@ -32,7 +33,7 @@ public class QuizEditorContext { if (_quiz == null && value != null) { - _module = getCurrentModule(value, planner.LocalCourse); + _module = getCurrentLocalModule(value, planner.LocalCourse); } _quiz = value; StateHasChanged?.Invoke(); @@ -115,16 +116,11 @@ public class QuizEditorContext return; } - var currentModule = getCurrentModule(Quiz, planner.LocalCourse); - if (currentModule.CanvasId == null) - { - logger.Log("was able to add quiz to canvas, but errored while making module item. module canvasId is null"); - return; - } + var canvasModule = getCurrentCanvasModule(Quiz, planner.LocalCourse); await canvas.CreateModuleItem( (ulong)courseCanvasId, - (ulong)currentModule.CanvasId, + canvasModule.Id, Quiz.Name, "Quiz", (ulong)canvasQuizId @@ -132,17 +128,25 @@ public class QuizEditorContext await planner.LocalCourse.Modules.First().SortModuleItems( (ulong)courseCanvasId, - (ulong)currentModule.CanvasId, + canvasModule.Id, canvas ); logger.Log($"finished adding quiz {Quiz.Name} to canvas"); } - private static LocalModule getCurrentModule(LocalQuiz quiz, LocalCourse course) + private static LocalModule getCurrentLocalModule(LocalQuiz quiz, LocalCourse course) { return course.Modules.FirstOrDefault( m => m.Quizzes.Select(q => q.Name + q.Description).Contains(quiz.Name + quiz.Description) ) ?? throw new Exception("could not find current module in quiz editor context"); } + + private CanvasModule getCurrentCanvasModule(LocalQuiz quiz, LocalCourse course) + { + var localModule = getCurrentLocalModule(quiz, course); + var canvasModule = planner.CanvasModules?.FirstOrDefault(m => m.Name == localModule.Name) + ?? throw new Exception($"error in quiz context, canvas module with name {localModule.Name} not found in planner"); + return canvasModule; + } } diff --git a/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs b/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs index 9a6b147..57012a7 100644 --- a/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs +++ b/Management/Features/Configuration/Synchronization/ModuleSyncronizationExtensions.cs @@ -6,7 +6,7 @@ namespace Management.Planner; public static partial class ModuleSyncronizationExtensions { - internal static async Task> CreateAllModules( + internal static async Task CreateAllModules( this LocalCourse localCourse, ulong canvasCourseId, IEnumerable canvasModules, @@ -15,21 +15,18 @@ public static partial class ModuleSyncronizationExtensions { var moduleTasks = localCourse.Modules.Select(async module => { - var canvasModule = canvasModules.FirstOrDefault(cm => cm.Id == module.CanvasId); + var canvasModule = canvasModules.FirstOrDefault(cm => cm.Name == module.Name); if (canvasModule == null) { var newModule = await canvas.Modules.CreateModule(canvasCourseId, module.Name); - return module with { CanvasId = newModule.Id }; } - if (canvasModule.Name != module.Name) + if (canvasModule?.Name != module.Name) // TODO: maybe check to see if we have name change here { await canvas.Modules.UpdateModule(canvasCourseId, canvasModule.Id, module.Name, canvasModule.Position); } - return module; }); - var newModules = await Task.WhenAll(moduleTasks); - return newModules ?? throw new Exception("Error ensuring all modules exist in canvas"); + await Task.WhenAll(moduleTasks); } internal static async Task SortCanvasModulesByLocalOrder( @@ -42,13 +39,14 @@ public static partial class ModuleSyncronizationExtensions var currentCanvasPositions = canvasModules.ToDictionary(m => m.Id, m => m.Position); foreach (var (localModule, i) in localCourse.Modules.Select((m, i) => (m, i))) { + uint correctPosition = (uint)(i + 1); - var moduleCanvasId = - localModule.CanvasId ?? throw new Exception("cannot sort module if no module canvas id"); - var currentCanvasPosition = currentCanvasPositions[moduleCanvasId]; + var canvasModule = canvasModules.FirstOrDefault(c => c.Name == localModule.Name) ?? throw new Exception($"error sorting canvas module, could not find canvas module with name {localModule.Name}"); ; + + var currentCanvasPosition = currentCanvasPositions[canvasModule.Id]; if (currentCanvasPosition != correctPosition) { - await canvas.Modules.UpdateModule(canvasId, moduleCanvasId, localModule.Name, correctPosition); + await canvas.Modules.UpdateModule(canvasId, canvasModule.Id, localModule.Name, correctPosition); } } } @@ -59,15 +57,15 @@ public static partial class ModuleSyncronizationExtensions CanvasService canvas ) { - var canvasModules = await canvas.Modules.GetModules(canvasId); - return localCourse with - { - Modules = localCourse.Modules.Select(m => - { - var canvasModule = canvasModules.FirstOrDefault(cm => cm.Name == m.Name); - return canvasModule == null ? m : m with { CanvasId = canvasModule.Id }; - }) - }; + // var canvasModules = await canvas.Modules.GetModules(canvasId); + return localCourse; + // { + // Modules = localCourse.Modules.Select(m => + // { + // var canvasModule = canvasModules.FirstOrDefault(cm => cm.Name == m.Name); + // return canvasModule == null ? m : m with { CanvasId = canvasModule.Id }; + // }) + // }; } public static async Task SortModuleItems( @@ -112,15 +110,15 @@ public static partial class ModuleSyncronizationExtensions internal static async Task EnsureAllModulesItemsCreated( this LocalModule localModule, ulong canvasId, - ulong moduleCanvasId, - Dictionary> canvasModulesItems, + CanvasModule canvasModule, + Dictionary> canvasModulesItems, CanvasService canvas ) { var anyUpdated = false; foreach (var localAssignment in localModule.Assignments.Where(a => a.DueAt > DateTime.Now)) { - var canvasModuleItemContentIds = canvasModulesItems[moduleCanvasId].Select(i => i.ContentId); + var canvasModuleItemContentIds = canvasModulesItems[canvasModule].Select(i => i.ContentId); if (!canvasModuleItemContentIds.Contains(localAssignment.CanvasId)) { var canvasAssignmentId = @@ -128,7 +126,7 @@ public static partial class ModuleSyncronizationExtensions ?? throw new Exception("cannot create module item if assignment does not have canvas id"); await canvas.CreateModuleItem( canvasId, - moduleCanvasId, + canvasModule.Id, localAssignment.Name, "Assignment", canvasAssignmentId @@ -142,29 +140,34 @@ public static partial class ModuleSyncronizationExtensions internal static async Task SyncModuleItemsWithCanvas( this LocalCourse localCourse, - ulong canvasId, - Dictionary> canvasModulesItems, + ulong courseCanvasId, + Dictionary> canvasModulesItems, CanvasService canvas ) { foreach (var localModule in localCourse.Modules) { - var moduleCanvasId = - localModule.CanvasId - ?? throw new Exception("cannot sync canvas modules items if module not synced with canvas"); + // var moduleCanvasId = + // localModule.CanvasId + // ?? throw new Exception("cannot sync canvas modules items if module not synced with canvas"); + var canvasModule = canvasModulesItems.Keys.FirstOrDefault(k => k.Name == localModule.Name); + if(canvasModule == null) + { + throw new Exception($"cannot sync module items in canvas, could not find module with name ${localModule.Name}"); + } bool anyUpdated = await localModule.EnsureAllModulesItemsCreated( - canvasId, - moduleCanvasId, + courseCanvasId, + canvasModule, canvasModulesItems, canvas ); var canvasModuleItems = anyUpdated - ? await canvas.Modules.GetModuleItems(canvasId, moduleCanvasId) - : canvasModulesItems[moduleCanvasId]; + ? await canvas.Modules.GetModuleItems(courseCanvasId, canvasModule.Id) + : canvasModulesItems[canvasModule]; - await localModule.SortModuleItems(canvasId, moduleCanvasId, canvas); + await localModule.SortModuleItems(courseCanvasId, canvasModule.Id, canvas); } } } diff --git a/Management/Models/Local/LocalCourse.cs b/Management/Models/Local/LocalCourse.cs index c1ee743..41f8bf1 100644 --- a/Management/Models/Local/LocalCourse.cs +++ b/Management/Models/Local/LocalCourse.cs @@ -27,6 +27,16 @@ public record LocalCourseSettings var yaml = serializer.Serialize(this); return yaml; } + + public static LocalCourseSettings ParseYaml(string rawText) + { + var deserializer = new DeserializerBuilder() + .IgnoreUnmatchedProperties() + .Build(); + + var settings = deserializer.Deserialize(rawText); + return settings; + } } public record SimpleTimeOnly diff --git a/Management/Models/Local/LocalModules.cs b/Management/Models/Local/LocalModules.cs index 28bf559..23894d9 100644 --- a/Management/Models/Local/LocalModules.cs +++ b/Management/Models/Local/LocalModules.cs @@ -4,7 +4,7 @@ public record LocalModule { public string Name { get; init; } = string.Empty; public string Id { get; init; } = DateTime.UtcNow.Ticks.ToString(); - public ulong? CanvasId { get; set; } = null; + // public ulong? CanvasId { get; set; } = null; public string Notes { get; set; } = string.Empty; public IEnumerable Assignments { get; init; } = Enumerable.Empty(); diff --git a/Management/Services/Canvas/CanvasModuleService.cs b/Management/Services/Canvas/CanvasModuleService.cs index 94d8088..014e187 100644 --- a/Management/Services/Canvas/CanvasModuleService.cs +++ b/Management/Services/Canvas/CanvasModuleService.cs @@ -65,7 +65,7 @@ public class CanvasModuleService return items; } - public async Task>> GetAllModulesItems( + public async Task>> GetAllModulesItems( ulong courseId, IEnumerable modules ) @@ -78,7 +78,7 @@ public class CanvasModuleService } ); - var output = new Dictionary>(); + var output = new Dictionary>(); var itemTasksResult = await Task.WhenAll(itemsTasks); foreach (var (module, items) in itemTasksResult) { @@ -86,7 +86,7 @@ public class CanvasModuleService throw new Exception( "i'm not sure how we got here, but module and items are null after looking up module items" ); - output[module.Id] = items; + output[module] = items; } return output; } diff --git a/Management/Services/Canvas/CanvasQuizService.cs b/Management/Services/Canvas/CanvasQuizService.cs index 78a550a..92dffa6 100644 --- a/Management/Services/Canvas/CanvasQuizService.cs +++ b/Management/Services/Canvas/CanvasQuizService.cs @@ -1,27 +1,18 @@ -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; using CanvasModel.Quizzes; using LocalModels; using RestSharp; namespace Management.Services.Canvas; -public class CanvasQuizService +public class CanvasQuizService( + IWebRequestor webRequestor, + CanvasServiceUtils utils, + CanvasAssignmentService assignments +) { - private readonly IWebRequestor webRequestor; - private readonly CanvasServiceUtils utils; - private readonly CanvasAssignmentService assignments; - - public CanvasQuizService( - IWebRequestor webRequestor, - CanvasServiceUtils utils, - CanvasAssignmentService assignments - ) - { - this.webRequestor = webRequestor; - this.utils = utils; - this.assignments = assignments; - } + private readonly IWebRequestor webRequestor = webRequestor; + private readonly CanvasServiceUtils utils = utils; + private readonly CanvasAssignmentService assignments = assignments; public async Task> GetAll(ulong courseId) { diff --git a/Management/Services/FileStorageManager.cs b/Management/Services/FileStorageManager.cs index 833dc74..3a343dc 100644 --- a/Management/Services/FileStorageManager.cs +++ b/Management/Services/FileStorageManager.cs @@ -6,9 +6,12 @@ using YamlDotNet.Serialization.NamingConventions; public class FileStorageManager { private readonly MyLogger logger; + private static readonly string _basePath = "../storage"; public FileStorageManager(MyLogger logger) { + if (!Directory.Exists(_basePath)) + throw new Exception("storage folder not found"); this.logger = logger; } public string CourseToYaml(LocalCourse course) @@ -32,18 +35,18 @@ public class FileStorageManager { var courseString = CourseToYaml(course); - var courseDirectory = $"../storage/{course.Settings.Name}"; + var courseDirectory = $"{_basePath}/{course.Settings.Name}"; if (!Directory.Exists(courseDirectory)) Directory.CreateDirectory(courseDirectory); await saveModules(course); - await File.WriteAllTextAsync($"../storage/{course.Settings.Name}.yml", courseString); + await File.WriteAllTextAsync($"{_basePath}/{course.Settings.Name}.yml", courseString); } private async Task saveModules(LocalCourse course) { - var courseDirectory = $"../storage/{course.Settings.Name}"; + var courseDirectory = $"{_basePath}/{course.Settings.Name}"; await saveSettings(course, courseDirectory); foreach (var module in course.Modules) @@ -67,7 +70,7 @@ public class FileStorageManager private async Task saveQuizzes(LocalCourse course, LocalModule module) { - var quizzesDirectory = $"../storage/{course.Settings.Name}/{module.Name}/quizzes"; + var quizzesDirectory = $"{_basePath}/{course.Settings.Name}/{module.Name}/quizzes"; if (!Directory.Exists(quizzesDirectory)) Directory.CreateDirectory(quizzesDirectory); @@ -106,7 +109,7 @@ public class FileStorageManager private async Task saveAssignments(LocalCourse course, LocalModule module) { - var assignmentsDirectory = $"../storage/{course.Settings.Name}/{module.Name}/assignments"; + var assignmentsDirectory = $"{_basePath}/{course.Settings.Name}/{module.Name}/assignments"; if (!Directory.Exists(assignmentsDirectory)) Directory.CreateDirectory(assignmentsDirectory); @@ -139,22 +142,83 @@ public class FileStorageManager logger.Log($"removing old assignment, it has probably been renamed {file}"); File.Delete(file); } - } public async Task> LoadSavedCourses() { - string path = "../storage/"; - if (!Directory.Exists(path)) - throw new Exception("storage folder not found"); - var fileNames = Directory.GetFiles(path); + var fileNames = Directory.GetFiles(_basePath); var courses = await Task.WhenAll( fileNames .Where(name => name.EndsWith(".yml")) - .Select(async n => ParseCourse(await File.ReadAllTextAsync($"../storage/{n}"))) + .Select(async n => ParseCourse(await File.ReadAllTextAsync($"{_basePath}/{n}"))) ); return courses; } + + // public async Task LoadCourseByName(string courseName) + // { + // var courseDirectory = $"{_basePath}/{courseName}"; + // if (!Directory.Exists(courseDirectory)) + // { + // var errorMessage = $"error loading course by name, could not find folder {courseDirectory}"; + // logger.Log(errorMessage); + // throw new LoadCourseFromFileException(errorMessage); + // } + // var settingsPath = $"{courseDirectory}/settings.yml"; + // if (!Directory.Exists(settingsPath)) + // { + // var errorMessage = $"error loading course by name, settings file {settingsPath}"; + // logger.Log(errorMessage); + // throw new LoadCourseFromFileException(errorMessage); + // } + + // var settingsString = await File.ReadAllTextAsync(settingsPath); + // var settings = LocalCourseSettings.ParseYaml(settingsString); + + // var modulePaths = Directory.GetDirectories(courseDirectory); + // var modules = modulePaths + // .Select(LoadModuleFromPath) + // .ToArray(); + + // } + + // public async Task LoadModuleFromPath(string modulePath) + // { + // var assignmentsPath = $"{modulePath}/assignments"; + // if (!Directory.Exists(assignmentsPath)) + // { + // var errorMessage = $"error loading course by name, assignments folder does not exist in {modulePath}"; + // logger.Log(errorMessage); + // throw new LoadCourseFromFileException(errorMessage); + // } + + // var quizzesPath = $"{modulePath}/quizzes"; + // if (!Directory.Exists(quizzesPath)) + // { + // var errorMessage = $"error loading course by name, quizzes folder does not exist in {modulePath}"; + // logger.Log(errorMessage); + // throw new LoadCourseFromFileException(errorMessage); + // } + + + // var assignments = LoadAssignmentsFromPath(assignmentsPath); + // var quizzes = LoadQuizzesFromPath(quizzesPath); + + + // } + // public async Task> LoadAssignmentsFromPath(string assignmentsFolder) + // { + + // } + // public async Task> LoadQuizzesFromPath(string quizzesFolder) + // { + + // } } + + +public class LoadCourseFromFileException(string message) : Exception(message) +{ +} \ No newline at end of file