the deletion of questions in the edit mode

This commit is contained in:
Qais Yousuf 2024-03-24 00:53:00 +01:00
parent 3c5f0c7010
commit 57a7e46194
11 changed files with 751 additions and 361 deletions

View file

@ -14,6 +14,7 @@ namespace Data
{ {
} }
public DbSet<Page> Pages { get; set; } public DbSet<Page> Pages { get; set; }
public DbSet<Banner> Banners { get; set; } public DbSet<Banner> Banners { get; set; }
@ -31,7 +32,7 @@ namespace Data
public DbSet<Question> Questions { get; set; } public DbSet<Question> Questions { get; set; }
public DbSet<Answer> Answers { get; set; } public DbSet<Answer> Answers { get; set; }
public DbSet<QuestionTypeEntities> QuestionTypeEntities { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
@ -68,9 +69,6 @@ namespace Data
modelBuilder.Entity<Answer>() modelBuilder.Entity<Answer>()
.HasKey(a => a.Id); .HasKey(a => a.Id);
modelBuilder.Entity<QuestionTypeEntities>()
.HasKey(t => t.Id);
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
} }

View file

@ -28,12 +28,12 @@ namespace Services.Implemnetation
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
} }
public void Delete(int? id) //public void Delete(int? id)
{ //{
var questionnairId = GetQuesById(id); // var questionnairId = GetQuesById(id);
_context.Questionnaires.Remove(questionnairId); // _context.Questionnaires.Remove(questionnairId);
} //}
public List<Questionnaire> GetAllQuestions() public List<Questionnaire> GetAllQuestions()
{ {
@ -55,11 +55,21 @@ namespace Services.Implemnetation
return _context.Questionnaires.AsNoTracking().Include(x => x.Questions).ThenInclude(x => x.Answers).FirstOrDefault(x=>x.Id==id); return _context.Questionnaires.AsNoTracking().Include(x => x.Questions).ThenInclude(x => x.Answers).FirstOrDefault(x=>x.Id==id);
} }
public void Update(Questionnaire questionnaire) public async Task Update(Questionnaire questionnaire)
{ {
_context.Questionnaires.Update(questionnaire); _context.Questionnaires.Update(questionnaire);
await _context.SaveChangesAsync();
}
public async Task Delete(int? id)
{
var questionnairId = GetQuesById(id);
_context.Questionnaires.Remove(questionnairId);
await _context.SaveChangesAsync();
} }
} }
} }

View file

@ -15,8 +15,8 @@ namespace Services.Interaces
Questionnaire GetQuestionnaireWithQuestionAndAnswer(int? id); Questionnaire GetQuestionnaireWithQuestionAndAnswer(int? id);
void Add(Questionnaire questionnaire); void Add(Questionnaire questionnaire);
void Update(Questionnaire questionnaire); Task Update(Questionnaire questionnaire);
void Delete(int? id); Task Delete(int? id);
Task commitAsync(); Task commitAsync();
} }

View file

