diff --git a/MultipleChoiceTrainer.sln b/MultipleChoiceTrainer.sln index c4b70e2..9ac1400 100644 --- a/MultipleChoiceTrainer.sln +++ b/MultipleChoiceTrainer.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30128.74 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultipleChoiceTrainer", "MultipleChoiceTrainer\MultipleChoiceTrainer.csproj", "{5B8B8E79-0139-4A22-A789-F9A4EBD703BA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultipleChoiceTrainer", "MultipleChoiceTrainer\MultipleChoiceTrainer.csproj", "{5B8B8E79-0139-4A22-A789-F9A4EBD703BA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/MultipleChoiceTrainer/Controllers/QuestionsController.cs b/MultipleChoiceTrainer/Controllers/QuestionsController.cs index 474b128..b947af3 100644 --- a/MultipleChoiceTrainer/Controllers/QuestionsController.cs +++ b/MultipleChoiceTrainer/Controllers/QuestionsController.cs @@ -19,6 +19,12 @@ namespace MultipleChoiceTrainer.Controllers _context = context; } + public IActionResult List(int sectionId) + { + return View(_context.Questions.Include(e => e.Choices).Where(e => e.SectionId == sectionId)); + } + + // GET: Questions/Create public IActionResult Create(int sectionId) { @@ -35,6 +41,8 @@ namespace MultipleChoiceTrainer.Controllers { if (ModelState.IsValid) { + question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList(); + _context.Add(question); await _context.SaveChangesAsync(); var section = _context.Sections.FirstOrDefault(s => s.Id == question.SectionId); @@ -52,7 +60,7 @@ namespace MultipleChoiceTrainer.Controllers return NotFound(); } - var question = await _context.Questions.FindAsync(id); + var question = _context.Questions.Include(e => e.Choices).FirstOrDefault(e => e.Id == id); if (question == null) { return NotFound(); @@ -66,7 +74,7 @@ namespace MultipleChoiceTrainer.Controllers // more details, see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] - public async Task Edit(int id, [Bind("Id,Text,SectionId")] Question question) + public async Task Edit(int id, Question question) { if (id != question.Id) { @@ -75,10 +83,21 @@ namespace MultipleChoiceTrainer.Controllers if (ModelState.IsValid) { + var deletedChoices = question.Choices.Where(e => (string.IsNullOrEmpty(e.Text) || string.IsNullOrWhiteSpace(e.Text)) && e.Id != 0).Select(e => e.Id).ToList(); + + question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList(); + try { _context.Update(question); await _context.SaveChangesAsync(); + + if(deletedChoices.Any()) + { + var q = _context.Questions.Include(e => e.Choices).First(e => e.Id == id); + q.Choices.RemoveAll(e => deletedChoices.Contains(e.Id)); + await _context.SaveChangesAsync(); + } } catch (DbUpdateConcurrencyException) { @@ -91,7 +110,7 @@ namespace MultipleChoiceTrainer.Controllers throw; } } - return RedirectToAction(nameof(Index), "Home", new { categoryId = question.Section.CategoryId }); + return RedirectToAction(nameof(List), new { sectionId = question.SectionId }); } ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId); return View(question); diff --git a/MultipleChoiceTrainer/Models/DataModels/Category.cs b/MultipleChoiceTrainer/Models/DataModels/Category.cs index 795fbb2..f288927 100644 --- a/MultipleChoiceTrainer/Models/DataModels/Category.cs +++ b/MultipleChoiceTrainer/Models/DataModels/Category.cs @@ -1,4 +1,5 @@ -using System; +using MultipleChoiceTrainer.Validation; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; @@ -11,6 +12,7 @@ namespace MultipleChoiceTrainer.Models.DataModels public int Id { get; set; } [Display(Name="Name")] + [NotNullOrEmpty] public string Name { get; set; } [Display(Name = "Beschreibung")] public string Description { get; set; } diff --git a/MultipleChoiceTrainer/Models/DataModels/Question.cs b/MultipleChoiceTrainer/Models/DataModels/Question.cs index 6f02646..b882490 100644 --- a/MultipleChoiceTrainer/Models/DataModels/Question.cs +++ b/MultipleChoiceTrainer/Models/DataModels/Question.cs @@ -1,6 +1,8 @@ -using System; +using MultipleChoiceTrainer.Validation; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; @@ -10,12 +12,14 @@ namespace MultipleChoiceTrainer.Models.DataModels { public int Id { get; set; } [Display(Name="Frage")] + [NotNullOrEmpty] public string Text { get; set; } public Section Section { get; set; } public int SectionId { get; set; } [Display(Name = "Antwortmöglichkeiten")] + [NotEmptyChoiceCollection()] public List Choices { get; set; } public ICollection Answers { get; set; } = new HashSet(); diff --git a/MultipleChoiceTrainer/Models/DataModels/Section.cs b/MultipleChoiceTrainer/Models/DataModels/Section.cs index 188499f..2461cd8 100644 --- a/MultipleChoiceTrainer/Models/DataModels/Section.cs +++ b/MultipleChoiceTrainer/Models/DataModels/Section.cs @@ -1,4 +1,5 @@ -using System; +using MultipleChoiceTrainer.Validation; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; @@ -11,6 +12,7 @@ namespace MultipleChoiceTrainer.Models.DataModels public int Id { get; set; } [Display(Name = "Name")] + [NotNullOrEmpty] public string Name { get; set; } [Display(Name = "Beschreibung")] public string Description { get; set; } diff --git a/MultipleChoiceTrainer/Validation/NotEmptyChoiceCollectionAttribute.cs b/MultipleChoiceTrainer/Validation/NotEmptyChoiceCollectionAttribute.cs new file mode 100644 index 0000000..fbf7263 --- /dev/null +++ b/MultipleChoiceTrainer/Validation/NotEmptyChoiceCollectionAttribute.cs @@ -0,0 +1,43 @@ +using MultipleChoiceTrainer.Models.DataModels; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace MultipleChoiceTrainer.Validation +{ + public class NotEmptyChoiceCollectionAttribute : ValidationAttribute + { + public NotEmptyChoiceCollectionAttribute() + { + + } + + + public override bool IsValid(object value) + { + ErrorMessage = "Es müssen mindestens zwei Antwortmöglichkeiten eingegeben werden!"; + + if (value == null || !(value is ICollection collection)) + { + return false; + } + + if(collection == null || collection.Where(e => !string.IsNullOrEmpty(e.Text)).Count() < 2) + { + return false; + } + + if(!collection.Where(e => !string.IsNullOrEmpty(e.Text)).Any(e => e.IsTrue)) + { + ErrorMessage = "Es muss mindestens eine richtige Antwort eingegeben werden!"; + return false; + } + + return true; + } + + } +} diff --git a/MultipleChoiceTrainer/Validation/NotNullOrEmptyAttribute.cs b/MultipleChoiceTrainer/Validation/NotNullOrEmptyAttribute.cs new file mode 100644 index 0000000..87ebd78 --- /dev/null +++ b/MultipleChoiceTrainer/Validation/NotNullOrEmptyAttribute.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; + +namespace MultipleChoiceTrainer.Validation +{ + public class NotNullOrEmptyAttribute : ValidationAttribute + { + public NotNullOrEmptyAttribute() + { + } + + protected override ValidationResult IsValid(object value, ValidationContext validationContext) + { + if (value == null) + return new ValidationResult($"{validationContext.DisplayName} darf nicht leer sein!"); + + if (string.IsNullOrEmpty(value.ToString()) || string.IsNullOrWhiteSpace(value.ToString())) + { + return new ValidationResult($"{validationContext.DisplayName} darf nicht leer sein!"); + } + + return ValidationResult.Success; + } + } +} diff --git a/MultipleChoiceTrainer/Views/Home/_homeLogInPartial.cshtml b/MultipleChoiceTrainer/Views/Home/_homeLogInPartial.cshtml index 3599e07..c56bff2 100644 --- a/MultipleChoiceTrainer/Views/Home/_homeLogInPartial.cshtml +++ b/MultipleChoiceTrainer/Views/Home/_homeLogInPartial.cshtml @@ -29,7 +29,7 @@
    @sub.Name @sub.Description
    - @sub.Questions.Count() Fragen + @sub.Questions.Count() Fragen

    Lektion bearbeiten     diff --git a/MultipleChoiceTrainer/Views/Questions/Create.cshtml b/MultipleChoiceTrainer/Views/Questions/Create.cshtml index d5831d2..a3d86bc 100644 --- a/MultipleChoiceTrainer/Views/Questions/Create.cshtml +++ b/MultipleChoiceTrainer/Views/Questions/Create.cshtml @@ -12,33 +12,37 @@

    -
    - - - +
    + + +
    -
    - - @if (Model != null && Model.Choices != null) - { - @for (int i = 0; i < Model.Choices.Count; i++) +
    + +
    + @for (int i = 0; i < 5; i++) { -
    - - -
    +
    + @if (Model != null && Model.Choices != null && Model.Choices.Count > i) + { + +
    + + +
    + } + else + { + +
    + + +
    + } +
    } - } - else - { - - - - - - - - } + +
    diff --git a/MultipleChoiceTrainer/Views/Questions/Edit.cshtml b/MultipleChoiceTrainer/Views/Questions/Edit.cshtml index 0e737b1..5da25e8 100644 --- a/MultipleChoiceTrainer/Views/Questions/Edit.cshtml +++ b/MultipleChoiceTrainer/Views/Questions/Edit.cshtml @@ -13,9 +13,41 @@
    -
    - + +
    + + +
    +
    + +
    + @for (int i = 0; i < 5; i++) + { +
    + @if (Model != null && Model.Choices != null && Model.Choices.Count > i) + { + + +
    + + +
    + } + else + { + +
    + + +
    + } +
    + } + +
    +
    +
    Abbrechen diff --git a/MultipleChoiceTrainer/Views/Questions/List.cshtml b/MultipleChoiceTrainer/Views/Questions/List.cshtml new file mode 100644 index 0000000..f6a90b6 --- /dev/null +++ b/MultipleChoiceTrainer/Views/Questions/List.cshtml @@ -0,0 +1,37 @@ +@model IEnumerable +@{ + ViewData["Title"] = "Fragen"; +} + + + + + + + + + + +@foreach (var item in Model) { + + + + + + +} + +
    + @Html.DisplayNameFor(model => model.Text) + + @Html.DisplayNameFor(model => model.Choices) +
    + @Html.DisplayFor(modelItem => item.Text) + + @foreach (var choice in item.Choices) + { + @choice.Text
    + } +
    + Bearbeiten +