Refactored DTOs to use AutoMapper instead of manual mapping and made some additional improvements and fixes.
Added : GetAllSurveys&DeleteUser.
This commit is contained in:
2025-02-07 06:40:57 -08:00
parent 272ef7194e
commit 3aabe1a367
214 changed files with 10555 additions and 262 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -24,9 +24,9 @@ namespace survey_beta.Controllers
} }
[HttpGet("export/{surveyId}")] [HttpGet("export/{surveyId}")]
public IActionResult ExportSurveyData(string surveyId) public async Task<IActionResult> ExportSurveyData(string surveyId)
{ {
return _analyticsServices.ExportSurveyDataToCsv(surveyId); return await _analyticsServices.ExportResponsesToCsv(surveyId);
} }
} }
} }

View File

@@ -1,39 +1,43 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using survey_beta.DTOs.Response; using survey_beta.DTOs.Response;
using survey_beta.Models; using survey_beta.Models;
using System;
using System.Threading.Tasks;
namespace survey_beta.Controllers namespace survey_beta.Controllers
{ {
[Route("api/[controller]")] [Route("api/[controller]")]
[ApiController] [ApiController]
public class ResponsesController : ControllerBase public class ResponseController : ControllerBase
{ {
private readonly ResponsesService _responsesService; private readonly ResponsesService _responsesService;
public ResponsesController(ResponsesService responsesService) public ResponseController(ResponsesService responsesService)
{ {
_responsesService = responsesService; _responsesService = responsesService;
} }
[HttpPost("add")] [HttpPost("add")]
public IActionResult AddResponse([FromBody] ResponseDto request) public async Task<IActionResult> CreateResponse([FromBody] ResponseDto request)
{ {
try try
{ {
_responsesService.AddResponse(request); await _responsesService.AddResponseAsync(request);
return Ok("Response added successfully."); return Ok(new { message = "Response added successfully." });
} }
catch (Exception ex) catch (Exception ex)
{ {
return BadRequest(new { message = ex.Message }); return BadRequest(new { error = ex.Message });
} }
} }
[HttpGet("survey/{surveyId}")] [HttpGet("survey/{surveyId}")]
public IActionResult GetSurveyResponses(string surveyId) public async Task<IActionResult> GetSurveyResponses(string surveyId)
{ {
var responses = _responsesService.GetSurveyResponses(surveyId); var responses = await _responsesService.GetSurveyResponsesAsync(surveyId);
if (responses == null || responses.Count == 0) return NotFound("No responses found for this survey."); if (responses == null || responses.Count == 0)
{
return NotFound(new { message = "No responses found for this survey." });
}
return Ok(responses); return Ok(responses);
} }
} }

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNet.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using survey_beta.DTOs.Create; using survey_beta.DTOs.Create;
@@ -14,15 +15,22 @@ using System.Threading.Tasks;
public class SurveyController : ControllerBase public class SurveyController : ControllerBase
{ {
private readonly SurveyService _surveyService; private readonly SurveyService _surveyService;
private readonly UserManager<User> _userManager; private readonly Microsoft.AspNetCore.Identity.UserManager<User> _userManager;
public SurveyController(SurveyService surveyService, UserManager<User> userManager) public SurveyController(SurveyService surveyService, Microsoft.AspNetCore.Identity.UserManager<User> userManager)
{ {
_surveyService = surveyService; _surveyService = surveyService;
_userManager = userManager; _userManager = userManager;
} }
[HttpGet("{id}")] [HttpGet("GetAll")]
public async Task<IActionResult> GetAllSurveys([FromQuery] string id = null)
{
var surveys = await _surveyService.GetAllSurveysAsync(id);
return Ok(surveys);
}
[HttpGet("GetSurveyById{id}")]
public async Task<IActionResult> GetById(string id) public async Task<IActionResult> GetById(string id)
{ {
var userId = _userManager.GetUserId(User); var userId = _userManager.GetUserId(User);
@@ -50,23 +58,17 @@ public class SurveyController : ControllerBase
return Ok(result); return Ok(result);
} }
[HttpPost("Create-Survey")]
// [Authorize] // [Authorize]
[HttpPost] public async Task<IActionResult> CreateSurvey([FromBody] CreateSurveyDto request)
public async Task<ActionResult<Survey>> CreateSurvey([FromBody] CreateSurveyDto request)
{ {
try var userId = _userManager.GetUserId(User);
{ var survey = await _surveyService.CreateSurveyAsync(request, userId);
var survey = await _surveyService.CreateSurveyAsync(request); return Ok(survey);
return CreatedAtAction(nameof(GetById), new { id = survey.Id }, survey);
}
catch (Exception ex)
{
return BadRequest(new { message = ex.Message });
}
} }
//[Authorize] //[Authorize]
[HttpPut] [HttpPut("EditSurvey{id}")]
public async Task<IActionResult> UpdateSurvey([FromBody] UpdateSurveyDto request) public async Task<IActionResult> UpdateSurvey([FromBody] UpdateSurveyDto request)
{ {
var success = await _surveyService.UpdateSurveyAsync(request); var success = await _surveyService.UpdateSurveyAsync(request);
@@ -75,7 +77,7 @@ public class SurveyController : ControllerBase
} }
//[Authorize] //[Authorize]
[HttpPatch("publish/{id}")] [HttpPatch("publish-Survey/{id}")]
public async Task<IActionResult> PublishSurvey(string id) public async Task<IActionResult> PublishSurvey(string id)
{ {
var success = await _surveyService.PublishSurveyAsync(id); var success = await _surveyService.PublishSurveyAsync(id);
@@ -84,7 +86,7 @@ public class SurveyController : ControllerBase
} }
//[Authorize] //[Authorize]
[HttpPatch("unpublish/{id}")] [HttpPatch("unpublish-Survey/{id}")]
public async Task<IActionResult> UnpublishSurvey(string id) public async Task<IActionResult> UnpublishSurvey(string id)
{ {
var success = await _surveyService.UnpublishSurveyAsync(id); var success = await _surveyService.UnpublishSurveyAsync(id);
@@ -93,7 +95,7 @@ public class SurveyController : ControllerBase
} }
//[Authorize] //[Authorize]
[HttpDelete("{id}")] [HttpDelete("Delete-Survey{id}")]
public async Task<IActionResult> DeleteSurvey(string id) public async Task<IActionResult> DeleteSurvey(string id)
{ {
var success = await _surveyService.DeleteSurveyAsync(id); var success = await _surveyService.DeleteSurveyAsync(id);

View File

@@ -6,7 +6,7 @@ namespace survey_beta.DTOs.Create
public class CreateQuestionDto public class CreateQuestionDto
{ {
public string Content { get; set; } public string Content { get; set; }
public string SurveyId { get; set; } //public string SurveyId { get; set; }
public List<CreateChoiceDto> Choices { get; set; } public List<CreateChoiceDto> Choices { get; set; }
} }

View File

@@ -9,7 +9,7 @@ namespace survey_beta.DTOs.Create
public string Description { get; set; } public string Description { get; set; }
public string Category { get; set; } public string Category { get; set; }
public DateTime ExpirationDate { get; set; } public DateTime ExpirationDate { get; set; }
public bool IsPublished { get; set; }
public List<CreateQuestionDto> Questions { get; set; } public List<CreateQuestionDto> Questions { get; set; }
} }
} }

View File

@@ -3,8 +3,7 @@
public class AnswerDto public class AnswerDto
{ {
public string Id { get; set; } = Guid.NewGuid().ToString(); public string Id { get; set; } = Guid.NewGuid().ToString();
public string Question { get; set; } public string QuestionId { get; set; }
public string AnswerText { get; set; }
public string ResponseId { get; set; } public string ResponseId { get; set; }
} }
} }