@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.IdentityModel.Tokens;
using Model; using Model;
using Services.Interaces; using Services.Interaces;
@ -17,7 +18,7 @@ namespace Web.Areas.Admin.Controllers
private readonly SurveyContext _context; private readonly SurveyContext _context;
private readonly IQuestionRepository _question; private readonly IQuestionRepository _question;
public QuestionnaireController(IQuestionnaireRepository Questionnaire,SurveyContext Context, IQuestionRepository Question) public QuestionnaireController(IQuestionnaireRepository Questionnaire, SurveyContext Context, IQuestionRepository Question)
{ {
_questionnaire = Questionnaire; _questionnaire = Questionnaire;
_context = Context; _context = Context;
@ -30,7 +31,7 @@ namespace Web.Areas.Admin.Controllers
var question = _question.GetQuestionsWithAnswers(); var question = _question.GetQuestionsWithAnswers();
List<QuestionnaireViewModel> viewmodel = new List<QuestionnaireViewModel>(); List<QuestionnaireViewModel> viewmodel = new List<QuestionnaireViewModel>();
@ -43,22 +44,22 @@ namespace Web.Areas.Admin.Controllers
Description = item.Description, Description = item.Description,
Title = item.Title, Title = item.Title,
Questions = item.Questions, Questions = item.Questions,
}); });
} }
return View(viewmodel); return View(viewmodel);
} }
[HttpGet] [HttpGet]
public IActionResult Create() public IActionResult Create()
{ {
var questionTypes = Enum.GetValues(typeof(QuestionType)).Cast<QuestionType>(); var questionTypes = Enum.GetValues(typeof(QuestionType)).Cast<QuestionType>();
ViewBag.QuestionTypes = new SelectList(questionTypes); ViewBag.QuestionTypes = new SelectList(questionTypes);
var questionnaire = new QuestionnaireViewModel var questionnaire = new QuestionnaireViewModel
@ -85,22 +86,22 @@ namespace Web.Areas.Admin.Controllers
var questionnaire = new Questionnaire var questionnaire = new Questionnaire
{ {
Id=viewmodel.Id, Id = viewmodel.Id,
Title=viewmodel.Title, Title = viewmodel.Title,
Description=viewmodel.Description, Description = viewmodel.Description,
}; };
var questions = viewmodel.Questions; var questions = viewmodel.Questions;
foreach (var questionViewModel in viewmodel.Questions) foreach (var questionViewModel in viewmodel.Questions)
{ {
var question = new Question var question = new Question
{ {
QuestionnaireId=questionViewModel.QuestionnaireId, QuestionnaireId = questionViewModel.QuestionnaireId,
Text = questionViewModel.Text, Text = questionViewModel.Text,
Type = questionViewModel.Type, Type = questionViewModel.Type,
Answers = new List<Answer>() Answers = new List<Answer>()
}; };
foreach (var answerViewModel in questionViewModel.Answers) foreach (var answerViewModel in questionViewModel.Answers)
@ -108,28 +109,28 @@ namespace Web.Areas.Admin.Controllers
var answer = new Answer var answer = new Answer
{ {
Text = answerViewModel.Text, Text = answerViewModel.Text,
QuestionId=answerViewModel.QuestionId, QuestionId = answerViewModel.QuestionId,
}; };
question.Answers.Add(answer); question.Answers.Add(answer);
} }
questionnaire.Questions.Add(question); questionnaire.Questions.Add(question);
} }
_questionnaire.Add(questionnaire); _questionnaire.Add(questionnaire);
await _questionnaire.commitAsync(); await _questionnaire.commitAsync();
TempData["Success"] = "Questionnaire created successfully"; TempData["Success"] = "Questionnaire created successfully";
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
return View(viewmodel); return View(viewmodel);
} }
@ -141,7 +142,7 @@ namespace Web.Areas.Admin.Controllers
.Cast<QuestionType>() .Cast<QuestionType>()
.Select(e => new SelectListItem { Value = e.ToString(), Text = e.ToString() }); .Select(e => new SelectListItem { Value = e.ToString(), Text = e.ToString() });
ViewBag.QuestionTypes = questionTypes; ViewBag.QuestionTypes = questionTypes;
var questionnaire = _questionnaire.GetQuestionnaireWithQuestionAndAnswer(id); var questionnaire = _questionnaire.GetQuestionnaireWithQuestionAndAnswer(id);
if (questionnaire == null) if (questionnaire == null)
@ -154,27 +155,27 @@ namespace Web.Areas.Admin.Controllers
Id = questionnaire.Id, Id = questionnaire.Id,
Title = questionnaire.Title, Title = questionnaire.Title,
Description = questionnaire.Description, Description = questionnaire.Description,
Questions = questionnaire.Questions Questions = questionnaire.Questions
.Select(q => new Question .Select(q => new Question
{ {
Id = q.Id, Id = q.Id,
Text = q.Text, Text = q.Text,
Type = q.Type, Type = q.Type,
QuestionnaireId=q.QuestionnaireId, QuestionnaireId = q.QuestionnaireId,
Answers = q.Answers.Select(a => new Answer Answers = q.Answers.Select(a => new Answer
{ {
Id = a.Id, Id = a.Id,
Text = a.Text, Text = a.Text,
Question=a.Question, Question = a.Question,
QuestionId=a.QuestionId QuestionId = a.QuestionId
}).ToList() }).ToList()
}).ToList() }).ToList()
}; };
@ -187,8 +188,8 @@ namespace Web.Areas.Admin.Controllers
{ {
var questionTypes = Enum.GetValues(typeof(QuestionType)) var questionTypes = Enum.GetValues(typeof(QuestionType))
.Cast<QuestionType>() .Cast<QuestionType>()
.Select(e => new SelectListItem { Value = e.ToString(), Text = e.ToString() }); .Select(e => new SelectListItem { Value = e.ToString(), Text = e.ToString() });
ViewBag.QuestionTypes = questionTypes; ViewBag.QuestionTypes = questionTypes;
if (ModelState.IsValid) if (ModelState.IsValid)
@ -205,6 +206,28 @@ namespace Web.Areas.Admin.Controllers
existingQuestionnaire.Title = viewModel.Title; existingQuestionnaire.Title = viewModel.Title;
existingQuestionnaire.Description = viewModel.Description; existingQuestionnaire.Description = viewModel.Description;
var existingQuestionIds = existingQuestionnaire.Questions.Select(q => q.Id).ToList();
// Iterate through existing questions and remove those not found in the view model
foreach (var existingQuestion in existingQuestionnaire.Questions.ToList())
{
// If the ID of the existing question is not found in the view model, remove it
if (!viewModel.Questions.Any(q => q.Id == existingQuestion.Id))
{
existingQuestionnaire.Questions.Remove(existingQuestion);
}
await _questionnaire.Update(existingQuestionnaire);
}
// Update the questionnaire with the modified list of questions
// Update or add new questions // Update or add new questions
foreach (var questionViewModel in viewModel.Questions) foreach (var questionViewModel in viewModel.Questions)
{ {
@ -213,140 +236,49 @@ namespace Web.Areas.Admin.Controllers
if (existingQuestion != null) if (existingQuestion != null)
{ {
var answersToRemove = new List<Answer>();
existingQuestion.Text = questionViewModel.Text; existingQuestion.Text = questionViewModel.Text;
existingQuestion.Type = questionViewModel.Type; existingQuestion.Type = questionViewModel.Type;
foreach (var answerViewModel in questionViewModel.Answers)
foreach (var answerViewModel in questionViewModel.Answers) {
// Check if the answer already exists
var existingAnswer = existingQuestion.Answers.FirstOrDefault(a => a.Id == answerViewModel.Id);
if (answerViewModel.Id == 0)
{ {
// Check if the answer already exists
var existingAnswer = existingQuestion.Answers.FirstOrDefault(a => a.Id == answerViewModel.Id);
if (answerViewModel.Id==0)
{
existingQuestion.Answers.Add(new Answer { Text = answerViewModel.Text }); existingQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
} }
else if (string.IsNullOrEmpty(answerViewModel.Text)) else if (answerViewModel.Text == null)
{ {
existingQuestion.Answers.Remove(existingAnswer);
existingQuestion.Answers.Remove(existingAnswer); await _questionnaire.Update(existingQuestionnaire);
_context.SaveChanges(); }
}
else if(existingAnswer !=null) else if (existingAnswer != null)
{ {
existingAnswer.Text = answerViewModel.Text; existingAnswer.Text = answerViewModel.Text;
} }
} }
} }
//else
//{
// var newQuestion = new Question
// {
// Text = questionViewModel.Text,
// Type = questionViewModel.Type,
// Answers = questionViewModel.Answers?.Select(a => new Answer { Text = a.Text }).ToList() ?? new List<Answer>()
// };
// existingQuestionnaire.Questions.Add(newQuestion);
//}
//if (existingQuestion != null)
//{
// existingQuestion.Text = questionViewModel.Text;
// existingQuestion.Type = questionViewModel.Type;
// //var answerId = existingQuestion.Answers.Select(x => x.Id).ToList();
// // Update or add new answers
// //foreach (var answerViewModel in questionViewModel.Answers)
// //{
// // var existingAnswer = existingQuestion.Answers.FirstOrDefault(a => a.Id == answerViewModel.Id);
// // if (existingAnswer != null)
// // {
// // existingAnswer.Text = answerViewModel.Text;
// // }
// // else
// // {
// // // Handle adding new answers if necessary
// // existingQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
// // }
// //}
// if (questionViewModel.Answers != null)
// {
// // Update or add new answers
// foreach (var answerViewModel in questionViewModel.Answers)
// {
// var existingAnswer = existingQuestion.Answers.FirstOrDefault(a => a.Id == answerViewModel.Id);
// if (existingAnswer != null)
// {
// // Update existing answer
// existingAnswer.Text = answerViewModel.Text;
// }
// else
// {
// foreach (var newanswers in questionViewModel.Answers)
// {
// existingQuestion.Answers.Add(new Answer { Text = newanswers.Text });
// }
// // Check if the answer with the same text already exists
// //var answerWithSameText = existingQuestion.Answers.FirstOrDefault(a => a.Text == answerViewModel.Text);
// //if (answerWithSameText == null)
// //{
// // // Add new answer only if it doesn't exist with the same text
// //}
// //else
// //{
// // // Optionally handle the case where an answer with the same text already exists
// // // You can choose to do nothing, show a message, or take any other action
// //}
// }
// }
// }
//}
//else
//{
// // Add new question with its answers
// var newQuestion = new Question
// {
// Text = questionViewModel.Text,
// Type = questionViewModel.Type,
// Answers = questionViewModel.Answers.Select(a => new Answer { Text = a.Text }).ToList()
// };
// existingQuestionnaire.Questions.Add(newQuestion);
//}
} }
// Remove any questions that are not in the view model
//var questionIdsInViewModel = viewModel.Questions.Select(q => q.Id); await _questionnaire.Update(existingQuestionnaire);
//var questionsToRemove = existingQuestionnaire.Questions.Where(q => !questionIdsInViewModel.Contains(q.Id)).ToList();
//foreach (var questionToRemove in questionsToRemove)
//{
// existingQuestionnaire.Questions.Remove(questionToRemove);
//}
// Save changes to the database
_questionnaire.Update(existingQuestionnaire);
await _questionnaire.commitAsync();
TempData["Success"] = "Questionnaire updated successfully"; TempData["Success"] = "Questionnaire updated successfully";
return RedirectToAction("Index"); return RedirectToAction(nameof(Index));
} }
// If ModelState is not valid, re-display the form with validation errors // If ModelState is not valid, re-display the form with validation errors
@ -391,13 +323,35 @@ namespace Web.Areas.Admin.Controllers
[HttpPost] [HttpPost]
[ActionName("Delete")] [ActionName("Delete")]
public IActionResult DeleteConfirm(int id) public async Task<IActionResult> DeleteConfirm(int id)
{ {
_questionnaire.Delete(id);
_questionnaire.commitAsync();
return Json(new { success = true, message = "Item deleted successfully" }); try
{
var deletedQuestionnaire = _questionnaire.Delete(id);
if (deletedQuestionnaire == null)
{
return NotFound(); // Or handle not found case appropriately
}
// If deletion is successful, you can redirect to a success page or return a success message
return Json(new { success = true, message = "Item deleted successfully" });
}
catch (Exception ex)
{
// Log the exception or handle it appropriately
return StatusCode(500, "An error occurred while processing your request.");
}
//return StatusCode(500, "An error occurred while processing your request");
} }
[HttpGet] [HttpGet]

