Add instructions management functionality and update related components
CI / Backend (build + test) (push) Successful in 1m17s
CI / Frontend (lint + typecheck + build) (push) Successful in 32s

- Introduced new endpoints for managing instruction intros and tabs, allowing admins to create, update, and delete instructional content.
- Enhanced the FactoryResetCommandHandler to include the seeding of instruction data during a factory reset.
- Updated the database schema to include InstructionIntro and InstructionTab entities, with corresponding migrations.
- Improved frontend routing and components to support the new instructions section, including a dedicated page for displaying instructions and tabs.
- Enhanced API documentation to reflect the new instruction management features and their expected request/response formats.
- Added localization support for the new instructions functionality in both Russian and English.
This commit is contained in:
Leonid Pershin
2026-07-14 22:20:10 +03:00
parent 8c53fcded2
commit bef3880593
52 changed files with 2303 additions and 24 deletions
@@ -0,0 +1,68 @@
using PnvPanel.Api.Common;
using PnvPanel.Application.Admin.Instructions;
using PnvPanel.Application.Common.Messaging;
using PnvPanel.Application.Instructions;
using PnvPanel.Infrastructure.Identity;
namespace PnvPanel.Api.Endpoints;
public static class AdminInstructionEndpoints
{
public static IEndpointRouteBuilder MapAdminInstructionEndpoints(this IEndpointRouteBuilder app)
{
var admin = app.MapGroup("/api/admin/instructions")
.WithTags("Admin.Instructions")
.RequireAuthorization(policy => policy.RequireRole(RoleNames.Admin));
admin.MapPut("/intro", UpdateIntro).Produces<InstructionIntroDto>();
admin.MapPost("/tabs", CreateTab).Produces<InstructionTabDto>();
admin.MapPut("/tabs/{id:guid}", UpdateTab).Produces<InstructionTabDto>();
admin.MapDelete("/tabs/{id:guid}", DeleteTab).Produces(StatusCodes.Status204NoContent);
return app;
}
private static async Task<IResult> UpdateIntro(
UpdateInstructionIntroCommand command,
ISender sender,
CancellationToken cancellationToken
)
{
var result = await sender.Send(command, cancellationToken);
return result.ToHttpResult();
}
private static async Task<IResult> CreateTab(
CreateInstructionTabCommand command,
ISender sender,
CancellationToken cancellationToken
)
{
var result = await sender.Send(command, cancellationToken);
return result.ToHttpResult();
}
private static async Task<IResult> UpdateTab(
Guid id,
UpdateInstructionTabBody body,
ISender sender,
CancellationToken cancellationToken
)
{
var command = new UpdateInstructionTabCommand(id, body.Title, body.Body, body.SortOrder);
var result = await sender.Send(command, cancellationToken);
return result.ToHttpResult();
}
private static async Task<IResult> DeleteTab(
Guid id,
ISender sender,
CancellationToken cancellationToken
)
{
var result = await sender.Send(new DeleteInstructionTabCommand(id), cancellationToken);
return result.ToHttpResult();
}
}
public sealed record UpdateInstructionTabBody(string Title, string Body, int SortOrder);
@@ -0,0 +1,32 @@
using PnvPanel.Api.Common;
using PnvPanel.Application.Common.Messaging;
using PnvPanel.Application.Instructions;
namespace PnvPanel.Api.Endpoints;
public static class InstructionEndpoints
{
public static IEndpointRouteBuilder MapInstructionEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/api/instructions")
.WithTags("Instructions")
.RequireAuthorization();
group.MapGet("/intro", GetIntro).Produces<InstructionIntroDto>();
group.MapGet("/tabs", ListTabs).Produces<IReadOnlyList<InstructionTabDto>>();
return app;
}
private static async Task<IResult> GetIntro(ISender sender, CancellationToken cancellationToken)
{
var result = await sender.Send(new GetInstructionIntroQuery(), cancellationToken);
return result.ToHttpResult();
}
private static async Task<IResult> ListTabs(ISender sender, CancellationToken cancellationToken)
{
var result = await sender.Send(new ListInstructionTabsQuery(), cancellationToken);
return result.ToHttpResult();
}
}
+2
View File
@@ -185,10 +185,12 @@ app.MapConfigEndpoints();
app.MapSubscriptionEndpoints();
app.MapAppEndpoints();
app.MapNewsEndpoints();
app.MapInstructionEndpoints();
app.MapAdminUserEndpoints();
app.MapAdminStatsEndpoints();
app.MapAdminAppEndpoints();
app.MapAdminNewsEndpoints();
app.MapAdminInstructionEndpoints();
app.MapSupportEndpoints();
app.MapAdminSupportEndpoints();
app.MapAdminMaintenanceEndpoints();