View File

@@ -8,5 +8,6 @@ namespace survey_beta.DTOs.Default
public string Letter { get; set; } public string Letter { get; set; }
public string Content { get; set; } public string Content { get; set; }
public string QuestionId { get; set; } public string QuestionId { get; set; }
public bool IsCorrect { get; set; }
} }
} }

View File

@@ -5,6 +5,8 @@
public string Id { get; set; } = Guid.NewGuid().ToString(); public string Id { get; set; } = Guid.NewGuid().ToString();
public string Content { get; set; } public string Content { get; set; }
public string SurveyId { get; set; } public string SurveyId { get; set; }
public List<ChoiceDto> Choices { get; set; } public string QuestionType { get; set; }
public string QuestionId { get; set; }
public IEnumerable<ChoiceDto> Choices { get; set; }
} }
} }

View File

@@ -1,12 +1,11 @@
namespace survey_beta.DTOs.Default using survey_beta.DTOs.Default;
{
public class ResponseDto public class ResponseDto
{ {
public string Id { get; set; } = Guid.NewGuid().ToString(); public string Id { get; set; }
public string IpAddress { get; set; }
public string SurveyId { get; set; } public string SurveyId { get; set; }
public string Answer { get; set; } public string Response { get; set; }
public DateTime CreatedAt { get; set; } public string ResponseContent { get; set; }
public string? IpAddress { get; set; }
} public ICollection<AnswerDto> Answers { get; set; }
} }

View File

@@ -2,11 +2,12 @@
{ {
public class SurveyDto public class SurveyDto
{ {
public string Id { get; set; } = Guid.NewGuid().ToString(); public string Id { get; set; }
public string Title { get; set; } public string Title { get; set; }
public string Description { get; set; } public string Description { get; set; }
public string Category { get; set; } public string Category { get; set; }
public DateTime ExpirationDate { get; set; } public DateTime ExpirationDate { get; set; }
public DateTime CreatedAt { get; set; }
public bool IsPublished { get; set; } public bool IsPublished { get; set; }
public string AuthorId { get; set; } public string AuthorId { get; set; }
public List<QuestionDto> Questions { get; set; } public List<QuestionDto> Questions { get; set; }

View File

@@ -1,10 +0,0 @@
namespace survey_beta.DTOs.Response
{
public class ResponseDto
{
public string Id { get; set; }
public string IpAddress { get; set; }
public string SurveyId { get; set; }
public string Response { get; set; }
}
}

View File

@@ -1,10 +1,11 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using survey_beta.Models; using survey_beta.Models;
namespace survey_beta.DataBaseContext namespace survey_beta.DataBaseContext
{ {
public class AppDbContext : IdentityDbContext<User> public class AppDbContext : Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext<User>
{ {
public DbSet<Survey> Surveys { get; set; } public DbSet<Survey> Surveys { get; set; }
public DbSet<Question> Questions { get; set; } public DbSet<Question> Questions { get; set; }
@@ -31,10 +32,10 @@ namespace survey_beta.DataBaseContext
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Question>() modelBuilder.Entity<Question>()
.HasOne(q => q.Survey) .HasIndex(q => q.SurveyId);
.WithMany(s => s.Questions) modelBuilder.Entity<Choice>()
.HasForeignKey(q => q.SurveyId) .HasIndex(c => c.QuestionId);
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Choice>() modelBuilder.Entity<Choice>()
.HasOne(c => c.Question) .HasOne(c => c.Question)
@@ -42,12 +43,6 @@ namespace survey_beta.DataBaseContext
.HasForeignKey(c => c.QuestionId) .HasForeignKey(c => c.QuestionId)
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Answer>()
.HasOne(a => a.Response)
.WithMany(r => r.Answers)
.HasForeignKey(a => a.ResponseId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Answer>() modelBuilder.Entity<Answer>()
.HasOne(a => a.Question) .HasOne(a => a.Question)
.WithMany() .WithMany()

View File

@@ -1,4 +1,5 @@
using survey_beta.DTOs.Create; #if false
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default; using survey_beta.DTOs.Default;
using survey_beta.Models; using survey_beta.Models;
@@ -28,3 +29,4 @@ namespace survey_beta.Mappers
} }
} }
} }
#endif

View File

@@ -0,0 +1,27 @@
using AutoMapper;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.DTOs.Update;
using survey_beta.Models;
namespace survey_beta.Mappers.Profiles
{
public class AnalyticsProfile : Profile
{
public AnalyticsProfile()
{
CreateMap<Response, ResponseDto>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.SurveyId, opt => opt.MapFrom(src => src.SurveyId))
.ForMember(dest => dest.Answers, opt => opt.MapFrom(src => src.Answers));
CreateMap<Answer, AnswerDto>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.QuestionId, opt => opt.MapFrom(src => src.QuestionId));
CreateMap<SurveyAnalytics, SurveyStats>()
.ForMember(dest => dest.SurveyId, opt => opt.MapFrom(src => src.SurveyId))
.ForMember(dest => dest.TotalResponses, opt => opt.MapFrom(src => src.TotalResponses));
}
}
}

View File

@@ -0,0 +1,15 @@
using AutoMapper;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.Models;
namespace survey_beta.Mappers.Profiles
{
public class AnswerProfile : Profile
{
public AnswerProfile()
{
CreateMap<Answer, AnswerDto>();
}
}
}

View File

@@ -0,0 +1,15 @@
using AutoMapper;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.Models;
namespace survey_beta.Mappers.Profiles
{
public class ChoiceProfile : Profile
{
public ChoiceProfile()
{
CreateMap<Choice, ChoiceDto>();
}
}
}

View File

@@ -0,0 +1,22 @@
using AutoMapper;
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.DTOs.Update;
using survey_beta.Models;
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<CreateSurveyDto, Survey>().ForMember(dest => dest.Id, opt => opt.Ignore());
CreateMap<CreateQuestionDto, Question>().ForMember(dest => dest.Id, opt => opt.Ignore());
CreateMap<CreateChoiceDto, Choice>().ForMember(dest => dest.Id, opt => opt.Ignore());
CreateMap<Survey, SurveyDto>();
CreateMap<Question, QuestionDto>();
CreateMap<Choice, ChoiceDto>();
CreateMap<UpdateSurveyDto, Survey>();
}
}