View file

@ -57,9 +57,10 @@
} }
</div> </div>
</div> </div>
<button type="button" id="add-question-btn" class="btn btn-md btn-success shadow"><i class="bi bi-plus-square"></i> Create New Question</button> |
</div> </div>
<div class="mt-3 card-footer"> <div class="mt-3 card-footer">
<button type="button" id="add-question-btn" class="btn btn-md btn-success shadow"><i class="bi bi-plus-square"></i> Create New Question</button> |
<button type="submit" class="btn btn-primary shadow">Submit</button> <button type="submit" class="btn btn-primary shadow">Submit</button>
| <a asp-action="Index" class="btn btn-info shadow">Back to list</a> | <a asp-action="Index" class="btn btn-info shadow">Back to list</a>
</div> </div>
@ -83,8 +84,106 @@
} }
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script> <script>
$(document).ready(function () {
var questionIndex = @Model.Questions?.Count;
$("#add-question-btn").click(function () {
var newQuestionHtml = `
<div class="question-group" data-question-index="${questionIndex}">
<label>Question ${questionIndex + 1}</label>
<textarea name="Questions[${questionIndex}].Text" class="form-control"></textarea>
<br>
<label class=h5>Select question type</label>
<select name="Questions[${questionIndex}].Type" class="form-control question-type-${questionIndex}">`;
var questionTypes = @Html.Raw(Json.Serialize(Enum.GetNames(typeof(QuestionType))));
for (var i = 0; i < questionTypes.length; i++) {
newQuestionHtml += `<option value="${questionTypes[i]}">${questionTypes[i]}</option>`;
}
newQuestionHtml += `</select>`;
// Add answers input fields
newQuestionHtml += `<div class="container-ms mx-5 py-2 px-5 ">`;
newQuestionHtml += `<div class="answers-container" data-question-index="${questionIndex}"><br>`;
newQuestionHtml += `<label class="h3">Create Answers:</label>`;
newQuestionHtml += `<div class="answer-group" data-answer-index="0"><hr class="border border-primary border-1 opacity-35">`;
newQuestionHtml += `<label>Answer 1</label>`;
newQuestionHtml += `<input type="text" name="Questions[${questionIndex}].Answers[0].Text" class="form-control" placeholder="new answer"/><br>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-success add-answer mt-2"><i class="bi bi-plus-lg"></i> Add Answer</button>`;
newQuestionHtml += `<hr class="border m-2">`
newQuestionHtml += `</div> `;
newQuestionHtml += `</div>`;
newQuestionHtml += `</div> `;
// Add Remove Question button
newQuestionHtml += `<button type="button" class="btn btn-sm btn-danger m-4 remove-question"><i class="bi bi-trash3-fill"></i> Remove Question </button>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-primary save-question">Save Question</button>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-secondary edit-question" style="display: none;">Edit Question</button>`;
newQuestionHtml += `<hr class="border border-primary border-4 opacity-75 mb-5">`
newQuestionHtml += `</div>`;
$("#questions-container .form-group").append(newQuestionHtml);
questionIndex++;
});
$("#questions-container").on("click", ".add-answer", function () {
var questionIndex = $(this).closest('.answers-container').data('question-index');
var answerIndex = $(this).closest('.answers-container').find('.answer-group').length;
var answerGroupHtml = `
<div class="answer-group">
<br>
<label class="control-label">Answer ${answerIndex + 1}</label>
<input type="text" class="form-control" name="Questions[${questionIndex}].Answers[${answerIndex}].Text" placeholder="new answer"/>
<button type="button" class="btn btn-danger btn-sm mt-1 remove-answer"><i class="bi bi-trash3-fill"></i></button>
<br>
</div>`;
$(this).before(answerGroupHtml);
$(this).prev('.answer-group').find('.remove-answer').show();
});
// Remove answer dynamically
$("#questions-container").on("click", ".remove-answer", function () {
$(this).closest('.answer-group').remove();
});
// Remove question dynamically
$(document).on("click", ".remove-question", function () {
$(this).closest('.question-group').remove();
});
// Save question
$("#questions-container").on("click", ".save-question", function () {
var questionGroup = $(this).closest('.question-group');
questionGroup.find('.edit-question').show();
questionGroup.find('.remove-question').hide();
questionGroup.find('.save-question').hide();
questionGroup.find('.question-type').hide(); // Hide question type
questionGroup.find('.answers-container').slideUp();
questionGroup.addClass('collapsed');
});
// Edit question
$("#questions-container").on("click", ".edit-question", function () {
var questionGroup = $(this).closest('.question-group');
questionGroup.find('.save-question').show();
questionGroup.find('.remove-question').show();
questionGroup.find('.edit-question').hide();
questionGroup.find('.question-type').show(); // Show question type
questionGroup.find('.answers-container').slideDown();
questionGroup.removeClass('collapsed');
});
});
</script>
@* <script>
$(document).ready(function () { $(document).ready(function () {
var questionIndex = @Model.Questions?.Count; var questionIndex = @Model.Questions?.Count;
@ -183,7 +282,7 @@
}); });
}); });
</script> </script>
*@
} }

