Bilder zur Frage können hochgeladen werden;

This commit is contained in:
2020-06-13 23:08:16 +02:00
parent 7b445ae16e
commit 64bda646b5
8 changed files with 128 additions and 53 deletions

3
.gitignore vendored
View File

@@ -339,4 +339,5 @@ ASALocalRun/
# BeatPulse healthcheck temp database
healthchecksdb
**/appsettings.json
**/appsettings.json
**/uploads/

View File

@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using MultipleChoiceTrainer.Data;
using MultipleChoiceTrainer.Models;
using MultipleChoiceTrainer.Models.DataModels;
namespace MultipleChoiceTrainer.Controllers
@@ -13,10 +16,11 @@ namespace MultipleChoiceTrainer.Controllers
public class QuestionsController : Controller
{
private readonly ApplicationDbContext _context;
public QuestionsController(ApplicationDbContext context)
private readonly IWebHostEnvironment _webHostEnvironment;
public QuestionsController(ApplicationDbContext context, IWebHostEnvironment hostEnvironment)
{
_context = context;
_webHostEnvironment = hostEnvironment;
}
public IActionResult List(int sectionId)
@@ -37,13 +41,14 @@ namespace MultipleChoiceTrainer.Controllers
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Question question)
{
public async Task<IActionResult> Create(QuestionViewModel question)
{
if (ModelState.IsValid)
{
{
question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList();
CopyUploadedFile(question);
_context.Add(question);
_context.Add(question as Question);
await _context.SaveChangesAsync();
var section = _context.Sections.FirstOrDefault(s => s.Id == question.SectionId);
return RedirectToAction(nameof(Index), "Home", new { categoryId = section.CategoryId });
@@ -66,7 +71,16 @@ namespace MultipleChoiceTrainer.Controllers
return NotFound();
}
ViewData["Section"] = _context.Sections.Include(e => e.Category).FirstOrDefault(s => s.Id == question.SectionId);
return View(question);
var vm = new QuestionViewModel()
{
Choices = question.Choices,
Image = question.Image,
Id = question.Id,
SectionId = question.SectionId,
Text = question.Text
};
return View(vm);
}
// POST: Questions/Edit/5
@@ -74,7 +88,7 @@ namespace MultipleChoiceTrainer.Controllers
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, Question question)
public async Task<IActionResult> Edit(int id, QuestionViewModel question)
{
if (id != question.Id)
{
@@ -87,9 +101,10 @@ namespace MultipleChoiceTrainer.Controllers
question.Choices = question.Choices.ToList().Where(e => !string.IsNullOrEmpty(e.Text) && !string.IsNullOrWhiteSpace(e.Text)).ToList();
CopyUploadedFile(question);
try
{
_context.Update(question);
_context.Update(question as Question);
await _context.SaveChangesAsync();
if(deletedChoices.Any())
@@ -120,5 +135,21 @@ namespace MultipleChoiceTrainer.Controllers
{
return _context.Questions.Any(e => e.Id == id);
}
private void CopyUploadedFile(QuestionViewModel model)
{
if (model.QuestionImage != null)
{
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "uploads", "images", "questions");
Directory.CreateDirectory(uploadsFolder);
model.Image = Guid.NewGuid().ToString() + Path.GetExtension(model.QuestionImage.FileName);
string filePath = Path.Combine(uploadsFolder, model.Image);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
model.QuestionImage.CopyTo(fileStream);
}
}
}
}
}

View File

@@ -18,6 +18,8 @@ namespace MultipleChoiceTrainer.Models.DataModels
public Section Section { get; set; }
public int SectionId { get; set; }
public string Image { get; set; }
[Display(Name = "Antwortmöglichkeiten")]
[NotEmptyChoiceCollection()]
public List<Choice> Choices { get; set; }

View File

@@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Http;
using MultipleChoiceTrainer.Models.DataModels;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace MultipleChoiceTrainer.Models
{
public class QuestionViewModel : Question
{
[Display(Name ="Bild zur Frage")]
public IFormFile QuestionImage { get; set; }
}
}

View File