View File

@@ -0,0 +1,15 @@
using AutoMapper;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.Models;
namespace survey_beta.Mappers.Profiles
{
public class QuestionProfile : Profile
{
public QuestionProfile()
{
CreateMap<Question, QuestionDto>();
}
}
}

View File

@@ -0,0 +1,23 @@
namespace survey_beta.Mappers.Profiles
{
using AutoMapper;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.Models;
public class ResponseProfile : Profile
{
public ResponseProfile()
{
CreateMap<ResponseDto, Response>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.SurveyId, opt => opt.MapFrom(src => src.SurveyId))
.ForMember(dest => dest.CreatedAt, opt => opt.MapFrom(src => DateTime.UtcNow))
.ForMember(dest => dest.Answers, opt => opt.MapFrom(src => src.Answers));
CreateMap<AnswerDto, Answer>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.ResponseId, opt => opt.MapFrom(src => src.ResponseId))
.ForMember(dest => dest.QuestionId, opt => opt.MapFrom(src => src.QuestionId));
}
}
}

View File

@@ -0,0 +1,17 @@
using AutoMapper;
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.Models;
namespace survey_beta.Mappers.Profiles
{
public class SurveyProfile : Profile
{
public SurveyProfile()
{
CreateMap<Survey, SurveyDto>();
CreateMap<CreateSurveyDto, Survey>();
}
}
}

View File

@@ -0,0 +1,16 @@
using AutoMapper;
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default;
using survey_beta.Models;
namespace survey_beta.Mappers.Profiles
{
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<User, UserDto>();
CreateMap<CreateUserDto, User>();
}
}
}

View File

@@ -1,4 +1,6 @@
using survey_beta.DTOs.Create; #if false
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default; using survey_beta.DTOs.Default;
using survey_beta.Models; using survey_beta.Models;
@@ -22,8 +24,9 @@ namespace survey_beta.Mappers
{ {
Id = Guid.NewGuid().ToString(), Id = Guid.NewGuid().ToString(),
Content = dto.Content, Content = dto.Content,
SurveyId = dto.SurveyId // SurveyId = dto.SurveyId
}; };
} }
} }
} }
#endif

View File

@@ -1,4 +1,5 @@
using survey_beta.DTOs.Create; #if false
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default; using survey_beta.DTOs.Default;
using survey_beta.Models; using survey_beta.Models;
@@ -27,3 +28,4 @@ namespace survey_beta.Mappers
} }
} }
} }
#endif

View File

@@ -1,4 +1,5 @@
using survey_beta.DTOs.Create; #if false
using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default; using survey_beta.DTOs.Default;
using survey_beta.Models; using survey_beta.Models;
@@ -34,3 +35,4 @@ namespace survey_beta.Mappers
} }
} }
} }
#endif

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Identity; #if false
using Microsoft.AspNetCore.Identity;
using survey_beta.DTOs.Create; using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default; using survey_beta.DTOs.Default;
using survey_beta.Models; using survey_beta.Models;
@@ -33,3 +34,4 @@ namespace survey_beta.Mappers
} }
} }
} }
#endif

View File

