version 0.27.33.54 , fix blog update issue , fix sitemap , fix page creation

release
Amir Hossein Khademi 2024-05-14 12:46:11 +03:30
parent 5a38eda328
commit c152f06e08
15 changed files with 146 additions and 50 deletions

View File

@ -1 +1 @@
0.27.32.53
0.27.33.54

View File

@ -82,6 +82,8 @@ public class BlogCategoryController : ICarterModule
if (dto.ParentId != default)
ent.SetParent(dto.ParentId);
newEnt.Id = ent.Id;
newEnt.CreatedAt = ent.CreatedAt;
newEnt.CreatedBy = ent.CreatedBy;
repositoryWrapper.SetRepository<BlogCategory>().Update(newEnt);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
return TypedResults.Ok();

View File

@ -74,6 +74,8 @@ public class BlogController : ICarterModule
throw new AppException("Blog not found");
var newEnt = Blog.Create(dto.Title, dto.Content, dto.Tags, dto.ReadingTime, dto.Summery, dto.IsSuggested, dto.CategoryId);
newEnt.Id = ent.Id;
newEnt.CreatedAt = ent.CreatedAt;
newEnt.CreatedBy = ent.CreatedBy;
repositoryWrapper.SetRepository<Blog>().Update(newEnt);
await repositoryWrapper.SaveChangesAsync(cancellationToken);
return TypedResults.Ok();

View File

@ -31,8 +31,19 @@ public class PageController : ICarterModule
.WithDisplayName("Post 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)
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewPages, ApplicationPermission.ManagePages));
}
public async Task<IResult> GetPagesAsync(Guid id, [FromServices] IPageService pageService, CancellationToken cancellationToken)
private async Task<IResult> DeletePageByIdAsync([FromRoute]Guid id,[FromServices]IPageService pageService,CancellationToken cancellationToken)
=> TypedResults.Ok(await pageService.DeletePageAsync(id, cancellationToken));
public async Task<IResult> GetPagesAsync([FromServices] IPageService pageService, CancellationToken cancellationToken)
{
return TypedResults.Ok(await pageService.GetPagesAsync(cancellationToken));
}

View File

@ -6,8 +6,8 @@
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<AssemblyVersion>0.27.31.52</AssemblyVersion>
<FileVersion>0.27.31.52</FileVersion>
<AssemblyVersion>0.27.33.54</AssemblyVersion>
<FileVersion>0.27.33.54</FileVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -8,7 +8,7 @@ string env = builder.Environment.IsDevelopment() == true ? "Development" : "Prod
builder.Host.UseContentRoot(Directory.GetCurrentDirectory());
if (builder.Environment.IsDevelopment())
{
string projectName = "Hamyan";
string projectName = "Vesmeh";
builder.Configuration.AddJsonFile($"AppSettings/appsettings.json").AddJsonFile($"AppSettings/appsettings.{env}{projectName}.json");
}

View File