View file

@ -4,7 +4,7 @@
ViewData["Title"] = "Edit"; ViewData["Title"] = "Edit";
} }
<style> @* <style>
.question-separator { .question-separator {
display: flex; display: flex;
align-items: center; align-items: center;
@ -23,8 +23,103 @@
margin: 0; margin: 0;
} }
</style> </style> *@
<div class="container mt-4"> <div class="container mt-4">
<div class="card justify-content-center p-4 shadow rounded">
<div class="card-body">
<h5 class="card-title">Edit Survey</h5>
<div class="row">
<form asp-action="Edit">
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="card shadow rounded" id="customCard">
<div id="questionsContainer">
@for (int i = 0; i < Model.Questions.Count; i++)
{
<div class="question">
<div class="question-separator">
<!-- Container for the first half of the line -->
<div class="line-container">
<hr class="border border-primary border-4 opacity-75 line-start">
</div>
<!-- Container for the next question text -->
<div class="next-question-container mt-2">
<p><span class="badge badge-primary">NEXT QUESTION</span></p>
</div>
<!-- Container for the second half of the line -->
<div class="line-container">
<hr class="border border-primary border-4 opacity-75 line-end">
</div>
</div>
<input type="hidden" asp-for="Questions[i].Id" />
<div class="question-title">
@Model.Questions[i].Text
<button type="button" class="btn btn-primary m-4 btn-sm editQuestion"><i class="bi bi-pencil-square"></i> Edit question</button>|
</div>
<div class="question-details" style="display: none;">
<div class="form-group">
<label asp-for="Questions[i].Text" class="control-label"></label>
<input asp-for="Questions[i].Text" class="form-control" />
<span asp-validation-for="Questions[i].Text" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Questions[i].Type" class="control-label"></label>
<select asp-for="Questions[i].Type" asp-items="@ViewBag.QuestionTypes" class="form-control"></select>
<span asp-validation-for="Questions[i].Type" class="text-danger"></span>
</div>
<div class="answers">
@for (int j = 0; j < Model.Questions[i].Answers.Count; j++)
{
<div class="answer">
<input type="hidden" asp-for="Questions[i].Answers[j].Id" />
<div class="form-group">
<label asp-for="Questions[i].Answers[j].Text" class="control-label"></label>
<input asp-for="Questions[i].Answers[j].Text" class="form-control" />
<span asp-validation-for="Questions[i].Answers[j].Text" class="text-danger"></span>
<button type="button" class="btn btn-danger btn-sm mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div>
</div>
}
</div>
<button type="button" class="btn btn-primary btn-sm mb-2 addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button>
</div>
<button type="button" class="btn btn-success btn-ms ml-5 mt-2 saveQuestion" style="display: none;"><i class="bi bi-floppy"></i> Save question</button>
<!-- Remove Question Button -->
<div class="d-block">
@Model.Questions[i].Text
<button type="button" class="btn btn-danger btn-sm removeQuestion"><i class="bi bi-trash"></i> Remove question</button>
</div>
</div>
}
</div>
</div>
<div class="m-4">
<button type="submit" class="btn btn-primary">Update questionnaire</button>
| <a asp-action="Index" class="btn btn-info">Back to list</a>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Modal -->
@* <div class="container mt-4">
<div class="card justify-content-center p-4 shadow rounded"> <div class="card justify-content-center p-4 shadow rounded">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Edit Survey</h5> <h5 class="card-title">Edit Survey</h5>
@ -68,6 +163,7 @@
<div class="question-title"> <div class="question-title">
@Model.Questions[i].Text @Model.Questions[i].Text
<button type="button" class="btn btn-primary m-4 btn-sm editQuestion"><i class="bi bi-pencil-square"></i> Edit question</button> <button type="button" class="btn btn-primary m-4 btn-sm editQuestion"><i class="bi bi-pencil-square"></i> Edit question</button>
</div> </div>
<div class="question-details" style="display: none;"> <div class="question-details" style="display: none;">
<div class="form-group"> <div class="form-group">
@ -96,7 +192,8 @@
</div> </div>
<button type="button" class="btn btn-primary btn-sm mb-2 addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button> <button type="button" class="btn btn-primary btn-sm mb-2 addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button>
</div> </div>
<button type="button" class="btn btn-success btn-md ml-5 mt-2 saveQuestion" style="display: none;"><i class="bi bi-floppy"></i> Save question</button> <button type="button" class="btn btn-success btn-ms ml-5 mt-2 saveQuestion" style="display: none;"><i class="bi bi-floppy"></i> Save question</button>
</div> </div>
} }
</div> </div>
@ -110,79 +207,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
@* <div class="container mt-4">
<div class="card justify-content-center p-4 shadow rounded">
<div class="card-body">
<h5 class="card-title">Edit Survey</h5>
<div class="row">
<form asp-action="Edit">
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="card shadow rounded p-4 m-4">
<div id="questionsContainer" class="m-4">
@for (int i = 0; i < Model.Questions.Count; i++)
{
<div class="question">
<input type="hidden" asp-for="Questions[i].Id" />
<div class="form-group">
<label asp-for="Questions[i].Text" class="control-label"></label>
<input asp-for="Questions[i].Text" class="form-control" />
<span asp-validation-for="Questions[i].Text" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Questions[i].Type" class="control-label"></label>
<select asp-for="Questions[i].Type" asp-items="@ViewBag.QuestionTypes" class="form-control"></select>
<span asp-validation-for="Questions[i].Type" class="text-danger"></span>
</div>
<div class="answers m-4">
@for (int j = 0; j < Model.Questions[i].Answers.Count; j++)
{
<div class="answer">
<input type="hidden" asp-for="Questions[i].Answers[j].Id" />
<div class="form-group">
<label asp-for="Questions[i].Answers[j].Text" class="control-label"></label>
<input asp-for="Questions[i].Answers[j].Text" class="form-control" />
<span asp-validation-for="Questions[i].Answers[j].Text" class="text-danger"></span>
<button type="button" class="btn btn-danger mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div>
</div>
}
</div>
<button type="button" class="btn btn-primary btn-sm addAnswer"><i class="bi bi-floppy"></i> Add new Answer</button>
</div>
}
</div>
</div>
<button type="submit" class="btn btn-primary">Update</button>
| <a asp-action="Index" class="btn btn-info">Back to list</a>
</form>
</div>
</div>
</div>
</div> *@ </div> *@
@ -193,6 +217,9 @@
@section Scripts { @section Scripts {
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.4/ckeditor.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.4/ckeditor.js"></script>
<script> <script>
@ -264,100 +291,19 @@
questionContainer.find('.saveQuestion').hide(); questionContainer.find('.saveQuestion').hide();
}); });
$(document).on('click', '.removeQuestion', function () {
$(this).closest('.question').remove();
});
}); });
// $(document).ready(function () {
// // Function to add a new answer
// $(document).on('click', '.addAnswer', function () {
// var questionContainer = $(this).closest('.question');
// var newQuestionIndex = questionContainer.index();
// // Correctly find the length of answers for the specific question
// var newAnswerIndex = questionContainer.find('.answers .form-group').length;
// var answerHtml = `
// <div class="form-group">
// <label class="control-label">Answer</label>
// <input type="text" name="Questions[${newQuestionIndex}].Answers[${newAnswerIndex}].Text" class="form-control" />
// <button type="button" class="btn btn-danger removeAnswer">Remove Answer</button>
// </div>`;
// // Append the new answer to the specific question
// questionContainer.find('.answers').append(answerHtml);
// });
// // Function to remove an answer (including dynamically added answers)
// $(document).on('click', '.removeAnswer', function () {
// $(this).closest('.form-group').remove();
// });
// // Function to toggle question edit mode
// $(document).on('click', '.editQuestion', function () {
// var questionContainer = $(this).closest('.question');
// questionContainer.find('.question-title').hide();
// questionContainer.find('.question-details').show();
// questionContainer.find('.editQuestion').hide();
// questionContainer.find('.saveQuestion').show();
// });
// // Function to save question details
// $(document).on('click', '.saveQuestion', function () {
// var questionContainer = $(this).closest('.question');
// var titleTextElement = questionContainer.find('.question-title');
// // Apply styles for success (green text color)
// titleTextElement.css('color', '#28a745'); // Set the success text color
// // Add checkmark icon before the text
// titleTextElement.prepend('<span class="check-icon">&#x2714; </span>');
// // Show the original question title
// titleTextElement.show();
// // Hide the question details
// questionContainer.find('.question-details').hide();
// // Show the edit button and hide the save button
// questionContainer.find('.editQuestion').show();
// questionContainer.find('.saveQuestion').hide();
// });
// });
</script> </script>
@* // $(document).on('click', '.removeQuestion', function () {
@* <script> // $(this).closest('.question').remove();
$(document).ready(function () { }); *@
// Function to add a new answer
$(document).on('click', '.addAnswer', function () {
var questionContainer = $(this).closest('.question');
var newQuestionIndex = questionContainer.index();
// Correctly find the length of answers for the specific question
var newAnswerIndex = questionContainer.find('.answers .form-group').length;
var answerHtml = `
<div class="form-group">
<label class="control-label">Answer</label>
<input type="text" name="Questions[${newQuestionIndex}].Answers[${newAnswerIndex}].Text" class="form-control" />
<button type="button" class="btn btn-danger mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div>`;
// Append the new answer to the specific question
questionContainer.find('.answers').append(answerHtml);
});
// Function to remove an answer (including dynamically added answers)
$(document).on('click', '.removeAnswer', function () {
$(this).closest('.form-group').remove();
});
});
</script> *@
} }

