Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expressed realms 169 add backend for sub section edit #171

Merged
merged 12 commits into from
Oct 16, 2024

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;

#nullable disable

namespace ExpressedRealms.DB.Migrations
{
/// <inheritdoc />
public partial class MakeExpressionSectionsSoftDeletes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "PublishStatusId",
table: "Expressions",
type: "integer",
nullable: false,
defaultValue: 1,
oldClrType: typeof(int),
oldType: "integer");

migrationBuilder.AddColumn<DateTimeOffset>(
name: "DeletedAt",
table: "ExpressionSections",
type: "timestamp with time zone",
nullable: true);

migrationBuilder.AddColumn<bool>(
name: "IsDeleted",
table: "ExpressionSections",
type: "boolean",
nullable: false,
defaultValue: false);
}

/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DeletedAt",
table: "ExpressionSections");

migrationBuilder.DropColumn(
name: "IsDeleted",
table: "ExpressionSections");

migrationBuilder.AlterColumn<int>(
name: "PublishStatusId",
table: "Expressions",
type: "integer",
nullable: false,
oldClrType: typeof(int),
oldType: "integer",
oldDefaultValue: 1);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("text");

b.Property<int>("PublishStatusId")
.HasColumnType("integer");
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(1);

b.Property<string>("ShortDescription")
.IsRequired()
Expand Down Expand Up @@ -184,9 +186,15 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.IsRequired()
.HasColumnType("text");

b.Property<DateTimeOffset?>("DeletedAt")
.HasColumnType("timestamp with time zone");

b.Property<int>("ExpressionId")
.HasColumnType("integer");

b.Property<bool>("IsDeleted")
.HasColumnType("boolean");

b.Property<string>("Name")
.IsRequired()
.HasMaxLength(150)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using ExpressedRealms.DB.Characters;
using ExpressedRealms.DB.Interceptors;

namespace ExpressedRealms.DB.Models.Expressions;

