Update page handling, dependencies, and UI components

*  Added `default` parameter to `DiscountActionDialogBoxViewModel`
* 🔧 Updated `@inject` in `ShippingActionDialogBox.razor` with new services
* ⬆️ Upgraded dependencies in `package-lock.json` and `package.json`
* 📝 Changed `IsShop` setting in `appsettings.Production.json` to `true`
* 💄 Updated `app.min.css` for Tailwind CSS v3.4.17 changes
* 🆕 Added `PageActionDialogBox.razor` and `PageActionDialogBox.razor.cs`
* 🆕 Introduced `BasePageLDto` class for detailed page info
* 🚀 Added `MapPost` endpoint for updating pages in `PageController.cs`
* 🔄 Refactored methods in `PageController.cs` for conciseness
* 🛠️ Updated `IPageService` and `PageService` with `UpdatePageAsync`
* 🗂️ Enhanced `SiteMapService` to filter pages by `Indexing`
* 🛒 Included `BrandId` in order bag commands

Changes made by Amir.h Khademi
master
Amir Hossein Khademi 2025-03-23 11:04:45 +03:30
parent 96feec0b26
commit 6da620690d
12 changed files with 86 additions and 47 deletions

View File

@ -38,6 +38,11 @@ public class PageController : ICarterModule
.HasApiVersion(1.0)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManagePages));
group.MapPost("", UpdatePageAsync)
.WithDisplayName("Update Page")
.HasApiVersion(1.0)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ManagePages));
group.MapDelete("{id}", DeletePageByIdAsync)
.WithDisplayName("Delete Page")
.HasApiVersion(1.0)
@ -55,27 +60,25 @@ public class PageController : ICarterModule
=> TypedResults.Ok(await pageService.DeletePageAsync(id, cancellationToken));
public async Task<IResult> GetPagesAsync([FromServices] IPageService pageService, CancellationToken cancellationToken)
{
return TypedResults.Ok(await pageService.GetPagesAsync(cancellationToken));
}
=> TypedResults.Ok(await pageService.GetPagesAsync(cancellationToken));
public async Task<IResult> GetPageByIdAsync(Guid id ,[FromServices] IPageService pageService, CancellationToken cancellationToken)
{
return TypedResults.Ok(await pageService.GetPageAsync(id: id,cancellationToken: cancellationToken));
}
=> TypedResults.Ok(await pageService.GetPageAsync(id: id, cancellationToken: cancellationToken));
public async Task<IResult> GetPageByTypeAsync(string type, [FromServices] IPageService pageService, CancellationToken cancellationToken)
{
return TypedResults.Ok(await pageService.GetPageAsync(type: type, cancellationToken: cancellationToken));
}
=> TypedResults.Ok(await pageService.GetPageAsync(type: type, cancellationToken: cancellationToken));
public async Task<IResult> GetPageAsync(string pageSlug, [FromServices] IPageService pageService, CancellationToken cancellationToken)
{
return TypedResults.Ok(await pageService.GetPageAsync(pageSlug: pageSlug,cancellationToken: cancellationToken));
}
=> TypedResults.Ok(await pageService.GetPageAsync(pageSlug: pageSlug, cancellationToken: cancellationToken));
public async Task<IResult> PostPageAsync([FromBody] PageActionRequestDto page, [FromServices] IPageService pageService, CancellationToken cancellationToken)
{
await pageService.CreatePageAsync(page, cancellationToken);
return TypedResults.Ok();
}
public async Task<IResult> UpdatePageAsync([FromBody] PageActionRequestDto page, [FromServices] IPageService pageService, CancellationToken cancellationToken)
{
await pageService.UpdatePageAsync(page, cancellationToken);
return TypedResults.Ok();
}
}

View File

@ -2,9 +2,10 @@
public interface IPageService : IScopedDependency
{
Task<BasePageSDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default);
Task<BasePageLDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default);
Task<List<BasePageSDto>> GetPagesAsync(CancellationToken cancellationToken = default);
Task<bool> CreatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default);
Task<bool> UpdatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default);
Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default);
Task<string> CheckRedirectAsync(string oldUrl, CancellationToken cancellationToken);

View File

@ -1,5 +1,4 @@
using Netina.Core.BaseServices.Abstracts;
using Netina.Domain.MartenEntities.Pages;
using Netina.Domain.MartenEntities.Pages;
namespace Netina.Core.BaseServices;
@ -9,7 +8,11 @@ public class PageService(
ISettingService settingService)
: IPageService
{
public async Task<BasePageSDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default)
public async Task<BasePageLDto> GetPageAsync(Guid? id = null,
string? pageName = null,
string? pageSlug = null,
string? type = null,
CancellationToken cancellationToken = default)
{
BasePage? page = null;
if (id != null)
@ -24,17 +27,7 @@ public class PageService(
throw new AppException("Page not found", ApiResultStatusCode.NotFound);
var entityType = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(page.Type);
var dto = new BasePageSDto
{
Content = page.Content,
Description = page.Description,
Id = page.Id,
IsCustomPage = page.IsCustomPage,
IsHtmlBasePage = page.IsHtmlBasePage,
Title = page.Title,
Slug = page.Slug,
Data = page.Data
};
var dto = page.Adapt<BasePageLDto>();
return dto;
}
@ -45,19 +38,7 @@ public class PageService(
var pages = await martenRepositoryWrapperWrapper.SetRepository<BasePage>().GetEntitiesAsync(cancellationToken);
foreach (var page in pages)
{
var dto = new BasePageSDto
{
Content = page.Content,
Description = page.Description,
Id = page.Id,
IsCustomPage = page.IsCustomPage,
IsHtmlBasePage = page.IsHtmlBasePage,
Title = page.Title,
Slug = page.Slug,
Data = page.Data,
CreatedAt = page.CreatedAt,
ModifiedAt = page.ModifiedAt
};
var dto = page.Adapt<BasePageSDto>();
sDtos.Add(dto);
}
return sDtos;
@ -124,4 +105,11 @@ public class PageService(
}
throw new BaseApiException(ApiResultStatusCode.NotFound, "PageSetting not found");
}
public async Task<bool> UpdatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default)
{
var basePage = entity.Adapt<BasePage>();
await martenRepositoryWrapperWrapper.SetRepository<BasePage>().AddOrUpdateEntityAsync(basePage, cancellationToken);
return true;
}
}

