From 6157b9b320c6298f2d0e50c900b3172ef19f06ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Fri, 27 Jun 2025 18:00:47 +0300 Subject: [PATCH] =?UTF-8?q?Seeder=20g=C3=BCncellemesi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Blog/BlogAppService.cs | 11 +- .../Seeds/ListFormsSeeder.cs | 436 +++++++++++------- .../Seeds/PlatformDataSeeder.cs | 4 +- .../Seeds/SeederData.json | 222 +++++++++ .../Seeds/SeederDto.cs | 2 + .../Kurs.Platform.Domain/Entities/BlogPost.cs | 5 +- ui/dev-dist/sw.js | 2 +- .../components/layouts/AuthLayout/Simple.tsx | 2 +- .../HorizontalMenuIcon.tsx | 2 +- ui/src/main.tsx | 3 +- ui/src/views/forum/admin/AdminView.tsx | 10 +- .../views/forum/admin/CategoryManagement.tsx | 26 +- ui/src/views/forum/admin/Dashboard.tsx | 20 +- ui/src/views/forum/admin/PostManagement.tsx | 18 +- ui/src/views/forum/admin/TopicManagement.tsx | 22 +- ui/src/views/forum/forum/CreatePostModal.tsx | 41 +- ui/src/views/forum/forum/CreateTopicModal.tsx | 170 ++++--- ui/src/views/forum/forum/ForumPostCard.tsx | 22 +- ui/src/views/forum/forum/ForumTopicCard.tsx | 4 +- ui/src/views/forum/forum/ForumView.tsx | 10 +- ui/src/views/list/Grid.tsx | 2 +- 21 files changed, 700 insertions(+), 334 deletions(-) diff --git a/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs b/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs index 26383428..edfd11a0 100644 --- a/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs +++ b/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs @@ -131,16 +131,11 @@ namespace Kurs.Platform.Blog input.CoverImage, input.CategoryId, _currentUser.Id.Value, - CurrentTenant.Id + true, + DateTime.UtcNow, + (Guid?)CurrentTenant.Id ); - post.CoverImage = input.CoverImage; - - if (input.IsPublished) - { - post.Publish(); - } - await _postRepository.InsertAsync(post, autoSave: true); return await GetPostAsync(post.Id); diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs index ed3cb3ea..5ce54202 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormsSeeder.cs @@ -440,26 +440,26 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency { new() { Order=1, ColCount=1, ColSpan=2, ItemType="group", Items = [ - new EditingFormItemDto { Order=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=2, DataField="InstitutionName", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=2, DataField="InstitutionName", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=3, DataField="VknTckn", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, - new EditingFormItemDto { Order=4, DataField="TaxOffice", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=4, DataField="TaxOffice", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=5, DataField="Mobile", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, new EditingFormItemDto { Order=6, DataField="Phone", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxNumberBox }, - new EditingFormItemDto { Order=7, DataField="Fax", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=7, DataField="Fax", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=8, DataField="IsActive", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, ] }, new() { Order=2, ColCount=1, ColSpan=2, ItemType="group", Items = [ - new EditingFormItemDto { Order=1, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=2, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=1, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=2, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=3, DataField="Country", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=4, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=5, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=6, DataField="PostalCode", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=7, DataField="Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=8, DataField="Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=4, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=5, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=6, DataField="PostalCode", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=7, DataField="Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=8, DataField="Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, ] } }), @@ -3089,7 +3089,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency new EditingFormItemDto { Order = 1, DataField = "CultureName", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 2, DataField = "Name", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 3, DataField = "ListFormCode", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order = 4, DataField = "ListFormType", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 4, DataField = "ListFormType", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 5, DataField = "SelectCommandType", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 6, DataField = "SelectCommand", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 7, DataField = "TableName", ColSpan = 2, IsRequired = false, EditorType2=EditorTypes.dxTextBox }, @@ -7742,26 +7742,26 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency new() { Order=1, ColCount=1, ColSpan=2, ItemType="group", Items = [ new EditingFormItemDto { Order=1, DataField="TenantId", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=2, DataField="Code", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=3, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=4, DataField="VknTckn", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=5, DataField="TaxOffice", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=2, DataField="Code", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=3, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=4, DataField="VknTckn", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, + new EditingFormItemDto { Order=5, DataField="TaxOffice", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=6, DataField="Mobile", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxNumberBox }, new EditingFormItemDto { Order=7, DataField="Phone", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxNumberBox }, - new EditingFormItemDto { Order=8, DataField="Fax", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=8, DataField="Fax", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=9, DataField="IsActive", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, ] }, new() { Order=2, ColCount=1, ColSpan=2, ItemType="group", Items = [ - new EditingFormItemDto { Order=1, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=2, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=1, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=2, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=3, DataField="Country", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=4, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=5, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=6, DataField="PostalCode", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=7, DataField="Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=8, DataField="Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=4, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=5, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=6, DataField="PostalCode", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=7, DataField="Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=8, DataField="Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, ] } }), @@ -8389,13 +8389,13 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency { new() { Order=1, ColCount=1, ColSpan=2, ItemType="group", Items = [ - new EditingFormItemDto { Order=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=2, DataField="ValueType", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=2, DataField="ValueType", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions = "{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order=3, DataField="Required", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, new EditingFormItemDto { Order=4, DataField="IsStatic", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox }, - new EditingFormItemDto { Order=5, DataField="Regex", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=6, DataField="RegexDescription", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, - new EditingFormItemDto { Order=7, DataField="Description", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" }, + new EditingFormItemDto { Order=5, DataField="Regex", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=6, DataField="RegexDescription", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=7, DataField="Description", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox }, ] } }), @@ -8760,24 +8760,24 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency }), EditingFormJson = JsonSerializer.Serialize(new List { - new() - { - Order = 1, - ColCount = 1, - ColSpan = 2, - ItemType = "group", - Items = - [ - new EditingFormItemDto + new() { Order = 1, - DataField = "Name", + ColCount = 1, ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox + ItemType = "group", + Items = + [ + new EditingFormItemDto + { + Order = 1, + DataField = "Name", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + } + ] } - ] - } }), InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { @@ -8940,32 +8940,32 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency }), EditingFormJson = JsonSerializer.Serialize(new List { - new() - { - Order = 1, - ColCount = 1, - ColSpan = 2, - ItemType = "group", - Items = - [ - new EditingFormItemDto + new() { Order = 1, - DataField = "Name", + ColCount = 1, ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox - }, - new EditingFormItemDto - { - Order = 2, - DataField = "Category", - ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox + ItemType = "group", + Items = + [ + new EditingFormItemDto + { + Order = 1, + DataField = "Name", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + }, + new EditingFormItemDto + { + Order = 2, + DataField = "Category", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + } + ] } - ] - } }), InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { @@ -9154,49 +9154,49 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency }), EditingFormJson = JsonSerializer.Serialize(new List { - new() - { - Order = 1, - ColCount = 1, - ColSpan = 2, - ItemType = "group", - Items = - [ - new EditingFormItemDto + new() { Order = 1, - DataField = "Title", + ColCount = 1, ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox - }, - new EditingFormItemDto - { - Order = 2, - DataField = "Abbreviation", - ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox + ItemType = "group", + Items = + [ + new EditingFormItemDto + { + Order = 1, + DataField = "Title", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + }, + new EditingFormItemDto + { + Order = 2, + DataField = "Abbreviation", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + } + ] } - ] - } }), InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { - new() - { - FieldName = "CreationTime", - FieldDbType = DbType.DateTime, - Value = "@NOW", - CustomValueType = FieldCustomValueTypeEnum.CustomKey - }, - new() - { - FieldName = "CreatorId", - FieldDbType = DbType.Guid, - Value = "@USERID", - CustomValueType = FieldCustomValueTypeEnum.CustomKey - } + new() + { + FieldName = "CreationTime", + FieldDbType = DbType.DateTime, + Value = "@NOW", + CustomValueType = FieldCustomValueTypeEnum.CustomKey + }, + new() + { + FieldName = "CreatorId", + FieldDbType = DbType.Guid, + Value = "@USERID", + CustomValueType = FieldCustomValueTypeEnum.CustomKey + } }) }); @@ -9370,74 +9370,74 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency }), EditingFormJson = JsonSerializer.Serialize(new List { - new() - { - Order = 1, - ColCount = 1, - ColSpan = 2, - ItemType = "group", - Items = - [ - new EditingFormItemDto - { - Order = 1, - DataField = "Code", - ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox - }, - new EditingFormItemDto - { - Order = 2, - DataField = "Symbol", - ColSpan = 2, - IsRequired = false, - EditorType2 = EditorTypes.dxTextBox - }, - new EditingFormItemDto - { - Order = 3, - DataField = "Name", - ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxTextBox - }, - new EditingFormItemDto - { - Order = 4, - DataField = "Rate", - ColSpan = 2, - IsRequired = true, - EditorType2 = EditorTypes.dxNumberBox - }, - new EditingFormItemDto - { - Order = 5, - DataField = "IsActive", - ColSpan = 2, - IsRequired = false, - EditorType2 = EditorTypes.dxCheckBox - } - ] - } + new() + { + Order = 1, + ColCount = 1, + ColSpan = 2, + ItemType = "group", + Items = + [ + new EditingFormItemDto + { + Order = 1, + DataField = "Code", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + }, + new EditingFormItemDto + { + Order = 2, + DataField = "Symbol", + ColSpan = 2, + IsRequired = false, + EditorType2 = EditorTypes.dxTextBox + }, + new EditingFormItemDto + { + Order = 3, + DataField = "Name", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxTextBox + }, + new EditingFormItemDto + { + Order = 4, + DataField = "Rate", + ColSpan = 2, + IsRequired = true, + EditorType2 = EditorTypes.dxNumberBox + }, + new EditingFormItemDto + { + Order = 5, + DataField = "IsActive", + ColSpan = 2, + IsRequired = false, + EditorType2 = EditorTypes.dxCheckBox + } + ] + } }), InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new[] - { - new FieldsDefaultValue { - FieldName = "CreationTime", - FieldDbType = DbType.DateTime, - Value = "@NOW", - CustomValueType = FieldCustomValueTypeEnum.CustomKey - }, - new FieldsDefaultValue - { - FieldName = "CreatorId", - FieldDbType = DbType.Guid, - Value = "@USERID", - CustomValueType = FieldCustomValueTypeEnum.CustomKey - } - }) + new FieldsDefaultValue + { + FieldName = "CreationTime", + FieldDbType = DbType.DateTime, + Value = "@NOW", + CustomValueType = FieldCustomValueTypeEnum.CustomKey + }, + new FieldsDefaultValue + { + FieldName = "CreatorId", + FieldDbType = DbType.Guid, + Value = "@USERID", + CustomValueType = FieldCustomValueTypeEnum.CustomKey + } + }) }); #region Currency Fields @@ -9860,7 +9860,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency [ new EditingFormItemDto { Order = 1, DataField = "Code", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 2, DataField = "Name", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextBox }, - new EditingFormItemDto { Order = 3, DataField = "GroupName", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 3, DataField = "GroupName", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 4, DataField = "CurrencyCode", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 5, DataField = "PhoneCode", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxNumberBox }, new EditingFormItemDto { Order = 6, DataField = "TaxLabel", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxTextBox }, @@ -10195,7 +10195,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency [ new EditingFormItemDto { Order = 1, DataField = "Name", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 2, DataField = "Code", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextBox }, - new EditingFormItemDto { Order = 3, DataField = "CountryCode", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox } + new EditingFormItemDto { Order = 3, DataField = "CountryCode", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" } ] } }), @@ -10797,9 +10797,9 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency ItemType = "group", Items = [ - new EditingFormItemDto { Order = 1, DataField = "Name", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 1, DataField = "Name", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 2, DataField = "Slug", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextBox }, - new EditingFormItemDto { Order = 3, DataField = "Description", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 3, DataField = "Description", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 4, DataField = "Icon", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 5, DataField = "DisplayOrder", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxNumberBox }, new EditingFormItemDto { Order = 6, DataField = "IsActive", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxCheckBox } @@ -11111,12 +11111,12 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency ItemType = "group", Items = [ - new EditingFormItemDto { Order = 1, DataField = "Title", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 1, DataField = "Title", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 2, DataField = "Slug", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxTextBox }, - new EditingFormItemDto { Order = 3, DataField = "Summary", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 3, DataField = "Summary", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 4, DataField = "CoverImage", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxTextBox }, new EditingFormItemDto { Order = 5, DataField = "ReadTime", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxTextBox }, - new EditingFormItemDto { Order = 6, DataField = "CategoryId", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox }, + new EditingFormItemDto { Order = 6, DataField = "CategoryId", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxSelectBox, EditorOptions="{ \"showClearButton\" : true }" }, new EditingFormItemDto { Order = 7, DataField = "ViewCount", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxNumberBox }, new EditingFormItemDto { Order = 8, DataField = "LikeCount", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxNumberBox }, new EditingFormItemDto { Order = 9, DataField = "CommentCount", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxNumberBox }, @@ -11333,7 +11333,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency DisplayExpr = "Name", ValueExpr = "Key", LookupQuery = $"SELECT \"{DbTablePrefix}BlogCategories\".\"Id\" AS \"Key\", \"{DbTablePrefix}BlogCategories\".\"Name\" as \"Name\" FROM \"{DbTablePrefix}BlogCategories\" ORDER BY \"{DbTablePrefix}BlogCategories\".\"Name\"" - }), + }), PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto { C = AppCodes.BlogManagement.BlogPosts + ".Create", @@ -11365,13 +11365,55 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency }) }, new() + { + ListFormCode = listFormBlogPosts.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Int32, + FieldName = "LikeCount", + Width = 80, + ListOrderNo = 9, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.BlogManagement.BlogPosts + ".Create", + R = AppCodes.BlogManagement.BlogPosts, + U = AppCodes.BlogManagement.BlogPosts + ".Update", + E = true, + Deny = false + }) + }, + new() + { + ListFormCode = listFormBlogPosts.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.Int32, + FieldName = "CommentCount", + Width = 80, + ListOrderNo = 10, + Visible = true, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.BlogManagement.BlogPosts + ".Create", + R = AppCodes.BlogManagement.BlogPosts, + U = AppCodes.BlogManagement.BlogPosts + ".Update", + E = true, + Deny = false + }) + }, + new() { ListFormCode = listFormBlogPosts.ListFormCode, CultureName = LanguageCodes.En, SourceDbType = DbType.Boolean, FieldName = "IsPublished", Width = 80, - ListOrderNo = 9, + ListOrderNo = 10, Visible = true, IsActive = true, IsDeleted = false, @@ -11392,7 +11434,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency SourceDbType = DbType.DateTime, FieldName = "PublishedAt", Width = 120, - ListOrderNo = 10, + ListOrderNo = 11, Visible = true, IsActive = true, IsDeleted = false, @@ -11405,6 +11447,48 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency E = true, Deny = false }) + }, + new() + { + ListFormCode = listFormBlogPosts.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.DateTime, + FieldName = "ContentTr", + Width = 120, + ListOrderNo = 11, + Visible = false, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.BlogManagement.BlogPosts + ".Create", + R = AppCodes.BlogManagement.BlogPosts, + U = AppCodes.BlogManagement.BlogPosts + ".Update", + E = true, + Deny = false + }) + }, + new() + { + ListFormCode = listFormBlogPosts.ListFormCode, + CultureName = LanguageCodes.En, + SourceDbType = DbType.DateTime, + FieldName = "ContentEn", + Width = 120, + ListOrderNo = 12, + Visible = false, + IsActive = true, + IsDeleted = false, + AllowSearch = true, + PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto + { + C = AppCodes.BlogManagement.BlogPosts + ".Create", + R = AppCodes.BlogManagement.BlogPosts, + U = AppCodes.BlogManagement.BlogPosts + ".Update", + E = true, + Deny = false + }) } ]); #endregion diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs index 7e7998ab..fab645a4 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/PlatformDataSeeder.cs @@ -593,7 +593,9 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency item.ReadTime, item.CoverImage, item.CategoryId, - item.AuthorId + item.AuthorId, + true, + DateTime.UtcNow )); } } diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index fc2428eb..038aaeee 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -535,6 +535,228 @@ "en": "Forum", "tr": "Forum" }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.Dashboard", + "en": "Dashboard", + "tr": "Gösterge Paneli" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.Categories", + "en": "Categories", + "tr": "Kategoriler" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.Topics", + "en": "Topics", + "tr": "Konular" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.Posts", + "en": "Posts", + "tr": "Yazılar" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.Statistics", + "en": "Statistics", + "tr": "İstatistikler" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.TotalCategories", + "en": "Total Categories", + "tr": "Toplam Kategoriler" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.TotalTopics", + "en": "Total Topics", + "tr": "Toplam Konular" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.TotalPosts", + "en": "Total Posts", + "tr": "Toplam Yazılar" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.EngagementRate", + "en": "Engagement Rate", + "tr": "Katılım Oranı" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.RecentActivity", + "en": "Recent Activity", + "tr": "Son Etkinlik" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.GeneralDiscussion", + "en": "New topic created in General Discussion", + "tr": "Genel Tartışmada yeni konu oluşturuldu" + }, + { + "resourceName": "Platform", + "key": "App.Forum.CategoryManagement.Title", + "en": "Category Management", + "tr": "Kategori Yönetimi" + }, + { + "resourceName": "Platform", + "key": "App.Forum.CategoryManagement.AddCategory", + "en": "Add Category", + "tr": "Kategori Ekle" + }, + { + "resourceName": "Platform", + "key": "App.Forum.CategoryManagement.EditCategory", + "en": "Edit Category", + "tr": "Kategoriyi Düzenle" + }, + { + "resourceName": "Platform", + "key": "App.Forum.CategoryManagement.DeleteCategory", + "en": "Delete Category", + "tr": "Kategori Sil" + }, + { + "resourceName": "Platform", + "key": "App.Forum.CategoryManagement.Categories", + "en": "Categories", + "tr": "Kategoriler" + }, + { + "resourceName": "Platform", + "key": "App.Forum.CategoryManagement.Loadingcategories", + "en": "Loading categories...", + "tr": "Kategoriler Yükleniyor..." + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Title", + "en": "Topic Management", + "tr": "Konu Yönetimi" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.NewTopic", + "en": "New Topic", + "tr": "Yeni Konu" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.AddTopic", + "en": "Add Topic", + "tr": "Konu Ekle" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.EditTopic", + "en": "Edit Topic", + "tr": "Konu Düzenle" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.DeleteTopic", + "en": "Delete Topic", + "tr": "Konu Sil" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Searchtopics", + "en": "Search topics...", + "tr": "Konular arama..." + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Topics", + "en": "Topics", + "tr": "Konular" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Loadingtopics", + "en": "Loading topics...", + "tr": "Konular Yük" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Lastreplyby", + "en": "Last reply by", + "tr": "Son cevaplayan" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.Title", + "en": "Post Management", + "tr": "Yazı Yönetimi" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.NewPost", + "en": "New Post", + "tr": "Yeni Yazı" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.ReplytoTopic", + "en": "Reply to Topic", + "tr": "Konuya Cevap Ver" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.AddPost", + "en": "Add Post", + "tr": "Yazı Ekle" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.AcceptedAnswer", + "en": "Accepted Answer", + "tr": "Kabul Edilen Cevap" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.PostReply", + "en": "Post Reply", + "tr": "Yazı Cevabı" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.EditPost", + "en": "Edit Post", + "tr": "Yazıyı Düzenle" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.DeletePost", + "en": "Delete Post", + "tr": "Yazıyı Sil" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.Loadingtopics", + "en": "Loading posts...", + "tr": "Yazılar Yükleniyor..." + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.Postmarked", + "en": "Post marked as accepted answer", + "tr": "Cevap olarak işaretlenen yazı" + }, + { + "resourceName": "Platform", + "key": "App.Forum.Dashboard.FeatureRequests", + "en": "New category created: Feature Requests", + "tr": "Yeni kategori oluşturuldu: Özellik Talepleri" + }, { "resourceName": "Platform", "key": "App.Home", diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs index c090f03e..8ad8fab5 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederDto.cs @@ -224,6 +224,8 @@ public class BlogPostSeedDto public string CoverImage { get; set; } public Guid CategoryId { get; set; } public Guid AuthorId { get; set; } + public Boolean IsPublished { get; set; } + public DateTime PublishedAt { get; set; } } public class ForumCategorySeedDto diff --git a/api/src/Kurs.Platform.Domain/Entities/BlogPost.cs b/api/src/Kurs.Platform.Domain/Entities/BlogPost.cs index 7ded6478..2de7133c 100644 --- a/api/src/Kurs.Platform.Domain/Entities/BlogPost.cs +++ b/api/src/Kurs.Platform.Domain/Entities/BlogPost.cs @@ -42,6 +42,8 @@ public class BlogPost : FullAuditedAggregateRoot string coverImage, Guid categoryId, Guid authorId, + bool isPublished, + DateTime? publishedAt = null, Guid? tenantId = null) : base(id) { Title = title; @@ -53,12 +55,13 @@ public class BlogPost : FullAuditedAggregateRoot CoverImage = coverImage; CategoryId = categoryId; AuthorId = authorId; + IsPublished = isPublished; + PublishedAt = publishedAt; TenantId = tenantId; ViewCount = 0; LikeCount = 0; CommentCount = 0; - IsPublished = false; } public void Publish() diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js index a8edd63d..db7285b5 100644 --- a/ui/dev-dist/sw.js +++ b/ui/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.mj87dckq3bo" + "revision": "0.ru7ltd9thg8" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/ui/src/components/layouts/AuthLayout/Simple.tsx b/ui/src/components/layouts/AuthLayout/Simple.tsx index ba2a83ab..21c404f0 100644 --- a/ui/src/components/layouts/AuthLayout/Simple.tsx +++ b/ui/src/components/layouts/AuthLayout/Simple.tsx @@ -89,7 +89,7 @@ const Simple = ({ children, content, ...rest }: SimpleProps) => { return (
- +
{ return <> } - return {navigationIcon[icon]} + return {navigationIcon[icon]} } export default HorizontalMenuIcon diff --git a/ui/src/main.tsx b/ui/src/main.tsx index e1961bd8..536f836f 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -3,7 +3,8 @@ import ReactDOM from 'react-dom/client' import App from './App' import './index.css' import { UiEvalService } from './services/UiEvalService' -import 'devextreme-react/text-area'; +import 'devextreme-react/text-area' +import 'devextreme-react/html-editor' ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render() diff --git a/ui/src/views/forum/admin/AdminView.tsx b/ui/src/views/forum/admin/AdminView.tsx index 1ccbcc66..b5b07aa9 100644 --- a/ui/src/views/forum/admin/AdminView.tsx +++ b/ui/src/views/forum/admin/AdminView.tsx @@ -5,6 +5,7 @@ import { TopicManagement } from './TopicManagement' import { PostManagement } from './PostManagement' import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum' import { AdminStats } from './Dashboard' +import { useLocalization } from '@/utils/hooks/useLocalization' interface AdminViewProps { categories: ForumCategory[] @@ -74,12 +75,13 @@ export function AdminView({ onUnmarkPostAsAcceptedAnswer, }: AdminViewProps) { const [activeSection, setActiveSection] = useState('stats') + const { translate } = useLocalization(); const navigationItems = [ - { id: 'stats' as AdminSection, label: 'Dashboard', icon: BarChart3 }, - { id: 'categories' as AdminSection, label: 'Categories', icon: Folder }, - { id: 'topics' as AdminSection, label: 'Topics', icon: MessageSquare }, - { id: 'posts' as AdminSection, label: 'Posts', icon: FileText }, + { id: 'stats' as AdminSection, label: translate('::App.Forum.Dashboard.Dashboard'), icon: BarChart3 }, + { id: 'categories' as AdminSection, label: translate('::App.Forum.Dashboard.Categories'), icon: Folder }, + { id: 'topics' as AdminSection, label: translate('::App.Forum.Dashboard.Topics'), icon: MessageSquare }, + { id: 'posts' as AdminSection, label: translate('::App.Forum.Dashboard.Posts'), icon: FileText }, ] return ( diff --git a/ui/src/views/forum/admin/CategoryManagement.tsx b/ui/src/views/forum/admin/CategoryManagement.tsx index 0fae864c..9820c449 100644 --- a/ui/src/views/forum/admin/CategoryManagement.tsx +++ b/ui/src/views/forum/admin/CategoryManagement.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react' import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react' import { ForumCategory } from '@/proxy/forum/forum' import { useStoreState } from '@/store/store' +import { useLocalization } from '@/utils/hooks/useLocalization' interface CategoryManagementProps { categories: ForumCategory[] @@ -31,6 +32,7 @@ export function CategoryManagement({ onUpdateCategoryLockState, onUpdateCategoryActiveState, }: CategoryManagementProps) { + const { translate } = useLocalization() const { tenant } = useStoreState((state) => state.auth) const [showCreateForm, setShowCreateForm] = useState(false) const [editingCategory, setEditingCategory] = useState(null) @@ -42,7 +44,7 @@ export function CategoryManagement({ displayOrder: 0, isActive: true, isLocked: false, - tenantId: '' + tenantId: '', }) const [submitting, setSubmitting] = useState(false) @@ -55,7 +57,7 @@ export function CategoryManagement({ displayOrder: 0, isActive: true, isLocked: false, - tenantId: '' + tenantId: '', }) setShowCreateForm(false) setEditingCategory(null) @@ -90,7 +92,7 @@ export function CategoryManagement({ displayOrder: category.displayOrder, isActive: category.isActive, isLocked: category.isLocked, - tenantId: tenant.tenantId ?? '' + tenantId: tenant.tenantId ?? '', }) setShowCreateForm(true) } @@ -128,14 +130,16 @@ export function CategoryManagement({ return (
-