View file

@ -0,0 +1,355 @@
// <auto-generated />
using System;
using Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Web.Migrations
{
[DbContext(typeof(SurveyContext))]
[Migration("20240323171512_QuestionTypeEntityRemoved")]
partial class QuestionTypeEntityRemoved
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Model.Address", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("CVR")
.HasColumnType("nvarchar(max)");
b.Property<string>("City")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Country")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Mobile")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PostalCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("State")
.HasColumnType("nvarchar(max)");
b.Property<string>("Street")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Addresss");
});
modelBuilder.Entity("Model.Answer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("QuestionId")
.HasColumnType("int");
b.Property<string>("Text")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("QuestionId");
b.ToTable("Answers");
});
modelBuilder.Entity("Model.Banner", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LinkUrl")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Banners");
});
modelBuilder.Entity("Model.Footer", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("CreatedBy")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ImageUlr")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("LastUpdated")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Owner")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Sitecopyright")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("UpdatedBy")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Footers");
});
modelBuilder.Entity("Model.FooterSocialMedia", b =>
{
b.Property<int>("FooterId")
.HasColumnType("int");
b.Property<int>("SocialId")
.HasColumnType("int");
b.HasKey("FooterId", "SocialId");
b.HasIndex("SocialId");
b.ToTable("FooterSocialMedias");
});
modelBuilder.Entity("Model.Page", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("BannerId")
.HasColumnType("int");
b.Property<string>("Content")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Slug")
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("BannerId");
b.ToTable("Pages");
});
modelBuilder.Entity("Model.Question", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("QuestionnaireId")
.HasColumnType("int");
b.Property<string>("Text")
.HasColumnType("nvarchar(max)");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("QuestionnaireId");
b.ToTable("Questions");
});
modelBuilder.Entity("Model.Questionnaire", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Title")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Questionnaires");
});
modelBuilder.Entity("Model.SocialMedia", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Url")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("SocialMedia");
});
modelBuilder.Entity("Model.Answer", b =>
{
b.HasOne("Model.Question", "Question")
.WithMany("Answers")
.HasForeignKey("QuestionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Question");
});
modelBuilder.Entity("Model.FooterSocialMedia", b =>
{
b.HasOne("Model.Footer", "Footer")
.WithMany("FooterSocialMedias")
.HasForeignKey("FooterId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Model.SocialMedia", "SocialMedia")
.WithMany("FooterSocialMedias")
.HasForeignKey("SocialId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Footer");
b.Navigation("SocialMedia");
});
modelBuilder.Entity("Model.Page", b =>
{
b.HasOne("Model.Banner", "banner")
.WithMany()
.HasForeignKey("BannerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("banner");
});
modelBuilder.Entity("Model.Question", b =>
{
b.HasOne("Model.Questionnaire", "Questionnaire")
.WithMany("Questions")
.HasForeignKey("QuestionnaireId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Questionnaire");
});
modelBuilder.Entity("Model.Footer", b =>
{
b.Navigation("FooterSocialMedias");
});
modelBuilder.Entity("Model.Question", b =>
{
b.Navigation("Answers");
});
modelBuilder.Entity("Model.Questionnaire", b =>
{
b.Navigation("Questions");
});
modelBuilder.Entity("Model.SocialMedia", b =>
{
b.Navigation("FooterSocialMedias");
});
#pragma warning restore 612, 618
}
}
}