@@ -1,4 +1,4 @@
@model MultipleChoiceTrainer.Models.DataModels.Question
@model MultipleChoiceTrainer.Models.QuestionViewModel
@{
ViewData["Title"] = "Frage Anlegen";
@@ -9,7 +9,7 @@
<hr />
<div class="row">
<div class="col-md-12">
<form asp-action="Create">
<form asp-action="Create" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="SectionId" value="@ViewBag.Section.Id" />
<div class="form-group row">
@@ -17,31 +17,37 @@
<input asp-for="Text" class="form-control col-10" />
<span asp-validation-for="Text" class="text-danger offset-2"></span>
</div>
<div class="form-group row">
<div class="custom-file col-10 offset-2">
<input class="custom-file-input" asp-for="QuestionImage">
<label class="custom-file-label" asp-for="QuestionImage"></label>
</div>
</div>
<div class="form-group row">
<label asp-for="Choices" class="control-label col-2"></label>
<div class="col-10 row">
@for (int i = 0; i < 5; i++)
{
<div class="row col-12 mb-1 px-0 mx-0">
@if (Model != null && Model.Choices != null && Model.Choices.Count > i)
{
<input asp-for="@Model.Choices[i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input asp-for="@Model.Choices[i].IsTrue" class="form-check-input" value="true" />
<label asp-for="@Model.Choices[i].IsTrue" class="form-check-label">Richtig</label>
</div>
}
else
{
<input type="text" name="Choices[@i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input type="checkbox" name="Choices[@i].IsTrue" id="CheckBox-IsTrue-@i" class="form-check-input" value="true" />
<label for="CheckBox-IsTrue-@i" class="form-check-label">Richtig</label>
</div>
}
</div>
<div class="row col-12 mb-1 px-0 mx-0">
@if (Model != null && Model.Choices != null && Model.Choices.Count > i)
{
<input asp-for="@Model.Choices[i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input asp-for="@Model.Choices[i].IsTrue" class="form-check-input" value="true" />
<label asp-for="@Model.Choices[i].IsTrue" class="form-check-label">Richtig</label>
</div>
}
else
{
<input type="text" name="Choices[@i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input type="checkbox" name="Choices[@i].IsTrue" id="CheckBox-IsTrue-@i" class="form-check-input" value="true" />
<label for="CheckBox-IsTrue-@i" class="form-check-label">Richtig</label>
</div>
}
</div>
}
<span asp-validation-for="Choices" class="text-danger" ></span>
<span asp-validation-for="Choices" class="text-danger"></span>
</div>
</div>
<div class="form-group">

View File

@@ -1,4 +1,4 @@
@model MultipleChoiceTrainer.Models.DataModels.Question
@model MultipleChoiceTrainer.Models.QuestionViewModel
@{
ViewData["Title"] = "Frage bearbeiten";
@@ -9,7 +9,7 @@
<hr />
<div class="row">
<div class="col-md-12">
<form asp-action="Edit">
<form asp-action="Edit" enctype="multipart/form-data">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<input type="hidden" asp-for="SectionId" />
@@ -19,32 +19,39 @@
<input asp-for="Text" class="form-control col-10" />
<span asp-validation-for="Text" class="text-danger offset-2"></span>
</div>
<div class="form-group row">
<div class="custom-file col-10 offset-2">
<input class="custom-file-input" asp-for="QuestionImage">
<label class="custom-file-label" asp-for="QuestionImage"></label>
</div>
<input type="hidden" asp-for="Image" />
</div>
<div class="form-group row">
<label asp-for="Choices" class="control-label col-2"></label>
<div class="col-10 row">
@for (int i = 0; i < 5; i++)
{
<div class="row col-12 mb-1 px-0 mx-0">
@if (Model != null && Model.Choices != null && Model.Choices.Count > i)
{
<input asp-for="@Model.Choices[i].Id" type="hidden" />
<input asp-for="@Model.Choices[i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input asp-for="@Model.Choices[i].IsTrue" class="form-check-input" value="true" />
<label asp-for="@Model.Choices[i].IsTrue" class="form-check-label">Richtig</label>
</div>
}
else
{
<input type="text" name="Choices[@i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input type="checkbox" name="Choices[@i].IsTrue" id="CheckBox-IsTrue-@i" class="form-check-input" value="true" />
<label for="CheckBox-IsTrue-@i" class="form-check-label">Richtig</label>
</div>
}
</div>
<div class="row col-12 mb-1 px-0 mx-0">
@if (Model != null && Model.Choices != null && Model.Choices.Count > i)
{
<input asp-for="@Model.Choices[i].Id" type="hidden" />
<input asp-for="@Model.Choices[i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input asp-for="@Model.Choices[i].IsTrue" class="form-check-input" value="true" />
<label asp-for="@Model.Choices[i].IsTrue" class="form-check-label">Richtig</label>
</div>
}
else
{
<input type="text" name="Choices[@i].Text" class="form-control col-10" />
<div class="form-check col-2 text-right">
<input type="checkbox" name="Choices[@i].IsTrue" id="CheckBox-IsTrue-@i" class="form-check-input" value="true" />
<label for="CheckBox-IsTrue-@i" class="form-check-label">Richtig</label>
</div>
}
</div>
}
<span asp-validation-for="Choices" class="text-danger" ></span>
<span asp-validation-for="Choices" class="text-danger"></span>
</div>
</div>

View File

@@ -41,10 +41,15 @@
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="~/js/bs-custom-file-input.min.js"></script>
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
$(document).ready(function () {
bsCustomFileInput.init()
})
</script>
@RenderSection("Scripts", required: false)
</body>

View File

@@ -0,0 +1,7 @@
/*!
* bsCustomFileInput v1.3.2 (https://github.com/Johann-S/bs-custom-file-input)
* Copyright 2018 - 2019 Johann-S <johann.servoire@gmail.com>
* Licensed under MIT (https://github.com/Johann-S/bs-custom-file-input/blob/master/LICENSE)
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).bsCustomFileInput=t()}(this,function(){"use strict";var d={CUSTOMFILE:'.custom-file input[type="file"]',CUSTOMFILELABEL:".custom-file-label",FORM:"form",INPUT:"input"},r=function(e){if(0<e.childNodes.length)for(var t=[].slice.call(e.childNodes),n=0;n<t.length;n++){var r=t[n];if(3!==r.nodeType)return r}return e},u=function(e){var t=e.bsCustomFileInput.defaultText,n=e.parentNode.querySelector(d.CUSTOMFILELABEL);n&&(r(n).innerHTML=t)},n=!!window.File,l=function(e){if(e.hasAttribute("multiple")&&n)return[].slice.call(e.files).map(function(e){return e.name}).join(", ");if(-1===e.value.indexOf("fakepath"))return e.value;var t=e.value.split("\\");return t[t.length-1]};function v(){var e=this.parentNode.querySelector(d.CUSTOMFILELABEL);if(e){var t=r(e),n=l(this);n.length?t.innerHTML=n:u(this)}}function p(){for(var e=[].slice.call(this.querySelectorAll(d.INPUT)).filter(function(e){return!!e.bsCustomFileInput}),t=0,n=e.length;t<n;t++)u(e[t])}var m="bsCustomFileInput",L="reset",h="change";return{init:function(e,t){void 0===e&&(e=d.CUSTOMFILE),void 0===t&&(t=d.FORM);for(var n,r,l,i=[].slice.call(document.querySelectorAll(e)),o=[].slice.call(document.querySelectorAll(t)),u=0,c=i.length;u<c;u++){var f=i[u];Object.defineProperty(f,m,{value:{defaultText:(n=f,r=void 0,void 0,r="",l=n.parentNode.querySelector(d.CUSTOMFILELABEL),l&&(r=l.innerHTML),r)},writable:!0}),v.call(f),f.addEventListener(h,v)}for(var a=0,s=o.length;a<s;a++)o[a].addEventListener(L,p),Object.defineProperty(o[a],m,{value:!0,writable:!0})},destroy:function(){for(var e=[].slice.call(document.querySelectorAll(d.FORM)).filter(function(e){return!!e.bsCustomFileInput}),t=[].slice.call(document.querySelectorAll(d.INPUT)).filter(function(e){return!!e.bsCustomFileInput}),n=0,r=t.length;n<r;n++){var l=t[n];u(l),l[m]=void 0,l.removeEventListener(h,v)}for(var i=0,o=e.length;i<o;i++)e[i].removeEventListener(L,p),e[i][m]=void 0}}});
//# sourceMappingURL=bs-custom-file-input.min.js.map