Blog Türkçe İngilizce Content

This commit is contained in:
Sedat Öztürk 2025-06-22 15:44:11 +03:00
parent a663cc0079
commit d0d255f41e
18 changed files with 112 additions and 70 deletions

View file

@ -8,7 +8,8 @@ namespace Kurs.Platform.Blog
{
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string ContentTr { get; set; }
public string ContentEn { get; set; }
public string Summary { get; set; }
public string CoverImage { get; set; }
@ -44,7 +45,8 @@ namespace Kurs.Platform.Blog
{
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string ContentTr { get; set; }
public string ContentEn { get; set; }
public string Summary { get; set; }
public string ReadTime { get; set; }
public string CoverImage { get; set; }
@ -65,7 +67,8 @@ namespace Kurs.Platform.Blog
public string Summary { get; set; }
public string ReadTime { get; set; }
public string CoverImage { get; set; }
public string Content { get; set; }
public string ContentTr { get; set; }
public string ContentEn { get; set; }
public BlogCategoryDto Category { get; set; }
public AuthorDto Author { get; set; }

View file

@ -126,7 +126,8 @@ namespace Kurs.Platform.Blog
GuidGenerator.Create(),
input.Title,
input.Slug,
input.Content,
input.ContentTr,
input.ContentEn,
input.Summary,
input.ReadTime,
input.CoverImage,
@ -160,7 +161,8 @@ namespace Kurs.Platform.Blog
post.Slug = input.Slug;
post.Summary = input.Summary;
post.CoverImage = input.CoverImage;
post.Content = input.Content;
post.ContentTr = input.ContentTr;
post.ContentEn = input.ContentEn;
if (input.IsPublished) post.Publish(); else post.Unpublish();

View file

@ -582,7 +582,8 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency
item.Id,
item.Title,
item.Slug,
item.Content,
item.ContentTr,
item.ContentEn,
item.Summary,
item.ReadTime,
item.CoverImage,

File diff suppressed because one or more lines are too long

View file

@ -215,7 +215,8 @@ public class BlogPostSeedDto
public Guid Id { get; set; }
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string ContentTr { get; set; }
public string ContentEn { get; set; }
public string ReadTime { get; set; }
public string Summary { get; set; }
public string CoverImage { get; set; }

View file

@ -10,7 +10,8 @@ namespace Kurs.Platform.Blog
public string Title { get; set; }
public string Slug { get; set; }
public string Content { get; set; }
public string ContentTr { get; set; }
public string ContentEn { get; set; }
public string Summary { get; set; }
public string CoverImage { get; set; }
public string ReadTime { get; set; }
@ -35,7 +36,8 @@ namespace Kurs.Platform.Blog
Guid id,
string title,
string slug,
string content,
string contentTr,
string contentEn,
string summary,
string readTime,
string coverImage,
@ -45,7 +47,8 @@ namespace Kurs.Platform.Blog
{
Title = title;
Slug = slug;
Content = content;
ContentTr = contentTr;
ContentEn = contentEn;
Summary = summary;
ReadTime = readTime;
CoverImage = coverImage;

View file

@ -415,7 +415,8 @@ public class PlatformDbContext :
b.Property(x => x.Title).IsRequired().HasMaxLength(256);
b.Property(x => x.Slug).IsRequired().HasMaxLength(256);
b.Property(x => x.Summary).IsRequired().HasMaxLength(512);
b.Property(x => x.Content).IsRequired();
b.Property(x => x.ContentTr).IsRequired();
b.Property(x => x.ContentEn).IsRequired();
b.Property(x => x.CoverImage).HasMaxLength(512);
b.HasIndex(x => x.Slug);

View file

@ -13,8 +13,8 @@ using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20250622112214_AddBlogEntities")]
partial class AddBlogEntities
[Migration("20250622123512_AddBlog")]
partial class AddBlog
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -746,7 +746,11 @@ namespace Kurs.Platform.Migrations
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
b.Property<string>("ContentEn")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ContentTr")
.IsRequired()
.HasColumnType("nvarchar(max)");

View file

@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace Kurs.Platform.Migrations
{
/// <inheritdoc />
public partial class AddBlogEntities : Migration
public partial class AddBlog : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -45,7 +45,8 @@ namespace Kurs.Platform.Migrations
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Title = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Slug = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Content = table.Column<string>(type: "nvarchar(max)", nullable: false),
ContentTr = table.Column<string>(type: "nvarchar(max)", nullable: false),
ContentEn = table.Column<string>(type: "nvarchar(max)", nullable: false),
Summary = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: false),
CoverImage = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
ReadTime = table.Column<string>(type: "nvarchar(max)", nullable: true),

View file

@ -743,7 +743,11 @@ namespace Kurs.Platform.Migrations
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<string>("Content")
b.Property<string>("ContentEn")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ContentTr")
.IsRequired()
.HasColumnType("nvarchar(max)");

View file

@ -30,12 +30,12 @@ function App() {
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/products" element={<Products />} />
<Route path="/services" element={<Services />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />} />
<Route path="/contact" element={<Contact />} />
<Route path="/blog/:id" element={<BlogDetail />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<NotFound />} />
</Routes>
</Layout>

File diff suppressed because one or more lines are too long

View file

@ -16,7 +16,7 @@ interface PostData {
const BlogDetail: React.FC = () => {
const { id } = useParams<{ id: string }>();
const { t } = useLanguage();
const { language, setLanguage, t } = useLanguage();
const [blogPost, setBlogPost] = useState<BlogPost | null>(null);
const [postData, setPostData] = useState<PostData | null>(null);
const [loading, setLoading] = useState(true);
@ -103,7 +103,7 @@ const BlogDetail: React.FC = () => {
})}
</div>
</div>
<div className="prose max-w-none text-gray-800" dangerouslySetInnerHTML={{ __html: t(blogPost.content!!) || "" }} />
<div className="prose max-w-none text-gray-800" dangerouslySetInnerHTML={{ __html: language == "tr" ? t(blogPost.contentTr!!) : t(blogPost.contentEn!!) }} />
</div>
</div>
);

View file

@ -4,7 +4,8 @@ export interface BlogPost {
id: string;
title: string;
slug: string;
content?: string;
contentTr?: string;
contentEn?: string;
summary: string;
readTime: string;
coverImage?: string;
@ -58,7 +59,8 @@ export interface BlogComment {
export interface CreateBlogPostRequest {
title: string;
slug: string;
content: string;
contentTr: string;
contentEn: string;
summary: string;
categoryId: string;
tags: string[];

View file

@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
"revision": "0.6hosm5icco8"
"revision": "0.pd7p0avqcno"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

View file

@ -63,12 +63,6 @@ const adminRoutes: Routes = [
component: lazy(() => import('@/views/blog/BlogManagement')),
authority: [],
},
{
key: ROUTES_ENUM.admin.forum.management,
path: ROUTES_ENUM.admin.forum.management,
component: lazy(() => import('@/views/forum/AdminView')),
authority: [],
},
]
export { adminRoutes }

View file

@ -4,7 +4,8 @@ export interface BlogPost {
id: string
title: string
slug: string
content?: string
contentTr?: string
contentEn?: string
summary: string
coverImage?: string
author: {
@ -58,7 +59,8 @@ export interface BlogComment {
export interface CreateUpdateBlogPostDto {
title: string
slug: string
content: string
contentTr: string
contentEn: string
summary: string
categoryId: string
tags: string[]

View file

@ -31,11 +31,14 @@ import THead from '@/components/ui/Table/THead'
import TBody from '@/components/ui/Table/TBody'
import Td from '@/components/ui/Table/Td'
import { SelectBoxOption } from '@/shared/types'
import { Checkbox } from '@/components/ui'
import { Checkbox, Tabs } from '@/components/ui'
import { Helmet } from 'react-helmet'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { ConfirmDialog } from '@/components/shared'
import { useStoreState } from '@/store/store'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import TabContent from '@/components/ui/Tabs/TabContent'
const validationSchema = Yup.object().shape({
title: Yup.string().required(),
@ -84,8 +87,8 @@ const BlogManagement = () => {
blogService.getPosts({ pageSize: 100 }),
blogService.getCategories(),
])
setCategories(categoriesData.filter(a=>a.name.startsWith("blog")))
setPosts(postsData.items.filter(a=> a.title.startsWith("blog")))
setCategories(categoriesData.filter((a) => a.name.startsWith('blog')))
setPosts(postsData.items.filter((a) => a.title.startsWith('blog')))
} catch (error) {
toast.push(
<Notification title="Hata" type="danger">
@ -139,7 +142,8 @@ const BlogManagement = () => {
const data: CreateUpdateBlogPostDto = {
title: values.title,
slug: values.slug,
content: values.content,
contentTr: values.contentTr,
contentEn: values.contentEn,
summary: values.summary,
categoryId: values.categoryId,
tags: values.tags ? values.tags.split(',').map((t: string) => t.trim()) : [],
@ -311,7 +315,8 @@ const BlogManagement = () => {
title: editingPost.title,
slug: editingPost.slug,
summary: editingPost.summary,
content: editingPost.content,
contentTr: editingPost.contentTr,
contentEn: editingPost.contentEn,
categoryId: editingPost.category.id,
tags: editingPost.tags.join(', '),
coverImage: editingPost.coverImage || '',
@ -389,7 +394,7 @@ const BlogManagement = () => {
</div>
{activeTab === 'posts' ? (
<Table compact >
<Table compact>
<THead>
<Tr>
<Th>{translate('::blog.posts.post.title')}</Th>
@ -641,19 +646,44 @@ const BlogManagement = () => {
<Field type="text" name="coverImage" component={Input} />
</FormItem>
<FormItem
label={translate('::blog.posts.post.content')}
asterisk
invalid={!!errors.content}
errorMessage={errors.content}
>
<ReactQuill
theme="snow"
value={values.content}
onChange={(val: string) => setFieldValue('content', val)}
style={{ height: '300px', marginBottom: '50px' }}
/>
</FormItem>
<Tabs defaultValue="tr" variant="pill">
<TabList className="flex-wrap border-b mb-4 bg-slate-50 rounded-t">
<TabNav value="tr">Türkçe</TabNav>
<TabNav value="en">English</TabNav>
</TabList>
<TabContent value="tr">
<FormItem
label={translate('::blog.posts.post.content')}
asterisk
invalid={!!errors.contentTr}
errorMessage={errors.contentTr}
>
<ReactQuill
theme="snow"
value={values.contentTr}
onChange={(val: string) => setFieldValue('contentTr', val)}
style={{ height: '300px', marginBottom: '50px' }}
/>
</FormItem>
</TabContent>
<TabContent value="en">
<FormItem
label={translate('::blog.posts.post.content')}
asterisk
invalid={!!errors.contentEn}
errorMessage={errors.contentEn}
>
<ReactQuill
theme="snow"
value={values.contentEn}
onChange={(val: string) => setFieldValue('contentEn', val)}
style={{ height: '300px', marginBottom: '50px' }}
/>
</FormItem>
</TabContent>
</Tabs>
<FormItem
label={translate('::blog.posts.post.status')}