@@ -0,0 +1,485 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using survey_beta.DataBaseContext;
#nullable disable
namespace survey_beta.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250204184529_answer")]
partial class answer
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("survey_beta.Models.Answer", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ChoiceId")
.HasColumnType("text");
b.Property<string>("QuestionId")
.HasColumnType("text");
b.Property<string>("ResponseId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ChoiceId");
b.HasIndex("QuestionId");
b.HasIndex("ResponseId");
b.ToTable("Answers");
});
modelBuilder.Entity("survey_beta.Models.Choice", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Letter")
.HasColumnType("text");
b.Property<string>("QuestionId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("QuestionId");
b.ToTable("Choices");
});
modelBuilder.Entity("survey_beta.Models.Question", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("SurveyId")
.HasColumnType("text");
b.Property<string>("Text")
.HasColumnType("text");
b.Property<string>("Type")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("SurveyId");
b.ToTable("Questions");
});
modelBuilder.Entity("survey_beta.Models.Response", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("IpAddress")
.HasColumnType("text");
b.Property<string>("SurveyId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("SurveyId");
b.ToTable("Responses");
});
modelBuilder.Entity("survey_beta.Models.Survey", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("AuthorId")
.HasColumnType("text");
b.Property<string>("Category")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<DateTime?>("ExpirationDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsPublished")
.HasColumnType("boolean");
b.Property<string>("Title")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Surveys");
});
modelBuilder.Entity("survey_beta.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("Fullname")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("survey_beta.Models.Answer", b =>
{
b.HasOne("survey_beta.Models.Choice", "Choice")
.WithMany()
.HasForeignKey("ChoiceId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("survey_beta.Models.Question", "Question")
.WithMany()
.HasForeignKey("QuestionId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("survey_beta.Models.Response", "Response")
.WithMany("Answers")
.HasForeignKey("ResponseId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Choice");
b.Navigation("Question");
b.Navigation("Response");
});
modelBuilder.Entity("survey_beta.Models.Choice", b =>
{
b.HasOne("survey_beta.Models.Question", "Question")
.WithMany("Choices")
.HasForeignKey("QuestionId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Question");
});
modelBuilder.Entity("survey_beta.Models.Question", b =>
{
b.HasOne("survey_beta.Models.Survey", "Survey")
.WithMany("Questions")
.HasForeignKey("SurveyId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Survey");
});
modelBuilder.Entity("survey_beta.Models.Response", b =>
{
b.HasOne("survey_beta.Models.Survey", "Survey")
.WithMany()
.HasForeignKey("SurveyId");
b.Navigation("Survey");
});
modelBuilder.Entity("survey_beta.Models.Survey", b =>
{
b.HasOne("survey_beta.Models.User", "Author")
.WithMany("Surveys")
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Author");
});
modelBuilder.Entity("survey_beta.Models.Question", b =>
{
b.Navigation("Choices");
});
modelBuilder.Entity("survey_beta.Models.Response", b =>
{
b.Navigation("Answers");
});
modelBuilder.Entity("survey_beta.Models.Survey", b =>
{
b.Navigation("Questions");
});
modelBuilder.Entity("survey_beta.Models.User", b =>
{
b.Navigation("Surveys");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,123 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace survey_beta.Migrations
{
/// <inheritdoc />
public partial class answer : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses");
migrationBuilder.AlterColumn<string>(
name: "SurveyId",
table: "Responses",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddColumn<string>(
name: "IpAddress",
table: "Responses",
type: "text",
nullable: true);
migrationBuilder.AlterColumn<string>(
name: "ResponseId",
table: "Answers",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "QuestionId",
table: "Answers",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "ChoiceId",
table: "Answers",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses",
column: "SurveyId",
principalTable: "Surveys",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses");
migrationBuilder.DropColumn(
name: "IpAddress",
table: "Responses");
migrationBuilder.AlterColumn<string>(
name: "SurveyId",
table: "Responses",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ResponseId",
table: "Answers",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "QuestionId",
table: "Answers",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ChoiceId",
table: "Answers",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses",
column: "SurveyId",
principalTable: "Surveys",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -0,0 +1,487 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using survey_beta.DataBaseContext;
#nullable disable
namespace survey_beta.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20250205124722_Choice")]
partial class Choice
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("ClaimType")
.HasColumnType("text");
b.Property<string>("ClaimValue")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("ProviderKey")
.HasColumnType("text");
b.Property<string>("ProviderDisplayName")
.HasColumnType("text");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("text");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("RoleId")
.HasColumnType("text");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("text");
b.Property<string>("LoginProvider")
.HasColumnType("text");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Value")
.HasColumnType("text");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("survey_beta.Models.Answer", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("ChoiceId")
.HasColumnType("text");
b.Property<string>("QuestionId")
.HasColumnType("text");
b.Property<string>("ResponseId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("ChoiceId");
b.HasIndex("QuestionId");
b.HasIndex("ResponseId");
b.ToTable("Answers");
});
modelBuilder.Entity("survey_beta.Models.Choice", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("Letter")
.HasColumnType("text");
b.Property<string>("QuestionId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("QuestionId");
b.ToTable("Choices");
});
modelBuilder.Entity("survey_beta.Models.Question", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<string>("SurveyId")
.HasColumnType("text");
b.Property<string>("Text")
.HasColumnType("text");
b.Property<string>("Type")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("SurveyId");
b.ToTable("Questions");
});
modelBuilder.Entity("survey_beta.Models.Response", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("IpAddress")
.HasColumnType("text");
b.Property<string>("SurveyId")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("SurveyId");
b.ToTable("Responses");
});
modelBuilder.Entity("survey_beta.Models.Survey", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<string>("AuthorId")
.HasColumnType("text");
b.Property<string>("Category")
.HasColumnType("text");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<DateTime?>("ExpirationDate")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsPublished")
.HasColumnType("boolean");
b.Property<string>("Title")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("AuthorId");
b.ToTable("Surveys");
});
modelBuilder.Entity("survey_beta.Models.User", b =>
{
b.Property<string>("Id")
.HasColumnType("text");
b.Property<int>("AccessFailedCount")
.HasColumnType("integer");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("text");
b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<bool>("EmailConfirmed")
.HasColumnType("boolean");
b.Property<string>("Fullname")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("LockoutEnabled")
.HasColumnType("boolean");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("timestamp with time zone");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("PasswordHash")
.HasColumnType("text");
b.Property<string>("PhoneNumber")
.HasColumnType("text");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("boolean");
b.Property<string>("SecurityStamp")
.HasColumnType("text");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("boolean");
b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("survey_beta.Models.User", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("survey_beta.Models.Answer", b =>
{
b.HasOne("survey_beta.Models.Choice", "Choice")
.WithMany()
.HasForeignKey("ChoiceId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("survey_beta.Models.Question", "Question")
.WithMany()
.HasForeignKey("QuestionId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("survey_beta.Models.Response", "Response")
.WithMany("Answers")
.HasForeignKey("ResponseId");
b.Navigation("Choice");
b.Navigation("Question");
b.Navigation("Response");
});
modelBuilder.Entity("survey_beta.Models.Choice", b =>
{
b.HasOne("survey_beta.Models.Question", "Question")
.WithMany("Choices")
.HasForeignKey("QuestionId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Question");
});
modelBuilder.Entity("survey_beta.Models.Question", b =>
{
b.HasOne("survey_beta.Models.Survey", "Survey")
.WithMany("Questions")
.HasForeignKey("SurveyId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Survey");
});
modelBuilder.Entity("survey_beta.Models.Response", b =>
{
b.HasOne("survey_beta.Models.Survey", "Survey")
.WithMany()
.HasForeignKey("SurveyId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Survey");
});
modelBuilder.Entity("survey_beta.Models.Survey", b =>
{
b.HasOne("survey_beta.Models.User", "Author")
.WithMany("Surveys")
.HasForeignKey("AuthorId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("Author");
});
modelBuilder.Entity("survey_beta.Models.Question", b =>
{
b.Navigation("Choices");
});
modelBuilder.Entity("survey_beta.Models.Response", b =>
{
b.Navigation("Answers");
});
modelBuilder.Entity("survey_beta.Models.Survey", b =>
{
b.Navigation("Questions");
});
modelBuilder.Entity("survey_beta.Models.User", b =>
{
b.Navigation("Surveys");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,82 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace survey_beta.Migrations
{
/// <inheritdoc />
public partial class Choice : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Answers_Responses_ResponseId",
table: "Answers");
migrationBuilder.DropForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses");
migrationBuilder.AlterColumn<string>(
name: "SurveyId",
table: "Responses",
type: "text",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "FK_Answers_Responses_ResponseId",
table: "Answers",
column: "ResponseId",
principalTable: "Responses",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses",
column: "SurveyId",
principalTable: "Surveys",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Answers_Responses_ResponseId",
table: "Answers");
migrationBuilder.DropForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses");
migrationBuilder.AlterColumn<string>(
name: "SurveyId",
table: "Responses",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddForeignKey(
name: "FK_Answers_Responses_ResponseId",
table: "Answers",
column: "ResponseId",
principalTable: "Responses",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Responses_Surveys_SurveyId",
table: "Responses",
column: "SurveyId",
principalTable: "Surveys",
principalColumn: "Id");
}
}
}

View File

@@ -160,15 +160,12 @@ namespace survey_beta.Migrations
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("ChoiceId") b.Property<string>("ChoiceId")
.IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("QuestionId") b.Property<string>("QuestionId")
.IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("ResponseId") b.Property<string>("ResponseId")
.IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.HasKey("Id"); b.HasKey("Id");
@@ -235,6 +232,9 @@ namespace survey_beta.Migrations
b.Property<DateTime>("CreatedAt") b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("IpAddress")
.HasColumnType("text");
b.Property<string>("SurveyId") b.Property<string>("SurveyId")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
@@ -400,20 +400,16 @@ namespace survey_beta.Migrations
b.HasOne("survey_beta.Models.Choice", "Choice") b.HasOne("survey_beta.Models.Choice", "Choice")
.WithMany() .WithMany()
.HasForeignKey("ChoiceId") .HasForeignKey("ChoiceId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade);
.IsRequired();
b.HasOne("survey_beta.Models.Question", "Question") b.HasOne("survey_beta.Models.Question", "Question")
.WithMany() .WithMany()
.HasForeignKey("QuestionId") .HasForeignKey("QuestionId")
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade);
.IsRequired();
b.HasOne("survey_beta.Models.Response", "Response") b.HasOne("survey_beta.Models.Response", "Response")
.WithMany("Answers") .WithMany("Answers")
.HasForeignKey("ResponseId") .HasForeignKey("ResponseId");
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Choice"); b.Navigation("Choice");

View File

@@ -6,8 +6,8 @@ namespace survey_beta.Models
public class Response public class Response
{ {
public string Id { get; set; } = Guid.NewGuid().ToString(); public string Id { get; set; } = Guid.NewGuid().ToString();
//public string IpAddress { get; set; } public string? IpAddress { get; set; }
public string? SurveyId { get; set; } public string SurveyId { get; set; }
public Survey? Survey { get; set; } public Survey? Survey { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public ICollection<Answer> Answers { get; set; } = new List<Answer>(); public ICollection<Answer> Answers { get; set; } = new List<Answer>();

View File

@@ -3,13 +3,14 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using survey_beta.DataBaseContext; using survey_beta.DataBaseContext;
using survey_beta.Mappers.Profiles;
using survey_beta.Models; using survey_beta.Models;
using System.Text; using System.Text;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options => builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// Add services to the container.
builder.Services.AddControllers(); builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
@@ -65,7 +66,14 @@ builder.Services.AddScoped<UsersServices>();
builder.Services.AddScoped<SurveyService>(); builder.Services.AddScoped<SurveyService>();
builder.Services.AddScoped<ResponsesService>(); builder.Services.AddScoped<ResponsesService>();
builder.Services.AddScoped<AnalyticsServices>(); builder.Services.AddScoped<AnalyticsServices>();
builder.Services.AddAutoMapper(typeof(MappingProfile));
builder.Services.AddAutoMapper(typeof(UserProfile));
builder.Services.AddAutoMapper(typeof(ResponseProfile));
builder.Services.AddAutoMapper(typeof(AnalyticsProfile));
builder.Services.AddAutoMapper(typeof(AnswerProfile));
builder.Services.AddAutoMapper(typeof(ChoiceProfile));
builder.Services.AddAutoMapper(typeof(QuestionProfile));
builder.Services.AddAutoMapper(typeof(SurveyProfile));
var app = builder.Build(); var app = builder.Build();
// HTTP request pipeline // HTTP request pipeline

View File

@@ -1,21 +1,27 @@
using Microsoft.AspNetCore.Http.HttpResults; using AutoMapper;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using survey_beta.DataBaseContext; using survey_beta.DataBaseContext;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Update; using survey_beta.DTOs.Update;
using survey_beta.Models; using survey_beta.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
public class AnalyticsServices public class AnalyticsServices
{ {
private readonly AppDbContext _context; private readonly AppDbContext _context;
public AnalyticsServices(AppDbContext context) private readonly IMapper _mapper;
public AnalyticsServices(AppDbContext context, IMapper mapper)
{ {
_context = context; _context = context;
_mapper = mapper;
} }
public void UpdateAnalytics(string surveyId) public void UpdateAnalytics(string surveyId)
{ {
var responses = _context.Responses var responses = _context.Responses
@@ -28,6 +34,7 @@ public class AnalyticsServices
SaveAnalytics(surveyId, analyticsData); SaveAnalytics(surveyId, analyticsData);
} }
private SurveyStats CalculateAnalytics(List<Response> responses) private SurveyStats CalculateAnalytics(List<Response> responses)
{ {
var answerFrequency = new Dictionary<string, int>(); var answerFrequency = new Dictionary<string, int>();
@@ -38,24 +45,21 @@ public class AnalyticsServices
foreach (var answer in response.Answers) foreach (var answer in response.Answers)
{ {
var choiceText = answer.Choice?.Letter; var choiceText = answer.Choice?.Letter;
if (choiceText != null) if (!string.IsNullOrEmpty(choiceText))
{ {
if (answerFrequency.ContainsKey(choiceText)) if (answerFrequency.ContainsKey(choiceText))
{
answerFrequency[choiceText]++; answerFrequency[choiceText]++;
}
else else
{
answerFrequency[choiceText] = 1; answerFrequency[choiceText] = 1;
} }
}
if (questionFrequency.ContainsKey(answer.Question?.Text)) var questionText = answer.Question?.Text;
if (!string.IsNullOrEmpty(questionText))
{ {
questionFrequency[answer.Question.Text]++; if (questionFrequency.ContainsKey(questionText))
} questionFrequency[questionText]++;
else else
{ questionFrequency[questionText] = 1;
questionFrequency[answer.Question.Text] = 1;
} }
} }
} }
@@ -68,18 +72,17 @@ public class AnalyticsServices
QuestionFrequency = questionFrequency QuestionFrequency = questionFrequency
}; };
} }
private void SaveAnalytics(string surveyId, SurveyStats analyticsData) private void SaveAnalytics(string surveyId, SurveyStats analyticsData)
{ {
var analytics = new SurveyAnalytics var analytics = _mapper.Map<SurveyAnalytics>(analyticsData);
{ analytics.SurveyId = surveyId;
SurveyId = surveyId, analytics.CreatedAt = DateTime.UtcNow;
TotalResponses = analyticsData.TotalResponses,
CreatedAt = DateTime.UtcNow,
};
_context.Add(analytics); _context.Add(analytics);
_context.SaveChanges(); _context.SaveChanges();
} }
public SurveyStats GetAggregatedSurveyResponses(string surveyId) public SurveyStats GetAggregatedSurveyResponses(string surveyId)
{ {
var responses = _context.Responses var responses = _context.Responses
@@ -90,37 +93,34 @@ public class AnalyticsServices
return CalculateAnalytics(responses); return CalculateAnalytics(responses);
} }
public IActionResult ExportSurveyDataToCsv(string surveyId)
public async Task<IActionResult> ExportResponsesToCsv(string surveyId)
{ {
var responses = _context.Responses var responses = await _context.Responses
.Where(r => r.SurveyId == surveyId) .Where(r => r.SurveyId == surveyId)
.Include(r => r.Answers) .Include(r => r.Answers)
.ThenInclude(a => a.Question)
.Include(r => r.Answers)
.ThenInclude(a => a.Choice) .ThenInclude(a => a.Choice)
.ToList(); .ToListAsync();
if (responses == null || responses.Count == 0)
{
return new ObjectResult("No responses found for this survey.")
{
StatusCode = 404
};
}
var csvData = new StringWriter(); var csvLines = new List<string>
var csvHeader = "ResponseId,Question,ChoiceText"; {
csvData.WriteLine(csvHeader); "ResponseId,Question,ChoiceText"
};
foreach (var response in responses) foreach (var response in responses)
{ {
foreach (var answer in response.Answers) foreach (var answer in response.Answers)
{ {
var choiceText = answer.Choice?.Letter ?? "No Choice"; var questionText = answer.Question.Content;
var csvLine = $"{response.Id},{answer.Question?.Text},{choiceText}"; csvLines.Add($"{response.Id},{questionText}");
csvData.WriteLine(csvLine);
} }
} }
var fileName = $"{surveyId}_responses.csv"; var fileName = "Survey_Responses.csv";
var fileBytes = System.Text.Encoding.UTF8.GetBytes(csvData.ToString()); var fileBytes = Encoding.UTF8.GetBytes(string.Join(Environment.NewLine, csvLines));
return new FileContentResult(fileBytes, "text/csv") return new FileContentResult(fileBytes, "text/csv")
{ {
FileDownloadName = fileName FileDownloadName = fileName

View File

@@ -1,44 +1,51 @@
using Microsoft.EntityFrameworkCore; using AutoMapper;
using Microsoft.EntityFrameworkCore;
using survey_beta.DataBaseContext; using survey_beta.DataBaseContext;
using survey_beta.DTOs.Response; using survey_beta.DTOs.Response;
using survey_beta.Models; using survey_beta.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class ResponsesService public class ResponsesService
{ {
private readonly AppDbContext _context; private readonly AppDbContext _context;
private readonly AnalyticsServices _analyticsService; private readonly IMapper _mapper;
public ResponsesService(AppDbContext context, AnalyticsServices analyticsService) public ResponsesService(AppDbContext context, IMapper mapper)
{ {
_context = context; _context = context;
_analyticsService = analyticsService; _mapper = mapper;
} }
public async Task AddResponseAsync(ResponseDto responseDto)
public void AddResponse(ResponseDto request)
{ {
var response = new Response var response = new Response
{ {
SurveyId = request.SurveyId, Id = responseDto.Id,
Id = request.Id, SurveyId = responseDto.SurveyId,
IpAddress = responseDto.IpAddress,
CreatedAt = DateTime.UtcNow, CreatedAt = DateTime.UtcNow,
// CreatedAt = DateTime.UtcNow,
//IpAddress= request.IpAddress
//Answers = request.Answers.Select(a => new Answer
//{
// }).ToList()
}; };
_context.Responses.Add(response); foreach (var answer in responseDto.Answers)
_context.SaveChanges(); {
var answerEntity = new Answer
{
QuestionId = answer.QuestionId,
ResponseId = response.Id
};
response.Answers.Add(answerEntity);
} }
public List<Response> GetSurveyResponses(string surveyId) await _context.Responses.AddAsync(response);
await _context.SaveChangesAsync();
}
public async Task<List<Response>> GetSurveyResponsesAsync(string surveyId)
{ {
return _context.Responses return await _context.Responses
.Where(r => r.SurveyId == surveyId) .Where(r => r.SurveyId == surveyId)
.Include(r => r.Answers) .Include(r => r.Answers)
.ToList(); .ToListAsync();
} }
} }

View File

@@ -1,72 +1,71 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using survey_beta.DataBaseContext; using survey_beta.DataBaseContext;
using survey_beta.DTOs.Create; using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default;
using survey_beta.DTOs.Response;
using survey_beta.DTOs.Update; using survey_beta.DTOs.Update;
using survey_beta.DTOs.Response;
using survey_beta.Models; using survey_beta.Models;
using System.Security.Claims; using AutoMapper;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;
using survey_beta.DTOs.Default;
public class SurveyService public class SurveyService
{ {
private readonly AppDbContext _context; private readonly AppDbContext _context;
private readonly IMapper _mapper;
private readonly ResponsesService _responsesService; private readonly ResponsesService _responsesService;
public SurveyService(AppDbContext context, ResponsesService responsesService) public SurveyService(AppDbContext context, IMapper mapper, ResponsesService responsesService)
{ {
_context = context; _context = context;
_mapper = mapper;
_responsesService = responsesService; _responsesService = responsesService;
} }
public async Task<List<SurveyDto>> GetAllSurveysAsync(string id = null)
{
IQueryable<Survey> query = _context.Surveys.Include(s => s.Questions);
public async Task<Survey> GetSurveyByIdAsync(string id) if (!string.IsNullOrEmpty(id))
{ {
return await _context.Surveys query = query.Where(s => s.Id == id);
}
var surveys = await query.ToListAsync();
return _mapper.Map<List<SurveyDto>>(surveys);
}
public async Task<SurveyDto> GetSurveyByIdAsync(string id)
{
var survey = await _context.Surveys.AsNoTracking()
.Include(s => s.Questions) .Include(s => s.Questions)
.ThenInclude(q => q.Choices)
.FirstOrDefaultAsync(s => s.Id == id); .FirstOrDefaultAsync(s => s.Id == id);
return survey == null ? null : _mapper.Map<SurveyDto>(survey);
} }
public async Task<List<Survey>> GetUserSurveysAsync(string userId) public async Task<SurveyDto> CreateSurveyAsync(CreateSurveyDto request, string userId)
{ {
return await _context.Surveys.Where(s => s.AuthorId == userId).ToListAsync(); var survey = _mapper.Map<Survey>(request);
} survey.Id = Guid.NewGuid().ToString();
public async Task<Survey> CreateSurveyAsync(CreateSurveyDto request) survey.AuthorId = userId;
{
var survey = new Survey
{
Id = Guid.NewGuid().ToString(),
Title = request.Title,
Description = request.Description,
Category = request.Category,
ExpirationDate = request.ExpirationDate,
AuthorId = null,
Questions = request.Questions.Select(q => new Question
{
Id = Guid.NewGuid().ToString(),
Text = q.Content,
}).ToList()
};
_context.Surveys.Add(survey); _context.Surveys.Add(survey);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return survey; return _mapper.Map<SurveyDto>(survey);
} }
public async Task<bool> UpdateSurveyAsync(UpdateSurveyDto request) public async Task<bool> UpdateSurveyAsync(UpdateSurveyDto request)
{ {
var survey = await _context.Surveys.FindAsync(request.Id); var survey = await _context.Surveys.FindAsync(request.Id);
if (survey == null) return false; if (survey == null) return false;
survey.Title = request.Title; _mapper.Map(request, survey);
survey.Description = request.Description;
survey.Category = request.Category;
survey.ExpirationDate = request.ExpirationDate;
survey.IsPublished = request.IsPublished;
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return true; return true;
} }
public async Task<bool> PublishSurveyAsync(string id) public async Task<bool> PublishSurveyAsync(string id)
{ {
var survey = await _context.Surveys.FindAsync(id); var survey = await _context.Surveys.FindAsync(id);
@@ -76,6 +75,7 @@ public class SurveyService
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return true; return true;
} }
public async Task<bool> UnpublishSurveyAsync(string id) public async Task<bool> UnpublishSurveyAsync(string id)
{ {
var survey = await _context.Surveys.FindAsync(id); var survey = await _context.Surveys.FindAsync(id);
@@ -85,27 +85,18 @@ public class SurveyService
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return true; return true;
} }
public async Task<bool> DeleteSurveyAsync(string id) public async Task<bool> DeleteSurveyAsync(string id)
{ {
var survey = await _context.Surveys.FindAsync(id); var survey = await _context.Surveys.AsNoTracking()
.Include(s => s.Questions)
.ThenInclude(q => q.Choices)
.FirstOrDefaultAsync(s => s.Id == id);
if (survey == null) return false; if (survey == null) return false;
_context.Surveys.Remove(survey); _context.Surveys.Remove(survey);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return true; return true;
} }
public async Task<bool> SubmitSurveyResponseAsync(string surveyId, survey_beta.DTOs.Response.ResponseDto responseDto)
{
var survey = await _context.Surveys
.Include(s => s.Questions)
.FirstOrDefaultAsync(s => s.Id == surveyId);
if (survey == null)
{
return false;
}
_responsesService.AddResponse(responseDto);
return true;
}
} }

View File

@@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using survey_beta.DTOs.Create; using survey_beta.DTOs.Create;
using survey_beta.DTOs.Default; using survey_beta.DTOs.Default;
@@ -7,19 +6,23 @@ using survey_beta.Models;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims; using System.Security.Claims;
using System.Text; using System.Text;
using AutoMapper;
public class UsersServices public class UsersServices
{ {
private readonly UserManager<User> _userManager; private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager; private readonly SignInManager<User> _signInManager;
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
private readonly IMapper _mapper;
public UsersServices(UserManager<User> userManager, SignInManager<User> signInManager, IConfiguration configuration) public UsersServices(UserManager<User> userManager, SignInManager<User> signInManager, IConfiguration configuration, IMapper mapper)
{ {
_userManager = userManager; _userManager = userManager;
_signInManager = signInManager; _signInManager = signInManager;
_configuration = configuration; _configuration = configuration;
_mapper = mapper;
} }
public async Task<UserDto> CreateUserAsync(CreateUserDto createUserDto) public async Task<UserDto> CreateUserAsync(CreateUserDto createUserDto)
{ {
var existingUser = await _userManager.FindByEmailAsync(createUserDto.Email); var existingUser = await _userManager.FindByEmailAsync(createUserDto.Email);
@@ -28,12 +31,7 @@ public class UsersServices
throw new Exception("User with this email already exists."); throw new Exception("User with this email already exists.");
} }
var user = new User var user = _mapper.Map<User>(createUserDto);
{
UserName = createUserDto.Username,
Email = createUserDto.Email,
Fullname = createUserDto.Fullname
};
var result = await _userManager.CreateAsync(user, createUserDto.Password); var result = await _userManager.CreateAsync(user, createUserDto.Password);
if (!result.Succeeded) if (!result.Succeeded)
@@ -41,14 +39,10 @@ public class UsersServices
throw new Exception("Failed to create user: " + string.Join(", ", result.Errors.Select(e => e.Description))); throw new Exception("Failed to create user: " + string.Join(", ", result.Errors.Select(e => e.Description)));
} }
return new UserDto var userDto = _mapper.Map<UserDto>(user);
{ userDto.Token = GenerateJwtToken(user);
Id = user.Id,
Email = user.Email, return userDto;
Username = user.UserName,
Fullname = user.Fullname,
Token = GenerateJwtToken(user)
};
} }
public async Task<UserDto> SignInAsync(LoginDto loginDto) public async Task<UserDto> SignInAsync(LoginDto loginDto)
{ {
@@ -64,14 +58,10 @@ public class UsersServices
throw new Exception("Invalid login attempt."); throw new Exception("Invalid login attempt.");
} }
return new UserDto var userDto = _mapper.Map<UserDto>(user);
{ userDto.Token = GenerateJwtToken(user);
Id = user.Id,
Email = user.Email, return userDto;
Username = user.UserName,
Fullname = user.Fullname,
Token = GenerateJwtToken(user)
};
} }
public async Task<UserDto> GetUserByIdAsync(string userId) public async Task<UserDto> GetUserByIdAsync(string userId)
{ {
@@ -81,13 +71,7 @@ public class UsersServices
throw new Exception("User not found."); throw new Exception("User not found.");
} }
return new UserDto return _mapper.Map<UserDto>(user);
{
Id = user.Id,
Email = user.Email,
Username = user.UserName,
Fullname = user.Fullname
};
} }
public async Task<UserDto> GetUserByUsernameAsync(string username) public async Task<UserDto> GetUserByUsernameAsync(string username)
{ {
@@ -97,13 +81,7 @@ public class UsersServices
throw new Exception("User not found."); throw new Exception("User not found.");
} }
return new UserDto return _mapper.Map<UserDto>(user);
{
Id = user.Id,
Email = user.Email,
Username = user.UserName,
Fullname = user.Fullname
};
} }
private string GenerateJwtToken(User user) private string GenerateJwtToken(User user)
{ {
@@ -127,26 +105,18 @@ public class UsersServices
return new JwtSecurityTokenHandler().WriteToken(token); return new JwtSecurityTokenHandler().WriteToken(token);
} }
public async Task<List<UserDto>> GetAllUsersAsync() public async Task<List<UserDto>> GetAllUsersAsync()
{ {
var users = _userManager.Users.ToList(); var users = _userManager.Users.ToList();
return _mapper.Map<List<UserDto>>(users);
var userDtos = users.Select(user => new UserDto
{
Id = user.Id,
Email = user.Email,
Username = user.UserName,
Fullname = user.Fullname
}).ToList();
return userDtos;
} }
public async Task<bool> DeleteUsersAsync(string userid) public async Task<bool> DeleteUsersAsync(string userid)
{ {
var user = await _userManager.FindByIdAsync(userid); var user = await _userManager.FindByIdAsync(userid);
if (user == null) return false; if (user == null) return false;
var result = await _userManager.DeleteAsync(user); var result = await _userManager.DeleteAsync(user);
if (!result.Succeeded) return false; return result.Succeeded;
return true;
} }
} }

View File

@@ -6,6 +6,6 @@
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=SurveyBeta;Username=postgres;Password=102030" "DefaultConnection": "Host=localhost;Database=SurveyBeta;Username=postgres;Password=MAJEDali645"
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More