Category Management

+

+ {translate('::App.Forum.CategoryManagement.Title')} +

@@ -143,7 +147,9 @@ export function CategoryManagement({ {showCreateForm && (

- {editingCategory ? 'Edit Category' : 'Create New Category'} + {editingCategory + ? translate('::App.Forum.CategoryManagement.EditCategory') + : translate('::App.Forum.CategoryManagement.CreateCategory')}

@@ -251,13 +257,13 @@ export function CategoryManagement({ {/* Categories List */}
-

Categories ({categories.length})

+

{translate('::App.Forum.CategoryManagement.Categories')} ({categories.length})

{loading ? (
-

Loading categories...

+

{translate('::App.Forum.CategoryManagement.Loadingcategories')}

) : (
@@ -327,7 +333,7 @@ export function CategoryManagement({ @@ -335,7 +341,7 @@ export function CategoryManagement({ diff --git a/ui/src/views/forum/admin/Dashboard.tsx b/ui/src/views/forum/admin/Dashboard.tsx index 71669858..5ce2278e 100644 --- a/ui/src/views/forum/admin/Dashboard.tsx +++ b/ui/src/views/forum/admin/Dashboard.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Folder, MessageSquare, FileText, TrendingUp } from 'lucide-react'; import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'; +import { useLocalization } from '@/utils/hooks/useLocalization'; interface AdminStatsProps { categories: ForumCategory[]; @@ -9,6 +10,7 @@ interface AdminStatsProps { } export function AdminStats({ categories, topics, posts }: AdminStatsProps) { + const { translate } = useLocalization(); const totalCategories = categories.length; const activeCategories = categories.filter(c => c.isActive).length; const totalTopics = topics.length; @@ -18,28 +20,28 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) { const stats = [ { - title: 'Total Categories', + title: translate('::App.Forum.Dashboard.TotalCategories'), value: totalCategories, subtitle: `${activeCategories} active`, icon: Folder, color: 'bg-blue-500', }, { - title: 'Total Topics', + title: translate('::App.Forum.Dashboard.TotalTopics'), value: totalTopics, subtitle: `${solvedTopics} solved`, icon: MessageSquare, color: 'bg-emerald-500', }, { - title: 'Total Posts', + title: translate('::App.Forum.Dashboard.TotalPosts'), value: totalPosts, subtitle: `${acceptedAnswers} accepted answers`, icon: FileText, color: 'bg-orange-500', }, { - title: 'Engagement Rate', + title: translate('::App.Forum.Dashboard.EngagementRate'), value: totalTopics > 0 ? Math.round((totalPosts / totalTopics) * 100) / 100 : 0, subtitle: 'posts per topic', icon: TrendingUp, @@ -50,7 +52,7 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) { return (
-

Forum Statistics

+

{translate('::App.Forum.Dashboard.Statistics')}

{stats.map((stat, index) => { @@ -75,26 +77,26 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) { {/* Recent Activity */}
-

Recent Activity

+

{translate('::App.Forum.Dashboard.RecentActivity')}

-

New topic created in General Discussion

+

{translate('::App.Forum.Dashboard.GeneralDiscussion')}

2 hours ago

-

Post marked as accepted answer

+

{translate('::App.Forum.Dashboard.Postmarked')}

4 hours ago

-

New category created: Feature Requests

+

{translate('::App.Forum.Dashboard.FeatureRequests')}

1 day ago

diff --git a/ui/src/views/forum/admin/PostManagement.tsx b/ui/src/views/forum/admin/PostManagement.tsx index 688a394e..d851d878 100644 --- a/ui/src/views/forum/admin/PostManagement.tsx +++ b/ui/src/views/forum/admin/PostManagement.tsx @@ -4,6 +4,7 @@ import { ForumPost, ForumTopic } from '@/proxy/forum/forum' import ReactQuill from 'react-quill' import 'react-quill/dist/quill.snow.css' import { useStoreState } from '@/store/store' +import { useLocalization } from '@/utils/hooks/useLocalization' interface PostManagementProps { posts: ForumPost[] @@ -31,6 +32,7 @@ export function PostManagement({ onMarkPostAsAcceptedAnswer, onUnmarkPostAsAcceptedAnswer, }: PostManagementProps) { + const { translate } = useLocalization() const { tenant } = useStoreState((state) => state.auth) const [content, setContent] = useState('') const [showCreateForm, setShowCreateForm] = useState(false) @@ -131,14 +133,16 @@ export function PostManagement({ return (
-

Post Management

+

+ {translate('::App.Forum.PostManagement.Title')} +

@@ -146,7 +150,9 @@ export function PostManagement({ {showCreateForm && (

- {editingPost ? 'Edit Post' : 'Create New Post'} + {editingPost + ? translate('::App.Forum.PostManagement.EditPost') + : translate('::App.Forum.PostManagement.AddPost')}

@@ -220,7 +226,7 @@ export function PostManagement({ {loading ? (
-

Loading posts...

+

{translate('::App.Forum.PostManagement.Loadingtopics')}

) : (
@@ -288,7 +294,7 @@ export function PostManagement({ @@ -296,7 +302,7 @@ export function PostManagement({ diff --git a/ui/src/views/forum/admin/TopicManagement.tsx b/ui/src/views/forum/admin/TopicManagement.tsx index d99c8a1d..df82db78 100644 --- a/ui/src/views/forum/admin/TopicManagement.tsx +++ b/ui/src/views/forum/admin/TopicManagement.tsx @@ -14,6 +14,7 @@ import { } from 'lucide-react' import { ForumCategory, ForumTopic } from '@/proxy/forum/forum' import { useStoreState } from '@/store/store' +import { useLocalization } from '@/utils/hooks/useLocalization' interface TopicManagementProps { topics: ForumTopic[] @@ -51,6 +52,7 @@ export function TopicManagement({ onMarkTopicAsSolved, onMarkTopicAsUnsolved, }: TopicManagementProps) { + const { translate } = useLocalization() const { tenant } = useStoreState((state) => state.auth) const [showCreateForm, setShowCreateForm] = useState(false) const [editingTopic, setEditingTopic] = useState(null) @@ -107,7 +109,7 @@ export function TopicManagement({ isPinned: topic.isPinned, isLocked: topic.isLocked, isSolved: topic.isSolved, - tenantId: tenant.tenantId ?? '' + tenantId: tenant.tenantId ?? '', }) setShowCreateForm(true) } @@ -183,14 +185,16 @@ export function TopicManagement({ return (
-

Topic Management

+

+ {translate('::App.Forum.TopicManagement.Title')} +

@@ -198,7 +202,9 @@ export function TopicManagement({ {showCreateForm && (

- {editingTopic ? 'Edit Topic' : 'Create New Topic'} + {editingTopic + ? translate('::App.Forum.TopicManagement.AddTopic') + : translate('::App.Forum.TopicManagement.EditTopic')}

@@ -295,13 +301,13 @@ export function TopicManagement({ {/* Topics List */}
-

Topics ({topics.length})

+

{translate('::App.Forum.TopicManagement.Topics')} ({topics.length})

{loading ? (
-

Loading topics...

+

{translate('::App.Forum.TopicManagement.Loadingtopics')}

) : (
@@ -393,7 +399,7 @@ export function TopicManagement({ @@ -401,7 +407,7 @@ export function TopicManagement({ diff --git a/ui/src/views/forum/forum/CreatePostModal.tsx b/ui/src/views/forum/forum/CreatePostModal.tsx index 6b41a98d..b3101056 100644 --- a/ui/src/views/forum/forum/CreatePostModal.tsx +++ b/ui/src/views/forum/forum/CreatePostModal.tsx @@ -1,38 +1,39 @@ -import React, { useState } from 'react'; -import { X } from 'lucide-react'; -import ReactQuill from 'react-quill'; -import 'react-quill/dist/quill.snow.css'; -import { useStoreState } from '@/store/store'; +import React, { useState } from 'react' +import { X } from 'lucide-react' +import ReactQuill from 'react-quill' +import 'react-quill/dist/quill.snow.css' +import { useStoreState } from '@/store/store' +import { useLocalization } from '@/utils/hooks/useLocalization' interface CreatePostModalProps { - onClose: () => void; - onSubmit: (data: { content: string, parentPostId?: string, tenantId?: string }) => void; + onClose: () => void + onSubmit: (data: { content: string; parentPostId?: string; tenantId?: string }) => void parentPostId: string } export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostModalProps) { - const [content, setContent] = useState(''); + const { translate } = useLocalization() + const [content, setContent] = useState('') const { tenant } = useStoreState((state) => state.auth) const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - const plainText = content.replace(/<[^>]+>/g, '').trim(); // HTML etiketlerini temizle + e.preventDefault() + const plainText = content.replace(/<[^>]+>/g, '').trim() // HTML etiketlerini temizle if (plainText) { - onSubmit({ content, parentPostId, tenantId: tenant.tenantId }); + onSubmit({ content, parentPostId, tenantId: tenant.tenantId }) } - }; + } return (

- {parentPostId ? 'Reply to Topic' : 'New Post'} + {parentPostId + ? translate('::App.Forum.PostManagement.ReplytoTopic') + : translate('::App.Forum.PostManagement.NewPost')}

-
@@ -57,18 +58,18 @@ export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostM onClick={onClose} className="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors" > - Cancel + {translate('::Cancel')}
- ); + ) } diff --git a/ui/src/views/forum/forum/CreateTopicModal.tsx b/ui/src/views/forum/forum/CreateTopicModal.tsx index 4b6180b3..2f5a89b7 100644 --- a/ui/src/views/forum/forum/CreateTopicModal.tsx +++ b/ui/src/views/forum/forum/CreateTopicModal.tsx @@ -1,87 +1,113 @@ -import React, { useState } from 'react'; -import { X } from 'lucide-react'; -import { useStoreState } from '@/store/store'; +import { X } from 'lucide-react' +import { useStoreState } from '@/store/store' +import { useLocalization } from '@/utils/hooks/useLocalization' +import { Field, FieldProps, Form, Formik } from 'formik' +import { Button, FormContainer, FormItem, Input } from '@/components/ui' +import * as Yup from 'yup' interface CreateTopicModalProps { - onClose: () => void; - onSubmit: (data: { title: string; content: string, tenantId?: string }) => void; + onClose: () => void + onSubmit: (data: { title: string; content: string; tenantId?: string }) => void } +export const topicInitialValues = { + title: '', + content: '', +} + +export const topicValidationSchema = Yup.object().shape({ + title: Yup.string().required('Başlık zorunludur'), + content: Yup.string().required('İçerik zorunludur'), +}) + export function CreateTopicModal({ onClose, onSubmit }: CreateTopicModalProps) { - const [title, setTitle] = useState(''); - const [content, setContent] = useState(''); + const { translate } = useLocalization() const { tenant } = useStoreState((state) => state.auth) - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - if (title.trim() && content.trim()) { - onSubmit({ title: title.trim(), content: content.trim(), tenantId: tenant.tenantId }); - } - }; + const handleSubmit = ( + values: { title: string; content: string }, + { setSubmitting }: { setSubmitting: (isSubmitting: boolean) => void }, + ) => { + onSubmit({ + title: values.title.trim(), + content: values.content.trim(), + tenantId: tenant.tenantId, + }) + setSubmitting(false) + } return (
-
-
-

Create New Topic

-
- -
-
- - setTitle(e.target.value)} - className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent" - placeholder="Enter topic title..." - required - autoFocus - /> -
- -
- -