Blog düzenlemesi

This commit is contained in:
Sedat ÖZTÜRK 2026-03-11 15:20:40 +03:00
parent dfc63617f8
commit 5e772272dc
15 changed files with 46 additions and 64 deletions

View file

@ -18,8 +18,7 @@ public class BlogPostDto : FullAuditedEntityDto<Guid>
public Guid CategoryId { get; set; } public Guid CategoryId { get; set; }
public BlogCategoryDto Category { get; set; } public BlogCategoryDto Category { get; set; }
public Guid UserId { get; set; } public string Author { get; set; }
public UserInfoViewModel User { get; set; }
public int ViewCount { get; set; } public int ViewCount { get; set; }
public int LikeCount { get; set; } public int LikeCount { get; set; }

View file

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Sozsoft.Platform.Identity.Dto;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
namespace Sozsoft.Platform.Public; namespace Sozsoft.Platform.Public;
@ -19,8 +18,7 @@ public class BlogPostListDto : EntityDto<Guid>
public Guid CategoryId { get; set; } public Guid CategoryId { get; set; }
public BlogCategoryDto Category { get; set; } public BlogCategoryDto Category { get; set; }
public Guid UserId { get; set; } public string Author { get; set; }
public UserInfoViewModel User { get; set; }
public int ViewCount { get; set; } public int ViewCount { get; set; }
public int LikeCount { get; set; } public int LikeCount { get; set; }

View file

@ -44,7 +44,7 @@ public class BlogAppService : PlatformAppService, IBlogAppService
ReadTime = input.ReadTime, ReadTime = input.ReadTime,
CoverImage = input.CoverImage, CoverImage = input.CoverImage,
CategoryId = input.CategoryId, CategoryId = input.CategoryId,
UserId = _currentUser.Id.Value, Author = _currentUser.Name,
IsPublished = true, IsPublished = true,
}; };
@ -73,7 +73,7 @@ public class BlogAppService : PlatformAppService, IBlogAppService
{ {
var post = await _postRepository.GetAsync(id); var post = await _postRepository.GetAsync(id);
if (post.UserId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Update")) if (post.Author != _currentUser.Name && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Update"))
{ {
throw new Volo.Abp.Authorization.AbpAuthorizationException(); throw new Volo.Abp.Authorization.AbpAuthorizationException();
} }
@ -125,7 +125,7 @@ public class BlogAppService : PlatformAppService, IBlogAppService
var post = await _postRepository.GetAsync(id); var post = await _postRepository.GetAsync(id);
// Check if user is author or has permission // Check if user is author or has permission
if (post.UserId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Delete")) if (post.Author != _currentUser.Name && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Delete"))
{ {
throw new Volo.Abp.Authorization.AbpAuthorizationException(); throw new Volo.Abp.Authorization.AbpAuthorizationException();
} }
@ -143,7 +143,7 @@ public class BlogAppService : PlatformAppService, IBlogAppService
var post = await _postRepository.GetAsync(id); var post = await _postRepository.GetAsync(id);
// Check if user is author or has permission // Check if user is author or has permission
if (post.UserId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish")) if (post.Author != _currentUser.Name && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish"))
{ {
throw new Volo.Abp.Authorization.AbpAuthorizationException(); throw new Volo.Abp.Authorization.AbpAuthorizationException();
} }
@ -159,7 +159,7 @@ public class BlogAppService : PlatformAppService, IBlogAppService
var post = await _postRepository.GetAsync(id); var post = await _postRepository.GetAsync(id);
// Check if user is author or has permission // Check if user is author or has permission
if (post.UserId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish")) if (post.Author != _currentUser.Name && !await AuthorizationService.IsGrantedAsync("App.BlogManagement.Publish"))
{ {
throw new Volo.Abp.Authorization.AbpAuthorizationException(); throw new Volo.Abp.Authorization.AbpAuthorizationException();
} }

View file

@ -13,7 +13,6 @@ using System.Linq;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using System.Text.Json; using System.Text.Json;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Sozsoft.Platform.Identity.Dto;
namespace Sozsoft.Platform.Public; namespace Sozsoft.Platform.Public;
@ -132,10 +131,6 @@ public class PublicAppService : PlatformAppService
var pageCategories = await _categoryRepository.GetListAsync(x => categoryIds.Contains(x.Id)); var pageCategories = await _categoryRepository.GetListAsync(x => categoryIds.Contains(x.Id));
var categoryDict = pageCategories.ToDictionary(x => x.Id, x => x); var categoryDict = pageCategories.ToDictionary(x => x.Id, x => x);
var userIds = pagedPosts.Select(x => x.UserId).Distinct().ToList();
var pageEmployees = await _identityUserRepository.GetListByIdsAsync(userIds);
var employeeDict = pageEmployees.ToDictionary(x => x.Id, x => x);
// Post DTO mapping // Post DTO mapping
var postDtos = pagedPosts.Select(post => var postDtos = pagedPosts.Select(post =>
{ {
@ -145,11 +140,6 @@ public class PublicAppService : PlatformAppService
dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(c); dto.Category = ObjectMapper.Map<BlogCategory, BlogCategoryDto>(c);
} }
if (employeeDict.TryGetValue(post.UserId, out var e))
{
dto.User = ObjectMapper.Map<Volo.Abp.Identity.IdentityUser, UserInfoViewModel>(e);
}
return dto; return dto;
}).ToList(); }).ToList();

