feat: Add SitePageSettings - simplified page management system
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m2s

- New entities: SitePageSettings + SitePageImage (4 fixed pages)
- EF Migration: AddSitePageSettings (SitePageSettings + SitePageImages tables)
- Proto: sitepagesettings.proto with 5 RPCs
- CQRS: GetPageSettings, GetAllPageSettings, SavePageSettings, SavePageImage, DeletePageImage
- gRPC Service: SitePageSettingsService (auto-registered)
- Proto NuGet bumped to 0.0.180
This commit is contained in:
masoodafar-web
2026-02-17 22:34:29 +03:30
parent 89e146bf32
commit fd24dcebcd
18 changed files with 5860 additions and 1 deletions
@@ -0,0 +1,146 @@
using CMSMicroservice.Protobuf.Protos.SitePageSettings;
using CMSMicroservice.Application.SitePageSettingsCQ.Commands.DeletePageImage;
using CMSMicroservice.Application.SitePageSettingsCQ.Commands.SavePageImage;
using CMSMicroservice.Application.SitePageSettingsCQ.Commands.SavePageSettings;
using CMSMicroservice.Application.SitePageSettingsCQ.Queries.GetAllPageSettings;
using CMSMicroservice.Application.SitePageSettingsCQ.Queries.GetPageSettings;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using MediatR;
namespace CMSMicroservice.WebApi.Services;
public class SitePageSettingsService : SitePageSettingsContract.SitePageSettingsContractBase
{
private readonly ISender _sender;
public SitePageSettingsService(ISender sender)
{
_sender = sender;
}
// ── GetPageSettings ──
public override async Task<PageSettingsResponse> GetPageSettings(GetPageSettingsRequest request, ServerCallContext context)
{
var query = new GetPageSettingsQuery { PageKey = request.PageKey };
var result = await _sender.Send(query, context.CancellationToken);
if (result == null)
throw new RpcException(new Status(StatusCode.NotFound, $"صفحه با کلید '{request.PageKey}' یافت نشد"));
return MapToResponse(result);
}
// ── GetAllPageSettings ──
public override async Task<GetAllPageSettingsResponse> GetAllPageSettings(GetAllPageSettingsRequest request, ServerCallContext context)
{
var query = new GetAllPageSettingsQuery();
var result = await _sender.Send(query, context.CancellationToken);
var response = new GetAllPageSettingsResponse();
foreach (var item in result)
{
response.Pages.Add(new PageSettingsSummary
{
Id = item.Id,
PageKey = item.PageKey,
Title = item.Title,
IsActive = item.IsActive,
ImageCount = item.ImageCount,
LastModified = Timestamp.FromDateTime(DateTime.SpecifyKind(item.LastModified, DateTimeKind.Utc))
});
}
return response;
}
// ── SavePageSettings ──
public override async Task<SavePageSettingsResponse> SavePageSettings(SavePageSettingsRequest request, ServerCallContext context)
{
var command = new SavePageSettingsCommand
{
PageKey = request.PageKey,
Title = request.Title,
MetaDescription = request.MetaDescription,
HeroTitle = request.HeroTitle,
HeroSubtitle = request.HeroSubtitle,
IsActive = request.IsActive,
SettingsJson = request.SettingsJson,
ImageFileBytes = request.HeroImageFile?.File?.ToByteArray(),
ImageFileMime = request.HeroImageFile?.Mime,
ImageFileName = request.HeroImageFile?.FileName
};
var result = await _sender.Send(command, context.CancellationToken);
return new SavePageSettingsResponse { Id = result.Id, Success = result.Success };
}
// ── SavePageImage ──
public override async Task<SavePageImageResponse> SavePageImage(SavePageImageRequest request, ServerCallContext context)
{
var command = new SavePageImageCommand
{
Id = request.Id,
SitePageSettingsId = request.SitePageSettingsId,
ImageGroup = request.ImageGroup,
Title = request.Title,
Subtitle = request.Subtitle,
Description = request.Description,
LinkUrl = request.LinkUrl,
IconName = request.IconName,
SortOrder = request.SortOrder,
IsActive = request.IsActive,
ImageFileBytes = request.ImageFile?.File?.ToByteArray(),
ImageFileMime = request.ImageFile?.Mime,
ImageFileName = request.ImageFile?.FileName
};
var result = await _sender.Send(command, context.CancellationToken);
return new SavePageImageResponse { Id = result.Id, Success = result.Success };
}
// ── DeletePageImage ──
public override async Task<Empty> DeletePageImage(DeletePageImageRequest request, ServerCallContext context)
{
var command = new DeletePageImageCommand { Id = request.Id };
await _sender.Send(command, context.CancellationToken);
return new Empty();
}
// ── Private Mapping Helpers ──
private static PageSettingsResponse MapToResponse(PageSettingsDto dto)
{
var response = new PageSettingsResponse
{
Id = dto.Id,
PageKey = dto.PageKey,
Title = dto.Title,
MetaDescription = dto.MetaDescription,
HeroTitle = dto.HeroTitle,
HeroSubtitle = dto.HeroSubtitle,
HeroImagePath = dto.HeroImagePath,
IsActive = dto.IsActive,
SettingsJson = dto.SettingsJson ?? string.Empty
};
foreach (var img in dto.Images)
{
response.Images.Add(new PageImageItem
{
Id = img.Id,
ImageGroup = img.ImageGroup,
Title = img.Title,
Subtitle = img.Subtitle,
Description = img.Description,
ImagePath = img.ImagePath,
ThumbnailPath = img.ThumbnailPath,
LinkUrl = img.LinkUrl,
IconName = img.IconName,
SortOrder = img.SortOrder,
IsActive = img.IsActive
});
}
return response;
}
}