View file

@ -0,0 +1,34 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Web.Migrations
{
/// <inheritdoc />
public partial class QuestionTypeEntityRemoved : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "QuestionTypeEntities");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "QuestionTypeEntities",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Type = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_QuestionTypeEntities", x => x.Id);
});
}
}
}

View file

@ -235,22 +235,6 @@ namespace Web.Migrations
b.ToTable("Questions"); b.ToTable("Questions");
}); });
modelBuilder.Entity("Model.QuestionTypeEntities", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("QuestionTypeEntities");
});
modelBuilder.Entity("Model.Questionnaire", b => modelBuilder.Entity("Model.Questionnaire", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")

View file

@ -1,5 +1,6 @@
using Data; using Data;
using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Services.Implemnetation; using Services.Implemnetation;
using Services.Interaces; using Services.Interaces;
@ -11,7 +12,15 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
builder.Services.ConfigureSQLConnection(builder.Configuration); var config = builder.Configuration;
builder.Services.AddDbContext<SurveyContext>(options =>
{
options.UseSqlServer(config.GetConnectionString("SurveyVista"), cfg => cfg.MigrationsAssembly("Web"));
});
//builder.Services.ConfigureSQLConnection(builder.Configuration);
builder.Services.ConfigurePageServices(); builder.Services.ConfigurePageServices();
builder.Services.ConfigureBannerServices(); builder.Services.ConfigureBannerServices();
@ -20,7 +29,7 @@ builder.Services.ConfigureSocialMedia();
builder.Services.ConfigureFooter(); builder.Services.ConfigureFooter();
builder.Services.ConfigureQuestionnarie(); builder.Services.ConfigureQuestionnarie();
builder.Services.ConfigureQuestion(); builder.Services.ConfigureQuestion();
//builder.Services.AddScoped<SurveyContext>(); builder.Services.AddScoped<SurveyContext>();
var app = builder.Build(); var app = builder.Build();

View file

@ -6,7 +6,8 @@
} }
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"ConnectionStrings": { "ConnectionStrings": {
"SurveyVista": "data source=SEO-PC; initial catalog=SurveyVista; integrated security=true; TrustServerCertificate=true;" "SurveyVista": "data source=SEO-PC; initial catalog=SurveyVista;integrated security=True; TrustServerCertificate=True;"
} }
} }