@ -12,12 +12,17 @@ public class SiteMapService : ISiteMapService
{
private readonly IUploadFileService _uploadFileService;
private readonly IRepositoryWrapper _repositoryWrapper;
private readonly IPageService _pageService;
private readonly SiteSettings _siteSetting;
public SiteMapService(IOptionsSnapshot<SiteSettings> snapshot, IUploadFileService uploadFileService, IRepositoryWrapper repositoryWrapper)
public SiteMapService(IOptionsSnapshot<SiteSettings> snapshot,
IUploadFileService uploadFileService,
IRepositoryWrapper repositoryWrapper,
IPageService pageService)
{
_uploadFileService = uploadFileService;
_repositoryWrapper = repositoryWrapper;
_pageService = pageService;
_siteSetting = snapshot.Value;
}
public async Task CreateSiteMapAsync()
@ -106,10 +111,77 @@ public class SiteMapService : ISiteMapService
await CreateBlogsSiteMapsAsync();
await CreateBrandsSiteMapsAsync();
await CreateBlogCategoriesSiteMapsAsync();
await CreatePagesSiteMapsAsync();
}
private async Task CreatePagesSiteMapsAsync()
{
var siteMapsUId = SiteMapUIds.Pages;
var pages = await _pageService.GetPagesAsync();
XmlDocument doc = new XmlDocument();
XmlDeclaration documentType = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.AppendChild(documentType);
//XmlNode declaration = doc.CreateNode(XmlNodeType.XmlDeclaration, "sitemap.xml", null);
//doc.AppendChild(declaration);
XmlElement root = doc.CreateElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
root.SetAttribute("xmlns:image", "http://www.google.com/schemas/sitemap-image/1.1");
doc.AppendChild(root);
foreach (var page in pages)
{
var productUrl = $"{_siteSetting.WebSiteUrl}/{page.Slug}";
XmlElement urlElement = doc.CreateElement("url", doc.DocumentElement?.NamespaceURI);
root.AppendChild(urlElement);
XmlElement loc = doc.CreateElement("loc", doc.DocumentElement?.NamespaceURI);
loc.InnerText = Path.Combine(productUrl);
urlElement.AppendChild(loc);
XmlElement lastmod = doc.CreateElement("lastmod", doc.DocumentElement?.NamespaceURI);
lastmod.InnerText = page.ModifiedAt == DateTime.MinValue ? page.CreatedAt.ToString("yyyy-MM-dd") : page.ModifiedAt.ToString("yyyy-MM-dd");
urlElement.AppendChild(lastmod);
XmlElement changeFeq = doc.CreateElement("changefreq", doc.DocumentElement?.NamespaceURI);
changeFeq.InnerText = "weekly";
urlElement.AppendChild(changeFeq);
XmlElement priority = doc.CreateElement("priority", doc.DocumentElement?.NamespaceURI);
priority.InnerText = "0.8";
urlElement.AppendChild(priority);
}
using var siteMapStream = new MemoryStream();
await using var siteMapWriter = new XmlTextWriter(siteMapStream, Encoding.UTF8);
doc.WriteTo(siteMapWriter);
siteMapWriter.Flush();
byte[] unZipBytes = siteMapStream.ToArray();
using (var compressedStream = new MemoryStream())
await using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
{
zipStream.Write(unZipBytes, 0, unZipBytes.Length);
zipStream.Close();
var siteMapArray = compressedStream.ToArray();
await _uploadFileService.UploadFileByteAsync(new FileUploadRequest
{
FileBytes = siteMapArray,
ContentType = "text/plain",
FileName = $"{siteMapsUId}.gz",
FileUploadType = FileUploadType.SiteMap,
});
}
}
private async Task CreateBrandsSiteMapsAsync()
{
var siteMapsUId = SiteMapUIds.Brands;

View File

@ -1,12 +1,9 @@
using Netina.Common.Models;
using Netina.Domain.Dtos.RequestDtos;
using Netina.Domain.Dtos.SmallDtos;
namespace Netina.Core.CoreServices.Abstracts;
namespace Netina.Core.CoreServices.Abstracts;
public interface IPageService : IScopedDependency
{
Task<BasePageSDto> 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> DeletePageAsync(Guid id,CancellationToken cancellationToken = default);
}

View File

@ -1,21 +1,16 @@
using Netina.Common.Models.Api;
using Netina.Common.Models.Exception;
using Netina.Core.CoreServices.Abstracts;
using Netina.Domain;
using Netina.Domain.Dtos.RequestDtos;
using Netina.Domain.Dtos.SmallDtos;
using Netina.Domain.MartenEntities.Pages;
using Netina.Repository.Repositories.Marten;
using Netina.Domain.MartenEntities.Pages;
namespace Netina.Core.CoreServices;
public class PageService : IPageService
{
private readonly IMartenRepositoryWrapper _martenRepositoryWrapper;
private readonly ICurrentUserService _currentUserService;
public PageService(IMartenRepositoryWrapper martenRepositoryWrapperWrapper)
public PageService(IMartenRepositoryWrapper martenRepositoryWrapperWrapper, ICurrentUserService currentUserService)
{
_martenRepositoryWrapper = martenRepositoryWrapperWrapper;
_currentUserService = currentUserService;
}
public async Task<BasePageSDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default)
{
@ -25,7 +20,7 @@ public class PageService : IPageService
else if (pageSlug != null)
page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Slug == pageSlug, cancellationToken);
else if (pageName != null)
page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Name == pageName, cancellationToken);
page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Title == pageName, cancellationToken);
else if (type != null)
page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Type == type, cancellationToken);
if (page == null)
@ -39,7 +34,7 @@ public class PageService : IPageService
Id = page.Id,
IsCustomPage = page.IsCustomPage,
IsHtmlBasePage = page.IsHtmlBasePage,
Name = page.Name,
Title = page.Title,
Slug = page.Slug,
Data = page.Data
};
@ -53,8 +48,6 @@ public class PageService : IPageService
var pages = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntitiesAsync(cancellationToken);
foreach (var page in pages)
{
var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(page.Type);
var dto = new BasePageSDto
{
Content = page.Content,
@ -62,9 +55,11 @@ public class PageService : IPageService
Id = page.Id,
IsCustomPage = page.IsCustomPage,
IsHtmlBasePage = page.IsHtmlBasePage,
Name = page.Name,
Title = page.Title,
Slug = page.Slug,
Data = page.Data
Data = page.Data,
CreatedAt = page.CreatedAt,
ModifiedAt = page.ModifiedAt
};
sDtos.Add(dto);
}
@ -77,16 +72,30 @@ public class PageService : IPageService
{
Content = entity.Content,
Description = entity.Description,
Id = entity.Id,
Id = Guid.NewGuid(),
IsCustomPage = entity.IsCustomPage,
IsHtmlBasePage = entity.IsHtmlBasePage,
Name = entity.Name,
Title = entity.Title,
Type = entity.Type,
Slug = entity.Slug,
CreatedAt = DateTime.Now,
CreatedBy = _currentUserService.UserName ?? string.Empty
};
var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(entity.Type);
basePage.Data = JsonConvert.SerializeObject(((JsonElement)entity.Data).Deserialize(type));
if (!basePage.Type.IsNullOrEmpty())
{
var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(entity.Type);
basePage.Data = JsonConvert.SerializeObject(((JsonElement)entity.Data).Deserialize(type));
}
await _martenRepositoryWrapper.SetRepository<BasePage>().AddOrUpdateEntityAsync(basePage, cancellationToken);
return true;
}
public async Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default)
{
var page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(p => p.Id == id, cancellationToken);
if (page == null)
throw new AppException("Page not found", ApiResultStatusCode.NotFound);
await _martenRepositoryWrapper.SetRepository<BasePage>().RemoveEntityAsync(page,cancellationToken);
return true;
}
}