public class ExpressionSection
public class ExpressionSection : ISoftDelete
{
public int Id { get; set; }
public int ExpressionId { get; set; }
public int SectionTypeId { get; set; }
public int? ParentId { get; set; }
public string Name { get; set; } = null!;
public string Content { get; set; } = null!;
public bool IsDeleted { get; set; }
public DateTimeOffset? DeletedAt { get; set; }

public virtual Expression Expression { get; set; } = null!;
public virtual ExpressionSection? Parent { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public void Configure(EntityTypeBuilder<ExpressionSection> builder)
builder.HasKey(e => e.Id);
builder.Property(e => e.Id).IsRequired();

builder.HasQueryFilter(x => !x.IsDeleted);

builder.Property(e => e.ExpressionId).IsRequired();

builder.Property(e => e.SectionTypeId).IsRequired();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using ExpressedRealms.Repositories.Expressions.Expressions;
using ExpressedRealms.Repositories.Expressions.Expressions.DTOs;
using ExpressedRealms.Repositories.Expressions.ExpressionTextSections;
using ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;
using Microsoft.Extensions.DependencyInjection;

namespace ExpressedRealms.Repositories.Expressions;
Expand All @@ -13,7 +15,12 @@ this IServiceCollection services
services.AddScoped<CreateExpressionDtoValidator>();
services.AddScoped<EditExpressionDtoValidator>();

services.AddScoped<GetExpressionTestSectionOptionsValidator>();
services.AddScoped<CreateExpressionTextSectionDtoValidator>();
services.AddScoped<EditExpressionTextSectionDtoValidator>();

services.AddScoped<IExpressionRepository, ExpressionRepository>();
services.AddScoped<IExpressionTextSectionRepository, ExpressionTextSectionRepository>();
return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ExpressedRealms.Repositories.Expressions.Expressions.DTOs;

public record CreateExpressionTextSectionDto
{
public string Name { get; set; } = null!;
public string Content { get; set; } = null!;
public int ExpressionId { get; set; }
public int SectionTypeId { get; set; }
public int? ParentId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using ExpressedRealms.DB;
using ExpressedRealms.Repositories.Expressions.ExpressionTextSections.Helpers;
using FluentValidation;
using Microsoft.EntityFrameworkCore;

namespace ExpressedRealms.Repositories.Expressions.Expressions.DTOs;

public class CreateExpressionTextSectionDtoValidator
: AbstractValidator<CreateExpressionTextSectionDto>
{
public CreateExpressionTextSectionDtoValidator(ExpressedRealmsDbContext dbContext)
{
RuleFor(x => x.Name).MaximumLength(50).NotEmpty();
RuleFor(x => x.Content).NotEmpty();
RuleFor(x => x.SectionTypeId)
.MustAsync(
async (sectionTypeId, cancellationToken) =>
{
return await dbContext.ExpressionSectionTypes.AnyAsync(
x => x.Id == sectionTypeId,
cancellationToken
);
}
)
.WithMessage("This is not a valid Section Type");
RuleFor(x => x.ExpressionId)
.MustAsync(
async (expressionId, cancellationToken) =>
{
return await dbContext.Expressions.AnyAsync(
x => x.Id == expressionId,
cancellationToken
);
}
)
.WithMessage("This is not a valid Expression Id");
RuleFor(x => x)
.MustAsync(
async (expressionSection, cancellationToken) =>
{
var expressionSections = await dbContext
.ExpressionSections.Where(x =>
x.ExpressionId == expressionSection.ExpressionId
)
.ToListAsync();

var validParentIds = RecursiveFunctions.GetValidParentIds(
expressionSections,
null,
0
);
return validParentIds.Contains(expressionSection.ParentId.Value);
}
)
.When(x => x.ParentId != null)
.WithMessage("This is not a valid Parent Id");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public record EditExpressionTextSectionDto
{
public int Id { get; init; }
public string Name { get; set; } = null!;
public string Content { get; set; } = null!;
public int ExpressionId { get; set; }
public int SectionTypeId { get; set; }
public int? ParentId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using ExpressedRealms.DB;
using ExpressedRealms.Repositories.Expressions.ExpressionTextSections.Helpers;
using FluentValidation;
using Microsoft.EntityFrameworkCore;

namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class EditExpressionTextSectionDtoValidator : AbstractValidator<EditExpressionTextSectionDto>
{
public EditExpressionTextSectionDtoValidator(ExpressedRealmsDbContext dbContext)
{
RuleFor(x => x.Id).NotEmpty().GreaterThan(0);
RuleFor(x => x.Name).MaximumLength(50).NotEmpty();
RuleFor(x => x.Content).NotEmpty();
RuleFor(x => x.SectionTypeId)
.MustAsync(
async (sectionTypeId, cancellationToken) =>
{
return await dbContext.ExpressionSectionTypes.AnyAsync(
x => x.Id == sectionTypeId,
cancellationToken
);
}
)
.WithMessage("This is not a valid Section Type");
RuleFor(x => x.ExpressionId)
.MustAsync(
async (expressionId, cancellationToken) =>
{
return await dbContext.Expressions.AnyAsync(
x => x.Id == expressionId,
cancellationToken
);
}
)
.WithMessage("This is not a valid Expression Id");
RuleFor(x => x)
.MustAsync(
async (expressionSection, cancellationToken) =>
{
var expressionSections = await dbContext
.ExpressionSections.Where(x =>
x.ExpressionId == expressionSection.ExpressionId
)
.ToListAsync();

var validParentIds = RecursiveFunctions.GetValidParentIds(
expressionSections,
null,
0
);
return validParentIds.Contains(expressionSection.ParentId.Value);
}
)
.When(x => x.ParentId != null)
.WithMessage("This is not a valid Parent Id");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class ExpressionSectionDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Content { get; set; }
public List<ExpressionSectionDto> SubSections { get; set; } = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public record ExpressionTextSectionDto
{
public string Name { get; set; } = null!;
public string ShortDescription { get; set; } = null!;
public string NavMenuImage { get; set; } = null!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class ExpressionTextSectionOptions
{
public List<ExpressionSectionDto> AvailableParents { get; set; } = null!;
public List<SectionTypeDto> ExpressionSectionTypes { get; set; } = null!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class GetExpressionTextSectionDto
{
public int Id { get; init; }
public string Name { get; set; } = null!;
public string Content { get; set; }
public int? ParentId { get; set; }
public int SectionTypeId { get; set; }
public List<SectionTypeDto> SectionTypes { get; set; } = null!;
public List<ExpressionSectionDto> AvailableParents { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class GetExpressionTestSectionOptionsDto
{
public int ExpressionId { get; set; }
public int? SectionId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using ExpressedRealms.DB;
using FluentValidation;
using Microsoft.EntityFrameworkCore;

namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class GetExpressionTestSectionOptionsValidator
: AbstractValidator<GetExpressionTestSectionOptionsDto>
{
public GetExpressionTestSectionOptionsValidator(ExpressedRealmsDbContext dbContext)
{
RuleFor(x => x.SectionId)
.MustAsync(
async (sectionId, cancellationToken) =>
{
return await dbContext.ExpressionSections.AnyAsync(
x => x.Id == sectionId,
cancellationToken
);
}
)
.When(x => x.SectionId is not null)
.WithMessage("This is not a valid Section");
RuleFor(x => x.ExpressionId)
.MustAsync(
async (expressionId, cancellationToken) =>
{
return await dbContext.Expressions.AnyAsync(
x => x.Id == expressionId,
cancellationToken
);
}
)
.WithMessage("This is not a valid Expression Id");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ExpressedRealms.Repositories.Expressions.ExpressionTextSections.DTOs;

public class SectionTypeDto
{
public int Id { get; set; }
public string Name { get; set; } = null!;
public string? Description { get; set; }
}
Loading
Loading