diff --git a/server/StudySharp.API/Controllers/TheoryBlockController.cs b/server/StudySharp.API/Controllers/TheoryBlockController.cs new file mode 100644 index 0000000..8b84815 --- /dev/null +++ b/server/StudySharp.API/Controllers/TheoryBlockController.cs @@ -0,0 +1,91 @@ +using System.Threading.Tasks; +using AutoMapper; +using MediatR; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using StudySharp.API.Requests.TheoryBlocks; +using StudySharp.API.Responses.TheoryBlocks; +using StudySharp.ApplicationServices.Commands; +using StudySharp.ApplicationServices.Queries; +using StudySharp.Domain.General; + +namespace StudySharp.API.Controllers +{ + [Authorize] + [ApiController] + [Route("api/courses")] + + public class TheoryBlockController : ControllerBase + { + private readonly IMediator _mediator; + private readonly IMapper _mapper; + + public TheoryBlockController(IMediator mediator, IMapper mapper) + { + _mapper = mapper; + _mediator = mediator; + } + + [HttpPost("{courseId:int}/theory-blocks")] + public async Task Add([FromRoute] int courseId, [FromBody] AddTheoryBlockRequest addTheoryBlockRequest) + { + var addTheoryBlockCommand = _mapper.Map(addTheoryBlockRequest); + addTheoryBlockCommand.CourseId = courseId; + return await _mediator.Send(addTheoryBlockCommand); + } + + [HttpDelete("{courseId:int}/theory-blocks/{id:int}")] + public async Task Remove([FromRoute] RemoveTheoryBlockByIdRequest removeTheoryBlockByIdRequest) + { + var removeTheoryBlockByIdCommand = _mapper.Map(removeTheoryBlockByIdRequest); + return await _mediator.Send(removeTheoryBlockByIdCommand); + } + + [HttpGet("{courseId:int}/theory-blocks/{id:int}")] + public async Task> GetTheoryBlockById([FromRoute] GetTheoryBlockByIdRequest getTheoryBlockByIdRequest) + { + var getTheoryBlockByIdQuery = _mapper.Map(getTheoryBlockByIdRequest); + var operationResult = await _mediator.Send(getTheoryBlockByIdQuery); + + if (!operationResult.IsSucceeded) + { + return OperationResult.Fail(operationResult.Errors); + } + + var response = _mapper.Map(operationResult.Result); + return OperationResult.Ok(response); + } + + [HttpPut("{courseId:int}/theory-blocks/{id:int}")] + public async Task> Update([FromRoute] int id, [FromRoute] int courseId, [FromBody] UpdateTheoryBlockByIdRequest updateTheoryBlockByIdRequest) + { + var updateTheoryBlockCommand = _mapper.Map(updateTheoryBlockByIdRequest); + updateTheoryBlockCommand.Id = id; + updateTheoryBlockCommand.CourseId = courseId; + var operationResult = await _mediator.Send(updateTheoryBlockCommand); + + if (!operationResult.IsSucceeded) + { + return OperationResult.Fail(operationResult.Errors); + } + + var response = _mapper.Map(operationResult); + return OperationResult.Ok(response); + } + + [HttpGet("{courseId:int}/theory-blocks")] + public async Task> GetTheoryBlocksByCourseId([FromRoute] GetTheoryBlocksByCourseIdRequest getTheoryBlockByCourseIdRequest) + { + var getTheoryBlockByCourseIdQuery = _mapper.Map(getTheoryBlockByCourseIdRequest); + var operationResult = await _mediator.Send(getTheoryBlockByCourseIdQuery); + + if (!operationResult.IsSucceeded) + { + return OperationResult.Fail(operationResult.Errors); + } + + var response = _mapper.Map(operationResult.Result); + return OperationResult.Ok(response); + } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/MapperProfiles/TheoryBlockProfile.cs b/server/StudySharp.API/MapperProfiles/TheoryBlockProfile.cs new file mode 100644 index 0000000..6f7ee8a --- /dev/null +++ b/server/StudySharp.API/MapperProfiles/TheoryBlockProfile.cs @@ -0,0 +1,19 @@ +using AutoMapper; +using StudySharp.API.Requests.TheoryBlocks; +using StudySharp.ApplicationServices.Commands; +using StudySharp.ApplicationServices.Queries; + +namespace StudySharp.API.MapperProfiles +{ + public class TheoryBlockProfile : Profile + { + public TheoryBlockProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Requests/TheoryBlocks/AddTheoryBlockRequest.cs b/server/StudySharp.API/Requests/TheoryBlocks/AddTheoryBlockRequest.cs new file mode 100644 index 0000000..30922d6 --- /dev/null +++ b/server/StudySharp.API/Requests/TheoryBlocks/AddTheoryBlockRequest.cs @@ -0,0 +1,10 @@ +using Microsoft.AspNetCore.Mvc; + +namespace StudySharp.API.Requests.TheoryBlocks +{ + public class AddTheoryBlockRequest + { + public string Name { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Requests/TheoryBlocks/GetTheoryBlockByIdRequest.cs b/server/StudySharp.API/Requests/TheoryBlocks/GetTheoryBlockByIdRequest.cs new file mode 100644 index 0000000..fdc8e3f --- /dev/null +++ b/server/StudySharp.API/Requests/TheoryBlocks/GetTheoryBlockByIdRequest.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; + +namespace StudySharp.API.Requests.TheoryBlocks +{ + public class GetTheoryBlockByIdRequest + { + [BindProperty(Name = "id", SupportsGet = true)] + public int Id { get; set; } + [BindProperty(Name = "courseId", SupportsGet = true)] + public int CourseId { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Requests/TheoryBlocks/GetTheoryBlocksByCourseIdRequest.cs b/server/StudySharp.API/Requests/TheoryBlocks/GetTheoryBlocksByCourseIdRequest.cs new file mode 100644 index 0000000..a1842fb --- /dev/null +++ b/server/StudySharp.API/Requests/TheoryBlocks/GetTheoryBlocksByCourseIdRequest.cs @@ -0,0 +1,10 @@ +using Microsoft.AspNetCore.Mvc; + +namespace StudySharp.API.Requests.TheoryBlocks +{ + public class GetTheoryBlocksByCourseIdRequest + { + [BindProperty(Name = "courseId", SupportsGet = true)] + public int CourseId { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Requests/TheoryBlocks/RemoveTheoryBlockByIdRequest.cs b/server/StudySharp.API/Requests/TheoryBlocks/RemoveTheoryBlockByIdRequest.cs new file mode 100644 index 0000000..c7df964 --- /dev/null +++ b/server/StudySharp.API/Requests/TheoryBlocks/RemoveTheoryBlockByIdRequest.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc; + +namespace StudySharp.API.Requests.TheoryBlocks +{ + public class RemoveTheoryBlockByIdRequest + { + [BindProperty(Name = "id", SupportsGet = true)] + public int Id { get; set; } + [BindProperty(Name = "courseId", SupportsGet = true)] + public int CourseId { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Requests/TheoryBlocks/UpdateTheoryBlockByIdRequest.cs b/server/StudySharp.API/Requests/TheoryBlocks/UpdateTheoryBlockByIdRequest.cs new file mode 100644 index 0000000..ce5f30a --- /dev/null +++ b/server/StudySharp.API/Requests/TheoryBlocks/UpdateTheoryBlockByIdRequest.cs @@ -0,0 +1,8 @@ +namespace StudySharp.API.Requests.TheoryBlocks +{ + public class UpdateTheoryBlockByIdRequest + { + public string Name { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Responses/TheoryBlocks/GetTheoryBlockByIdResponse.cs b/server/StudySharp.API/Responses/TheoryBlocks/GetTheoryBlockByIdResponse.cs new file mode 100644 index 0000000..16f1b4b --- /dev/null +++ b/server/StudySharp.API/Responses/TheoryBlocks/GetTheoryBlockByIdResponse.cs @@ -0,0 +1,13 @@ +using StudySharp.Domain.Models; + +namespace StudySharp.API.Responses.TheoryBlocks +{ + public class GetTheoryBlockByIdResponse + { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public int CourseId { get; set; } + public Course Course { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Responses/TheoryBlocks/GetTheoryBlocksByCourseIdResponse.cs b/server/StudySharp.API/Responses/TheoryBlocks/GetTheoryBlocksByCourseIdResponse.cs new file mode 100644 index 0000000..6724174 --- /dev/null +++ b/server/StudySharp.API/Responses/TheoryBlocks/GetTheoryBlocksByCourseIdResponse.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using StudySharp.Domain.Models; + +namespace StudySharp.API.Responses.TheoryBlocks +{ + public class GetTheoryBlocksByCourseIdResponse + { + public List TheoryBlocks { get; set; } + } +} \ No newline at end of file diff --git a/server/StudySharp.API/Responses/TheoryBlocks/UpdateTheoryBlockResponse.cs b/server/StudySharp.API/Responses/TheoryBlocks/UpdateTheoryBlockResponse.cs new file mode 100644 index 0000000..9c48a56 --- /dev/null +++ b/server/StudySharp.API/Responses/TheoryBlocks/UpdateTheoryBlockResponse.cs @@ -0,0 +1,6 @@ +namespace StudySharp.API.Responses.TheoryBlocks +{ + public class UpdateTheoryBlockResponse + { + } +} \ No newline at end of file diff --git a/server/StudySharp.ApplicationServices/Commands/AddTheoryBlockCommand.cs b/server/StudySharp.ApplicationServices/Commands/AddTheoryBlockCommand.cs index aef2848..566ef79 100644 --- a/server/StudySharp.ApplicationServices/Commands/AddTheoryBlockCommand.cs +++ b/server/StudySharp.ApplicationServices/Commands/AddTheoryBlockCommand.cs @@ -27,9 +27,13 @@ public AddTheoryBlockCommandHandler(StudySharpDbContext sharpDbContext) public async Task Handle(AddTheoryBlockCommand request, CancellationToken cancellationToken) { - if (await _context.TheoryBlocks.AnyAsync( - _ => _.Name.ToLower().Equals(request.Name.ToLower()) && _.CourseId == request.CourseId, - cancellationToken)) + var courseExistent = await _context.Courses.AnyAsync(_ => _.Id == request.CourseId, cancellationToken); + if (!courseExistent) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(Course), nameof(Course.Id), request.CourseId)); + } + + if (await _context.TheoryBlocks.AnyAsync(_ => _.Name.ToLower().Equals(request.Name.ToLower()), cancellationToken)) { return OperationResult.Fail(string.Format(ErrorConstants.EntityAlreadyExists, nameof(TheoryBlock), nameof(TheoryBlock.Name), request.Name)); } diff --git a/server/StudySharp.ApplicationServices/Commands/RemoveTheoryBlockByIdCommand.cs b/server/StudySharp.ApplicationServices/Commands/RemoveTheoryBlockByIdCommand.cs index f97318b..b7dd2b8 100644 --- a/server/StudySharp.ApplicationServices/Commands/RemoveTheoryBlockByIdCommand.cs +++ b/server/StudySharp.ApplicationServices/Commands/RemoveTheoryBlockByIdCommand.cs @@ -1,6 +1,7 @@ using System.Threading; using System.Threading.Tasks; using MediatR; +using Microsoft.EntityFrameworkCore; using StudySharp.Domain.Constants; using StudySharp.Domain.General; using StudySharp.Domain.Models; @@ -11,6 +12,7 @@ namespace StudySharp.ApplicationServices.Commands public sealed class RemoveTheoryBlockByIdCommand : IRequest { public int Id { get; set; } + public int CourseId { get; set; } } public sealed class RemoveTheoryBlockByIdCommandHandler : IRequestHandler @@ -22,15 +24,19 @@ public RemoveTheoryBlockByIdCommandHandler(StudySharpDbContext sharpDbContext) _context = sharpDbContext; } - public async Task Handle( - RemoveTheoryBlockByIdCommand request, - CancellationToken cancellationToken) + public async Task Handle(RemoveTheoryBlockByIdCommand request, CancellationToken cancellationToken) { - var theoryBlock = await _context.TheoryBlocks.FindAsync(request.Id, cancellationToken); + var courseExistent = await _context.Courses.AnyAsync(_ => _.Id == request.CourseId, cancellationToken); + if (!courseExistent) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(Course), nameof(Course.Id), request.CourseId)); + } + + var theoryBlock = await _context.TheoryBlocks.FirstOrDefaultAsync(_ => _.Id == request.Id, cancellationToken); if (theoryBlock == null) { - return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(TheoryBlock), nameof(TheoryBlock.Name), request.Id)); + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(TheoryBlock), nameof(TheoryBlock.Id), request.Id)); } _context.TheoryBlocks.Remove(theoryBlock); diff --git a/server/StudySharp.ApplicationServices/Commands/UpdateTheoryBlockCommand.cs b/server/StudySharp.ApplicationServices/Commands/UpdateTheoryBlockCommand.cs new file mode 100644 index 0000000..4fe1a7e --- /dev/null +++ b/server/StudySharp.ApplicationServices/Commands/UpdateTheoryBlockCommand.cs @@ -0,0 +1,51 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.EntityFrameworkCore; +using StudySharp.Domain.Constants; +using StudySharp.Domain.General; +using StudySharp.Domain.Models; +using StudySharp.DomainServices; + +namespace StudySharp.ApplicationServices.Commands +{ + public sealed class UpdateTheoryBlockCommand : IRequest + { + public int Id { get; set; } + public int CourseId { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + + public sealed class UpdateTheoryBlockCommandHandler : IRequestHandler + { + private readonly StudySharpDbContext _context; + + public UpdateTheoryBlockCommandHandler(StudySharpDbContext sharpDbContext) + { + _context = sharpDbContext; + } + + public async Task Handle(UpdateTheoryBlockCommand request, CancellationToken cancellationToken) + { + var courseExistent = await _context.Courses.AnyAsync(_ => _.Id == request.CourseId, cancellationToken); + if (!courseExistent) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(Course), nameof(Course.Id), request.CourseId)); + } + + var theoryBlock = await _context.TheoryBlocks.FirstOrDefaultAsync(_ => _.Id == request.Id, cancellationToken); + if (theoryBlock == null) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(TheoryBlock), nameof(TheoryBlock.Id), request.Id)); + } + + theoryBlock.Name = request.Name; + theoryBlock.Description = request.Description; + + _context.TheoryBlocks.Update(theoryBlock); + await _context.SaveChangesAsync(cancellationToken); + return OperationResult.Ok(); + } + } +} \ No newline at end of file diff --git a/server/StudySharp.ApplicationServices/Queries/GetTheoryBlockByIdQuery.cs b/server/StudySharp.ApplicationServices/Queries/GetTheoryBlockByIdQuery.cs index c471503..d0232bf 100644 --- a/server/StudySharp.ApplicationServices/Queries/GetTheoryBlockByIdQuery.cs +++ b/server/StudySharp.ApplicationServices/Queries/GetTheoryBlockByIdQuery.cs @@ -1,6 +1,7 @@ using System.Threading; using System.Threading.Tasks; using MediatR; +using Microsoft.EntityFrameworkCore; using StudySharp.Domain.Constants; using StudySharp.Domain.General; using StudySharp.Domain.Models; @@ -11,6 +12,7 @@ namespace StudySharp.ApplicationServices.Queries public sealed class GetTheoryBlockByIdQuery : IRequest> { public int Id { get; set; } + public int CourseId { get; set; } } public sealed class GetTheoryBlockByIdQueryHandler : IRequestHandler> @@ -22,11 +24,15 @@ public GetTheoryBlockByIdQueryHandler(StudySharpDbContext studySharpDbContext) _context = studySharpDbContext; } - public async Task> Handle( - GetTheoryBlockByIdQuery request, - CancellationToken cancellationToken) + public async Task> Handle(GetTheoryBlockByIdQuery request, CancellationToken cancellationToken) { - var theoryBlock = await _context.TheoryBlocks.FindAsync(request.Id, cancellationToken); + var courseExistent = await _context.Courses.AnyAsync(_ => _.Id == request.CourseId, cancellationToken); + if (!courseExistent) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(Course), nameof(Course.Id), request.CourseId)); + } + + var theoryBlock = await _context.TheoryBlocks.FirstOrDefaultAsync(_ => _.Id == request.Id && _.CourseId == request.CourseId, cancellationToken); if (theoryBlock == null) { return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(TheoryBlock), nameof(TheoryBlock.Id), request.Id)); diff --git a/server/StudySharp.ApplicationServices/Queries/GetTheoryBlocksByCourseIdQuery.cs b/server/StudySharp.ApplicationServices/Queries/GetTheoryBlocksByCourseIdQuery.cs new file mode 100644 index 0000000..a05ffeb --- /dev/null +++ b/server/StudySharp.ApplicationServices/Queries/GetTheoryBlocksByCourseIdQuery.cs @@ -0,0 +1,43 @@ +using System.Threading; +using System.Threading.Tasks; +using MediatR; +using Microsoft.EntityFrameworkCore; +using StudySharp.Domain.Constants; +using StudySharp.Domain.General; +using StudySharp.Domain.Models; +using StudySharp.DomainServices; + +namespace StudySharp.ApplicationServices.Queries +{ + public sealed class GetTheoryBlocksByCourseIdQuery : IRequest> + { + public int CourseId { get; set; } + } + + public sealed class GetTheoryBlockByCourseIdQueryHandler : IRequestHandler> + { + private readonly StudySharpDbContext _context; + + public GetTheoryBlockByCourseIdQueryHandler(StudySharpDbContext studySharpDbContext) + { + _context = studySharpDbContext; + } + + public async Task> Handle(GetTheoryBlocksByCourseIdQuery request, CancellationToken cancellationToken) + { + var courseExistent = await _context.Courses.AnyAsync(_ => _.Id == request.CourseId, cancellationToken); + if (!courseExistent) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(Course), nameof(Course.Id), request.CourseId)); + } + + var theoryBlock = await _context.TheoryBlocks.FindAsync(request.CourseId); + if (theoryBlock == null) + { + return OperationResult.Fail(string.Format(ErrorConstants.EntityNotFound, nameof(Course.TheoryBlocks), nameof(TheoryBlock.CourseId), request.CourseId)); + } + + return OperationResult.Ok(theoryBlock); + } + } +} \ No newline at end of file diff --git a/server/StudySharp.DomainServices/Migrations/20210925114723_Init.Designer.cs b/server/StudySharp.DomainServices/Migrations/20210925114723_Init.Designer.cs index 6c147d8..e0fe55d 100644 --- a/server/StudySharp.DomainServices/Migrations/20210925114723_Init.Designer.cs +++ b/server/StudySharp.DomainServices/Migrations/20210925114723_Init.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -492,4 +492,4 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) #pragma warning restore 612, 618 } } -} +} \ No newline at end of file diff --git a/server/StudySharp.DomainServices/Migrations/20210925114723_Init.cs b/server/StudySharp.DomainServices/Migrations/20210925114723_Init.cs index 0607e7a..73a2696 100644 --- a/server/StudySharp.DomainServices/Migrations/20210925114723_Init.cs +++ b/server/StudySharp.DomainServices/Migrations/20210925114723_Init.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; @@ -399,4 +399,4 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "Teachers"); } } -} +} \ No newline at end of file diff --git a/server/StudySharp.DomainServices/Migrations/StudySharpDbContextModelSnapshot.cs b/server/StudySharp.DomainServices/Migrations/StudySharpDbContextModelSnapshot.cs index 69beb26..1ac72d6 100644 --- a/server/StudySharp.DomainServices/Migrations/StudySharpDbContextModelSnapshot.cs +++ b/server/StudySharp.DomainServices/Migrations/StudySharpDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -490,4 +490,4 @@ protected override void BuildModel(ModelBuilder modelBuilder) #pragma warning restore 612, 618 } } -} +} \ No newline at end of file