Bilder zur Frage können hochgeladen werden;
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -339,4 +339,5 @@ ASALocalRun/
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
**/appsettings.json
|
||||
**/appsettings.json
|
||||
**/uploads/
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
16
MultipleChoiceTrainer/Models/QuestionViewModel.cs
Normal file
16
MultipleChoiceTrainer/Models/QuestionViewModel.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
7
MultipleChoiceTrainer/wwwroot/js/bs-custom-file-input.min.js
vendored
Normal file
7
MultipleChoiceTrainer/wwwroot/js/bs-custom-file-input.min.js
vendored
Normal 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
|
||||
Reference in New Issue
Block a user