View File

@ -5,12 +5,14 @@ public static class SiteMapUIds
public const string Brands = "662AF2DC6A2746FA88191F1F3DA94164";
public const string Blogs = "4C2F0C2A7A3E41268702D12FDDDB837F";
public const string BlogCategories = "B5FF333DC4FF4BB4A309CE3AA32CE45A";
public const string Pages = "B463B6C4CC53432C822D79934F528D3E";
public static List<string> AllSiteMapsUIds => new List<string>
{
BlogCategories,
Categories,
Blogs,
Brands
Brands,
Pages
};
}

View File

@ -3,7 +3,7 @@
public class PageActionRequestDto
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
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; }

View File

@ -5,13 +5,14 @@ namespace Netina.Domain.Dtos.SmallDtos;
public class BasePageSDto : BaseDto<BasePageSDto,BasePage>
{
public string Name { get; set; } = string.Empty;
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 T GetData<T>() => JsonConvert.DeserializeObject<T>(Data);
}

View File

@ -2,7 +2,7 @@
public class BasePage : MartenEntity
{
public string Name { get; set; } = string.Empty;
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; }

View File

@ -1,8 +1,4 @@
using Marten;
using Netina.Common.Models.Api;
using Netina.Common.Models.Entity;
using Netina.Common.Models.Exception;
using Netina.Repository.Repositories.Marten;
namespace Netina.Infrastructure.Marten;
@ -45,18 +41,22 @@ public class MartenRepository<TMartenEntity> : IMartenRepository<TMartenEntity>
return entity;
}
public async Task AddOrUpdateEntityAsync(TMartenEntity setting, CancellationToken cancellation)
public async Task AddOrUpdateEntityAsync(TMartenEntity entity, CancellationToken cancellation)
{
if (setting == null)
throw new AppException($"{nameof(setting)} is null", ApiResultStatusCode.BadRequest);
if (entity == null)
throw new AppException($"{nameof(entity)} is null", ApiResultStatusCode.BadRequest);
await using var session = _documentStore.LightweightSession();
session.Store(setting);
session.Store(entity);
await session.SaveChangesAsync(cancellation);
}
public Task RemoveEntityAsync(CancellationToken cancellation)
public async Task RemoveEntityAsync(TMartenEntity entity, CancellationToken cancellation)
{
throw new NotImplementedException();
if (entity == null)
throw new AppException($"{nameof(entity)} is null", ApiResultStatusCode.BadRequest);
await using var session = _documentStore.LightweightSession();
session.Delete(entity);
await session.SaveChangesAsync(cancellation);
}
}

View File

@ -4,12 +4,12 @@ namespace Netina.Repository.Repositories.Marten;
public interface IMartenRepository<TMartenEntity> : IScopedDependency where TMartenEntity : IMartenEntity
{
Task<List<TMartenEntity>> GetEntitiesAsync(CancellationToken cancellation);
Task<List<TMartenEntity>> GetEntitiesAsync(Expression<Func<TMartenEntity, bool>> expression, CancellationToken cancellation);
Task<List<TMartenEntity>> GetEntitiesAsync(CancellationToken cancellation = default);
Task<List<TMartenEntity>> GetEntitiesAsync(Expression<Func<TMartenEntity, bool>> expression, CancellationToken cancellation = default);
Task<TMartenEntity> GetEntityAsync(Guid id, CancellationToken cancellation);
Task<TMartenEntity?> GetEntityAsync(Expression<Func<TMartenEntity, bool>> expression, CancellationToken cancellation);
Task<TMartenEntity> GetEntityAsync(Guid id, CancellationToken cancellation = default);
Task<TMartenEntity?> GetEntityAsync(Expression<Func<TMartenEntity, bool>> expression, CancellationToken cancellation = default);
Task AddOrUpdateEntityAsync(TMartenEntity setting, CancellationToken cancellation);
Task RemoveEntityAsync(CancellationToken cancellation);
Task AddOrUpdateEntityAsync(TMartenEntity entity, CancellationToken cancellation = default);
Task RemoveEntityAsync(TMartenEntity entity, CancellationToken cancellation = default);
}