View File

@ -123,7 +123,7 @@ public class SiteMapService(
root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1");
doc.AppendChild(root);
foreach (var page in pages)
foreach (var page in pages.Where(p=>p.Indexing))
{
string slugHtml = page.Slug;
if (slugHtml.Contains(' '))

View File

@ -31,7 +31,7 @@ public class AddToOrderBagCommandHandler(
await mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
orderBag.AddToOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount,
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId, requestDto.Count);
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId,productSDto.BrandId, requestDto.Count);
}
repositoryWrapper.SetRepository<Order>().Update(orderBag);

View File

@ -31,7 +31,7 @@ public class SubmitOrderBagCommandHandler(
await mediator.Send(new CalculateProductDiscountCommand(productSDto), cancellationToken);
orderBag.ChangeOrderBag(productSDto.Id, productSDto.Cost, productSDto.CostWithDiscount,
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId, requestDto.Count);
productSDto.HasDiscount, productSDto.PackingCost, productSDto.CategoryId,productSDto.BrandId, requestDto.Count);
}
foreach (var orderProduct in orderBag.OrderProducts.ToList())
{

View File

@ -0,0 +1,16 @@
using Newtonsoft.Json;
namespace Netina.Domain.Dtos.LargDtos;
public class BasePageLDto : BaseDto<BasePageLDto, BasePage>
{
public string Title { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public bool IsCustomPage { get; set; }
public bool IsHtmlBasePage { get; set; }
public string Slug { get; set; } = string.Empty;
public string Data { get; set; } = string.Empty;
public DateTime ModifiedAt { get; set; }
public bool Indexing { get; set; }
public List<BasePageSection> Sections { get; set; } = new();
}

View File

@ -1,4 +1,6 @@
namespace Netina.Domain.Dtos.RequestDtos;
using Netina.Domain.MartenEntities.Pages;
namespace Netina.Domain.Dtos.RequestDtos;
public class PageActionRequestDto
{
@ -11,4 +13,6 @@ public class PageActionRequestDto
public string Slug { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public object? Data { get; set; }
public bool Indexing { get; set; }
public List<BasePageSection> Sections { get; set; } = new();
}

View File

@ -1,5 +1,4 @@
using Netina.Domain.MartenEntities.Pages;
using Newtonsoft.Json;
using Newtonsoft.Json;
namespace Netina.Domain.Dtos.SmallDtos;
@ -13,6 +12,7 @@ public class BasePageSDto : BaseDto<BasePageSDto,BasePage>
public string Slug { get; set; } = string.Empty;
public string Data { get; set; } = string.Empty;
public DateTime ModifiedAt { get; set; }
public bool Indexing { get; set; } = true;
public T GetData<T>() => JsonConvert.DeserializeObject<T>(Data);
}

View File

@ -12,7 +12,11 @@ public partial class Order
}
public void AddToOrderBag(Guid productId, double cost, double costWithDiscount, bool hasDiscount, double packingCost,
public void AddToOrderBag(Guid productId,
double cost,
double costWithDiscount,
bool hasDiscount,
double packingCost,
Guid categoryId,
Guid brandId,
int count)

View File

@ -10,4 +10,26 @@ public class BasePage : MartenEntity
public string Slug { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
public string Data { get; set; } = string.Empty;
public bool Indexing { get; set; } = true;
public List<BasePageSection> Sections { get; set; } = new();
}
public class BasePageSection
{
public string Title { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string CTAText { get; set; } = string.Empty;
public string CTARoute { get; set; } = string.Empty;
public BasePageSectionType Type { get; set; }
public string Query { get; set; } = string.Empty;
}
public enum BasePageSectionType
{
[Display(Name = "اسلایدر محصولات")]
ProductSlider = 0,
[Display(Name = "اسلایدر دسته بندی محصولات")]
ProductCategorySlider = 1,
[Display(Name = "اسلایدر بلاگ ها")]
BlogSlider = 2
}

View File

@ -83,6 +83,7 @@
<Using Include="Netina.Domain.Entities.Warehouses" />
<Using Include="Netina.Domain.Enums" />
<Using Include="Netina.Domain.MartenEntities.Faqs" />
<Using Include="Netina.Domain.MartenEntities.Pages" />
<Using Include="Netina.Domain.MartenEntities.Settings" />
<Using Include="Netina.Domain.Models" />
<Using Include="System.ComponentModel.DataAnnotations" />