View file

@ -2910,7 +2910,7 @@
"DisplayName": "App.Definitions.WorkHour", "DisplayName": "App.Definitions.WorkHour",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",
@ -2919,7 +2919,7 @@
"DisplayName": "Create", "DisplayName": "Create",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",
@ -2928,7 +2928,7 @@
"DisplayName": "Update", "DisplayName": "Update",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",
@ -2937,7 +2937,7 @@
"DisplayName": "Delete", "DisplayName": "Delete",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",
@ -2946,7 +2946,7 @@
"DisplayName": "Export", "DisplayName": "Export",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",
@ -2955,7 +2955,7 @@
"DisplayName": "Import", "DisplayName": "Import",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",
@ -2964,7 +2964,7 @@
"DisplayName": "Note", "DisplayName": "Note",
"IsEnabled": true, "IsEnabled": true,
"MultiTenancySide": 3, "MultiTenancySide": 3,
"MenuGroup": "Kurs" "MenuGroup": "Erp|Kurs"
}, },
{ {
"GroupName": "App.Administration", "GroupName": "App.Administration",

View file

@ -16,7 +16,7 @@ public class BlogPost : FullAuditedEntity<Guid>
public Guid CategoryId { get; set; } public Guid CategoryId { get; set; }
public BlogCategory Category { get; set; } public BlogCategory Category { get; set; }
public Guid UserId { get; set; } public string Author { get; set; }
public int? ViewCount { get; set; } = 0; public int? ViewCount { get; set; } = 0;
public int? LikeCount { get; set; } = 0; public int? LikeCount { get; set; } = 0;

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations namespace Sozsoft.Platform.Migrations
{ {
[DbContext(typeof(PlatformDbContext))] [DbContext(typeof(PlatformDbContext))]
[Migration("20260310211156_Initial")] [Migration("20260311115619_Initial")]
partial class Initial partial class Initial
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -796,6 +796,9 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id") b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier"); .HasColumnType("uniqueidentifier");
b.Property<string>("Author")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("CategoryId") b.Property<Guid>("CategoryId")
.HasColumnType("uniqueidentifier"); .HasColumnType("uniqueidentifier");
@ -872,9 +875,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("nvarchar(256)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<int?>("ViewCount") b.Property<int?>("ViewCount")
.HasColumnType("int"); .HasColumnType("int");

View file

@ -1850,7 +1850,7 @@ namespace Sozsoft.Platform.Migrations
CoverImage = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true), CoverImage = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
ReadTime = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true), ReadTime = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), Author = table.Column<string>(type: "nvarchar(max)", nullable: true),
ViewCount = table.Column<int>(type: "int", nullable: true), ViewCount = table.Column<int>(type: "int", nullable: true),
LikeCount = table.Column<int>(type: "int", nullable: true), LikeCount = table.Column<int>(type: "int", nullable: true),
CommentCount = table.Column<int>(type: "int", nullable: true), CommentCount = table.Column<int>(type: "int", nullable: true),

View file

@ -793,6 +793,9 @@ namespace Sozsoft.Platform.Migrations
b.Property<Guid>("Id") b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier"); .HasColumnType("uniqueidentifier");
b.Property<string>("Author")
.HasColumnType("nvarchar(max)");
b.Property<Guid>("CategoryId") b.Property<Guid>("CategoryId")
.HasColumnType("uniqueidentifier"); .HasColumnType("uniqueidentifier");
@ -869,9 +872,6 @@ namespace Sozsoft.Platform.Migrations
.HasMaxLength(256) .HasMaxLength(256)
.HasColumnType("nvarchar(256)"); .HasColumnType("nvarchar(256)");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.Property<int?>("ViewCount") b.Property<int?>("ViewCount")
.HasColumnType("int"); .HasColumnType("int");

View file

@ -202,7 +202,7 @@
"Summary": "blog.posts.ai.excerpt", "Summary": "blog.posts.ai.excerpt",
"CoverImage": "https://images.pexels.com/photos/8386434/pexels-photo-8386434.jpeg?auto=compress&cs=tinysrgb&w=1920", "CoverImage": "https://images.pexels.com/photos/8386434/pexels-photo-8386434.jpeg?auto=compress&cs=tinysrgb&w=1920",
"CategoryName": "blog.categories.technology", "CategoryName": "blog.categories.technology",
"UserName": "system@sozsoft.com" "Author": "system@sozsoft.com"
}, },
{ {
"Title": "blog.posts.web.title", "Title": "blog.posts.web.title",
@ -213,7 +213,7 @@
"Summary": "blog.posts.web.excerpt", "Summary": "blog.posts.web.excerpt",
"CoverImage": "https://images.pexels.com/photos/11035471/pexels-photo-11035471.jpeg?auto=compress&cs=tinysrgb&w=1920", "CoverImage": "https://images.pexels.com/photos/11035471/pexels-photo-11035471.jpeg?auto=compress&cs=tinysrgb&w=1920",
"CategoryName": "blog.categories.webdev", "CategoryName": "blog.categories.webdev",
"UserName": "system@sozsoft.com" "Author": "system@sozsoft.com"
}, },
{ {
"Title": "blog.posts.security.title", "Title": "blog.posts.security.title",
@ -224,7 +224,7 @@
"Summary": "blog.posts.security.excerpt", "Summary": "blog.posts.security.excerpt",
"CoverImage": "https://images.pexels.com/photos/5380642/pexels-photo-5380642.jpeg?auto=compress&cs=tinysrgb&w=1920", "CoverImage": "https://images.pexels.com/photos/5380642/pexels-photo-5380642.jpeg?auto=compress&cs=tinysrgb&w=1920",
"CategoryName": "blog.categories.security", "CategoryName": "blog.categories.security",
"UserName": "system@sozsoft.com" "Author": "system@sozsoft.com"
}, },
{ {
"Title": "blog.posts.mobile.title", "Title": "blog.posts.mobile.title",
@ -235,7 +235,7 @@
"ReadTime": "4 dk", "ReadTime": "4 dk",
"CoverImage": "https://images.pexels.com/photos/13017583/pexels-photo-13017583.jpeg?auto=compress&cs=tinysrgb&w=1920", "CoverImage": "https://images.pexels.com/photos/13017583/pexels-photo-13017583.jpeg?auto=compress&cs=tinysrgb&w=1920",
"CategoryName": "blog.categories.mobile", "CategoryName": "blog.categories.mobile",
"UserName": "system@sozsoft.com" "Author": "system@sozsoft.com"
}, },
{ {
"Title": "blog.posts.database.title", "Title": "blog.posts.database.title",
@ -246,7 +246,7 @@
"ReadTime": "8 dk", "ReadTime": "8 dk",
"CoverImage": "https://images.pexels.com/photos/325229/pexels-photo-325229.jpeg?auto=compress&cs=tinysrgb&w=1920", "CoverImage": "https://images.pexels.com/photos/325229/pexels-photo-325229.jpeg?auto=compress&cs=tinysrgb&w=1920",
"CategoryName": "blog.categories.database", "CategoryName": "blog.categories.database",
"UserName": "system@sozsoft.com" "Author": "system@sozsoft.com"
}, },
{ {
"Title": "blog.posts.digital.title", "Title": "blog.posts.digital.title",
@ -257,7 +257,7 @@
"ReadTime": "6 dk", "ReadTime": "6 dk",
"CoverImage": "https://images.pexels.com/photos/7681091/pexels-photo-7681091.jpeg?auto=compress&cs=tinysrgb&w=1920", "CoverImage": "https://images.pexels.com/photos/7681091/pexels-photo-7681091.jpeg?auto=compress&cs=tinysrgb&w=1920",
"CategoryName": "blog.categories.digital", "CategoryName": "blog.categories.digital",
"UserName": "system@sozsoft.com" "Author": "system@sozsoft.com"
} }
], ],
"GlobalSearch": [ "GlobalSearch": [

View file

@ -118,7 +118,7 @@ public class BlogPostSeedDto
public string Summary { get; set; } public string Summary { get; set; }
public string CoverImage { get; set; } public string CoverImage { get; set; }
public string CategoryName { get; set; } public string CategoryName { get; set; }
public string UserName { get; set; } public string Author { get; set; }
public bool IsPublished { get; set; } public bool IsPublished { get; set; }
public DateTime PublishedAt { get; set; } public DateTime PublishedAt { get; set; }
} }
@ -669,9 +669,8 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
if (!exists) if (!exists)
{ {
var category = await _blogCategoryRepository.FirstOrDefaultAsync(x => x.Name == item.CategoryName); var category = await _blogCategoryRepository.FirstOrDefaultAsync(x => x.Name == item.CategoryName);
var user = await _repositoryUser.FindByNormalizedUserNameAsync(item.UserName);
if (category != null && user != null) if (category != null)
{ {
await _blogPostsRepository.InsertAsync(new BlogPost await _blogPostsRepository.InsertAsync(new BlogPost
{ {
@ -683,7 +682,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
CoverImage = item.CoverImage, CoverImage = item.CoverImage,
ReadTime = item.ReadTime, ReadTime = item.ReadTime,
CategoryId = category.Id, CategoryId = category.Id,
UserId = user.Id, Author = item.Author,
IsPublished = true, IsPublished = true,
PublishedAt = DateTime.UtcNow PublishedAt = DateTime.UtcNow
}); });

View file

@ -8,12 +8,7 @@ export interface BlogPost {
contentEn?: string contentEn?: string
summary: string summary: string
coverImage?: string coverImage?: string
userid: string author: string
user: {
id: string
name: string
username: string
}
category: { category: {
id: string id: string
name: string name: string
@ -54,6 +49,7 @@ export interface CreateUpdateBlogPostDto {
contentEn: string contentEn: string
summary: string summary: string
categoryId: string categoryId: string
author: string
tags: string[] tags: string[]
coverImage?: string coverImage?: string
isPublished: boolean isPublished: boolean
@ -76,6 +72,6 @@ export interface BlogListParams {
categoryId?: string categoryId?: string
tag?: string tag?: string
search?: string search?: string
employeeId?: string author?: string
sortBy?: 'latest' | 'popular' | 'trending' sortBy?: 'latest' | 'popular' | 'trending'
} }

View file

@ -56,9 +56,13 @@ function RolesPermission({
const filteredGroups = data.groups const filteredGroups = data.groups
.map((group: any) => { .map((group: any) => {
const filteredPermissions = group.permissions.filter( const filteredPermissions = group.permissions.filter((perm: any) => {
(perm: any) => Array.isArray(perm.menuGroup) && perm.menuGroup.includes(tenantGroup), if (!perm.menuGroup) return false
) const groups = typeof perm.menuGroup === 'string'
? perm.menuGroup.split('|').map((g: string) => g.trim())
: perm.menuGroup
return groups.includes(tenantGroup)
})
return { ...group, permissions: filteredPermissions } return { ...group, permissions: filteredPermissions }
}) })

View file

@ -195,7 +195,7 @@ const Blog = () => {
<div className="flex items-center text-sm text-gray-500 space-x-4"> <div className="flex items-center text-sm text-gray-500 space-x-4">
<div className="flex items-center"> <div className="flex items-center">
<FaUser size={16} className="mr-1" /> <FaUser size={16} className="mr-1" />
{post.user.username} {post.author}
</div> </div>
<div className="flex items-center"> <div className="flex items-center">
<FaCalendarAlt size={16} className="mr-1" /> <FaCalendarAlt size={16} className="mr-1" />

View file

@ -12,11 +12,7 @@ import { APP_NAME } from '@/constants/app.constant'
interface PostData { interface PostData {
image?: string image?: string
user?: { author?: string
id: string
name: string
username: string
}
} }
const BlogDetail: React.FC = () => { const BlogDetail: React.FC = () => {
@ -39,7 +35,7 @@ const BlogDetail: React.FC = () => {
setBlogPost(response) setBlogPost(response)
setPostData({ setPostData({
image: response.coverImage, image: response.coverImage,
user: response.user, author: response.author,
}) })
} else { } else {
setError('Blog post ID is missing.') setError('Blog post ID is missing.')
@ -107,7 +103,7 @@ const BlogDetail: React.FC = () => {
</h1> </h1>
<div className="flex items-center text-sm text-gray-500 space-x-4 mb-8"> <div className="flex items-center text-sm text-gray-500 space-x-4 mb-8">
<div className="flex items-center"> <div className="flex items-center">
<span>{postData.user?.username}</span> <span>{postData.author}</span>
</div> </div>
<div className="flex items-center"> <div className="flex items-center">
{blogPost.publishedAt && showDbDateAsIs(blogPost.publishedAt)} {blogPost.publishedAt && showDbDateAsIs(blogPost.publishedAt)}