Seeder güncellemesi
This commit is contained in:
parent
fbeba1bada
commit
6157b9b320
21 changed files with 700 additions and 334 deletions
|
|
@ -131,16 +131,11 @@ namespace Kurs.Platform.Blog
|
||||||
input.CoverImage,
|
input.CoverImage,
|
||||||
input.CategoryId,
|
input.CategoryId,
|
||||||
_currentUser.Id.Value,
|
_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);
|
await _postRepository.InsertAsync(post, autoSave: true);
|
||||||
|
|
||||||
return await GetPostAsync(post.Id);
|
return await GetPostAsync(post.Id);
|
||||||
|
|
|
||||||
|
|
@ -440,26 +440,26 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
{
|
{
|
||||||
new() { Order=1, ColCount=1, ColSpan=2, ItemType="group", Items =
|
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=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=2, DataField="InstitutionName", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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=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=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=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 EditingFormItemDto { Order=8, DataField="IsActive", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
new() { Order=2, ColCount=1, ColSpan=2, ItemType="group", Items =
|
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=1, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=2, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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=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=4, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=5, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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 = 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 = 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 = 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 = 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 = 6, DataField = "SelectCommand", ColSpan = 2, IsRequired = true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order = 7, DataField = "TableName", ColSpan = 2, IsRequired = false, 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() { 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=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=2, DataField="Code", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=3, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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=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=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 EditingFormItemDto { Order=9, DataField="IsActive", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxCheckBox },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
new() { Order=2, ColCount=1, ColSpan=2, ItemType="group", Items =
|
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=1, DataField="Address", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=2, DataField="Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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=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=4, DataField="City", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=5, DataField="District", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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() { 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=1, DataField="Name", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=2, DataField="ValueType", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox },
|
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=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=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=5, DataField="Regex", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=6, DataField="RegexDescription", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox, EditorOptions="{ \"showClearButton\" : true }" },
|
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, EditorOptions="{ \"showClearButton\" : true }" },
|
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<EditingFormDto>
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
|
||||||
Order = 1,
|
|
||||||
ColCount = 1,
|
|
||||||
ColSpan = 2,
|
|
||||||
ItemType = "group",
|
|
||||||
Items =
|
|
||||||
[
|
|
||||||
new EditingFormItemDto
|
|
||||||
{
|
{
|
||||||
Order = 1,
|
Order = 1,
|
||||||
DataField = "Name",
|
ColCount = 1,
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
ItemType = "group",
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
Items =
|
||||||
|
[
|
||||||
|
new EditingFormItemDto
|
||||||
|
{
|
||||||
|
Order = 1,
|
||||||
|
DataField = "Name",
|
||||||
|
ColSpan = 2,
|
||||||
|
IsRequired = true,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
||||||
{
|
{
|
||||||
|
|
@ -8940,32 +8940,32 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
}),
|
}),
|
||||||
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
|
||||||
Order = 1,
|
|
||||||
ColCount = 1,
|
|
||||||
ColSpan = 2,
|
|
||||||
ItemType = "group",
|
|
||||||
Items =
|
|
||||||
[
|
|
||||||
new EditingFormItemDto
|
|
||||||
{
|
{
|
||||||
Order = 1,
|
Order = 1,
|
||||||
DataField = "Name",
|
ColCount = 1,
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
ItemType = "group",
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
Items =
|
||||||
},
|
[
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 2,
|
Order = 1,
|
||||||
DataField = "Category",
|
DataField = "Name",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
IsRequired = true,
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
|
},
|
||||||
|
new EditingFormItemDto
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
DataField = "Category",
|
||||||
|
ColSpan = 2,
|
||||||
|
IsRequired = true,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
||||||
{
|
{
|
||||||
|
|
@ -9154,49 +9154,49 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
}),
|
}),
|
||||||
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
|
||||||
Order = 1,
|
|
||||||
ColCount = 1,
|
|
||||||
ColSpan = 2,
|
|
||||||
ItemType = "group",
|
|
||||||
Items =
|
|
||||||
[
|
|
||||||
new EditingFormItemDto
|
|
||||||
{
|
{
|
||||||
Order = 1,
|
Order = 1,
|
||||||
DataField = "Title",
|
ColCount = 1,
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
ItemType = "group",
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
Items =
|
||||||
},
|
[
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 2,
|
Order = 1,
|
||||||
DataField = "Abbreviation",
|
DataField = "Title",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
IsRequired = true,
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
|
},
|
||||||
|
new EditingFormItemDto
|
||||||
|
{
|
||||||
|
Order = 2,
|
||||||
|
DataField = "Abbreviation",
|
||||||
|
ColSpan = 2,
|
||||||
|
IsRequired = true,
|
||||||
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[]
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
FieldName = "CreationTime",
|
FieldName = "CreationTime",
|
||||||
FieldDbType = DbType.DateTime,
|
FieldDbType = DbType.DateTime,
|
||||||
Value = "@NOW",
|
Value = "@NOW",
|
||||||
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
||||||
},
|
},
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
FieldName = "CreatorId",
|
FieldName = "CreatorId",
|
||||||
FieldDbType = DbType.Guid,
|
FieldDbType = DbType.Guid,
|
||||||
Value = "@USERID",
|
Value = "@USERID",
|
||||||
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -9370,74 +9370,74 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
}),
|
}),
|
||||||
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||||
{
|
{
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Order = 1,
|
Order = 1,
|
||||||
ColCount = 1,
|
ColCount = 1,
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
ItemType = "group",
|
ItemType = "group",
|
||||||
Items =
|
Items =
|
||||||
[
|
[
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 1,
|
Order = 1,
|
||||||
DataField = "Code",
|
DataField = "Code",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
IsRequired = true,
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
},
|
},
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 2,
|
Order = 2,
|
||||||
DataField = "Symbol",
|
DataField = "Symbol",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = false,
|
IsRequired = false,
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
},
|
},
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 3,
|
Order = 3,
|
||||||
DataField = "Name",
|
DataField = "Name",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
IsRequired = true,
|
||||||
EditorType2 = EditorTypes.dxTextBox
|
EditorType2 = EditorTypes.dxTextBox
|
||||||
},
|
},
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 4,
|
Order = 4,
|
||||||
DataField = "Rate",
|
DataField = "Rate",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = true,
|
IsRequired = true,
|
||||||
EditorType2 = EditorTypes.dxNumberBox
|
EditorType2 = EditorTypes.dxNumberBox
|
||||||
},
|
},
|
||||||
new EditingFormItemDto
|
new EditingFormItemDto
|
||||||
{
|
{
|
||||||
Order = 5,
|
Order = 5,
|
||||||
DataField = "IsActive",
|
DataField = "IsActive",
|
||||||
ColSpan = 2,
|
ColSpan = 2,
|
||||||
IsRequired = false,
|
IsRequired = false,
|
||||||
EditorType2 = EditorTypes.dxCheckBox
|
EditorType2 = EditorTypes.dxCheckBox
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new[]
|
InsertFieldsDefaultValueJson = JsonSerializer.Serialize(new[]
|
||||||
{
|
|
||||||
new FieldsDefaultValue
|
|
||||||
{
|
{
|
||||||
FieldName = "CreationTime",
|
new FieldsDefaultValue
|
||||||
FieldDbType = DbType.DateTime,
|
{
|
||||||
Value = "@NOW",
|
FieldName = "CreationTime",
|
||||||
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
FieldDbType = DbType.DateTime,
|
||||||
},
|
Value = "@NOW",
|
||||||
new FieldsDefaultValue
|
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
||||||
{
|
},
|
||||||
FieldName = "CreatorId",
|
new FieldsDefaultValue
|
||||||
FieldDbType = DbType.Guid,
|
{
|
||||||
Value = "@USERID",
|
FieldName = "CreatorId",
|
||||||
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
FieldDbType = DbType.Guid,
|
||||||
}
|
Value = "@USERID",
|
||||||
})
|
CustomValueType = FieldCustomValueTypeEnum.CustomKey
|
||||||
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
#region Currency Fields
|
#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 = 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 = 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 = 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 = 5, DataField = "PhoneCode", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxNumberBox },
|
||||||
new EditingFormItemDto { Order = 6, DataField = "TaxLabel", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxTextBox },
|
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 = 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 = 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",
|
ItemType = "group",
|
||||||
Items =
|
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 = 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 = 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 = 5, DataField = "DisplayOrder", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxNumberBox },
|
||||||
new EditingFormItemDto { Order = 6, DataField = "IsActive", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxCheckBox }
|
new EditingFormItemDto { Order = 6, DataField = "IsActive", ColSpan = 2, IsRequired = false, EditorType2 = EditorTypes.dxCheckBox }
|
||||||
|
|
@ -11111,12 +11111,12 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
ItemType = "group",
|
ItemType = "group",
|
||||||
Items =
|
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 = 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 = 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 = 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 = 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 = 8, DataField = "LikeCount", ColSpan = 2, IsRequired = true, EditorType2 = EditorTypes.dxNumberBox },
|
||||||
new EditingFormItemDto { Order = 9, DataField = "CommentCount", 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",
|
DisplayExpr = "Name",
|
||||||
ValueExpr = "Key",
|
ValueExpr = "Key",
|
||||||
LookupQuery = $"SELECT \"{DbTablePrefix}BlogCategories\".\"Id\" AS \"Key\", \"{DbTablePrefix}BlogCategories\".\"Name\" as \"Name\" FROM \"{DbTablePrefix}BlogCategories\" ORDER BY \"{DbTablePrefix}BlogCategories\".\"Name\""
|
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
|
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
|
||||||
{
|
{
|
||||||
C = AppCodes.BlogManagement.BlogPosts + ".Create",
|
C = AppCodes.BlogManagement.BlogPosts + ".Create",
|
||||||
|
|
@ -11365,13 +11365,55 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
new()
|
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,
|
ListFormCode = listFormBlogPosts.ListFormCode,
|
||||||
CultureName = LanguageCodes.En,
|
CultureName = LanguageCodes.En,
|
||||||
SourceDbType = DbType.Boolean,
|
SourceDbType = DbType.Boolean,
|
||||||
FieldName = "IsPublished",
|
FieldName = "IsPublished",
|
||||||
Width = 80,
|
Width = 80,
|
||||||
ListOrderNo = 9,
|
ListOrderNo = 10,
|
||||||
Visible = true,
|
Visible = true,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
|
|
@ -11392,7 +11434,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
SourceDbType = DbType.DateTime,
|
SourceDbType = DbType.DateTime,
|
||||||
FieldName = "PublishedAt",
|
FieldName = "PublishedAt",
|
||||||
Width = 120,
|
Width = 120,
|
||||||
ListOrderNo = 10,
|
ListOrderNo = 11,
|
||||||
Visible = true,
|
Visible = true,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
|
|
@ -11405,6 +11447,48 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
E = true,
|
E = true,
|
||||||
Deny = false
|
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
|
#endregion
|
||||||
|
|
|
||||||
|
|
@ -593,7 +593,9 @@ public class PlatformDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
item.ReadTime,
|
item.ReadTime,
|
||||||
item.CoverImage,
|
item.CoverImage,
|
||||||
item.CategoryId,
|
item.CategoryId,
|
||||||
item.AuthorId
|
item.AuthorId,
|
||||||
|
true,
|
||||||
|
DateTime.UtcNow
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,228 @@
|
||||||
"en": "Forum",
|
"en": "Forum",
|
||||||
"tr": "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",
|
"resourceName": "Platform",
|
||||||
"key": "App.Home",
|
"key": "App.Home",
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,8 @@ public class BlogPostSeedDto
|
||||||
public string CoverImage { get; set; }
|
public string CoverImage { get; set; }
|
||||||
public Guid CategoryId { get; set; }
|
public Guid CategoryId { get; set; }
|
||||||
public Guid AuthorId { get; set; }
|
public Guid AuthorId { get; set; }
|
||||||
|
public Boolean IsPublished { get; set; }
|
||||||
|
public DateTime PublishedAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ForumCategorySeedDto
|
public class ForumCategorySeedDto
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ public class BlogPost : FullAuditedAggregateRoot<Guid>
|
||||||
string coverImage,
|
string coverImage,
|
||||||
Guid categoryId,
|
Guid categoryId,
|
||||||
Guid authorId,
|
Guid authorId,
|
||||||
|
bool isPublished,
|
||||||
|
DateTime? publishedAt = null,
|
||||||
Guid? tenantId = null) : base(id)
|
Guid? tenantId = null) : base(id)
|
||||||
{
|
{
|
||||||
Title = title;
|
Title = title;
|
||||||
|
|
@ -53,12 +55,13 @@ public class BlogPost : FullAuditedAggregateRoot<Guid>
|
||||||
CoverImage = coverImage;
|
CoverImage = coverImage;
|
||||||
CategoryId = categoryId;
|
CategoryId = categoryId;
|
||||||
AuthorId = authorId;
|
AuthorId = authorId;
|
||||||
|
IsPublished = isPublished;
|
||||||
|
PublishedAt = publishedAt;
|
||||||
TenantId = tenantId;
|
TenantId = tenantId;
|
||||||
|
|
||||||
ViewCount = 0;
|
ViewCount = 0;
|
||||||
LikeCount = 0;
|
LikeCount = 0;
|
||||||
CommentCount = 0;
|
CommentCount = 0;
|
||||||
IsPublished = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Publish()
|
public void Publish()
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.mj87dckq3bo"
|
"revision": "0.ru7ltd9thg8"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ const Simple = ({ children, content, ...rest }: SimpleProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
<Container className="flex flex-col flex-auto items-center justify-center min-w-0 h-full">
|
<Container className="flex flex-col flex-auto items-center justify-center min-w-0 h-full">
|
||||||
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-10">
|
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-6">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mb-4">
|
||||||
<a
|
<a
|
||||||
href={import.meta.env.VITE_COMPANY_URL}
|
href={import.meta.env.VITE_COMPANY_URL}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const HorizontalMenuIcon = ({ icon }: HorizontalMenuIconProps) => {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
return <span className="text-2xl ltr:mr-2 rtl:ml-2">{navigationIcon[icon]}</span>
|
return <span className="text-xl ltr:mr-2 rtl:ml-2">{navigationIcon[icon]}</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HorizontalMenuIcon
|
export default HorizontalMenuIcon
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ import ReactDOM from 'react-dom/client'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import { UiEvalService } from './services/UiEvalService'
|
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(<App />)
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { TopicManagement } from './TopicManagement'
|
||||||
import { PostManagement } from './PostManagement'
|
import { PostManagement } from './PostManagement'
|
||||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||||
import { AdminStats } from './Dashboard'
|
import { AdminStats } from './Dashboard'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface AdminViewProps {
|
interface AdminViewProps {
|
||||||
categories: ForumCategory[]
|
categories: ForumCategory[]
|
||||||
|
|
@ -74,12 +75,13 @@ export function AdminView({
|
||||||
onUnmarkPostAsAcceptedAnswer,
|
onUnmarkPostAsAcceptedAnswer,
|
||||||
}: AdminViewProps) {
|
}: AdminViewProps) {
|
||||||
const [activeSection, setActiveSection] = useState<AdminSection>('stats')
|
const [activeSection, setActiveSection] = useState<AdminSection>('stats')
|
||||||
|
const { translate } = useLocalization();
|
||||||
|
|
||||||
const navigationItems = [
|
const navigationItems = [
|
||||||
{ id: 'stats' as AdminSection, label: 'Dashboard', icon: BarChart3 },
|
{ id: 'stats' as AdminSection, label: translate('::App.Forum.Dashboard.Dashboard'), icon: BarChart3 },
|
||||||
{ id: 'categories' as AdminSection, label: 'Categories', icon: Folder },
|
{ id: 'categories' as AdminSection, label: translate('::App.Forum.Dashboard.Categories'), icon: Folder },
|
||||||
{ id: 'topics' as AdminSection, label: 'Topics', icon: MessageSquare },
|
{ id: 'topics' as AdminSection, label: translate('::App.Forum.Dashboard.Topics'), icon: MessageSquare },
|
||||||
{ id: 'posts' as AdminSection, label: 'Posts', icon: FileText },
|
{ id: 'posts' as AdminSection, label: translate('::App.Forum.Dashboard.Posts'), icon: FileText },
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React, { useState } from 'react'
|
||||||
import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react'
|
import { Plus, Edit2, Trash2, Lock, Unlock, Eye, EyeOff, Loader2 } from 'lucide-react'
|
||||||
import { ForumCategory } from '@/proxy/forum/forum'
|
import { ForumCategory } from '@/proxy/forum/forum'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface CategoryManagementProps {
|
interface CategoryManagementProps {
|
||||||
categories: ForumCategory[]
|
categories: ForumCategory[]
|
||||||
|
|
@ -31,6 +32,7 @@ export function CategoryManagement({
|
||||||
onUpdateCategoryLockState,
|
onUpdateCategoryLockState,
|
||||||
onUpdateCategoryActiveState,
|
onUpdateCategoryActiveState,
|
||||||
}: CategoryManagementProps) {
|
}: CategoryManagementProps) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
const { tenant } = useStoreState((state) => state.auth)
|
const { tenant } = useStoreState((state) => state.auth)
|
||||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||||
const [editingCategory, setEditingCategory] = useState<ForumCategory | null>(null)
|
const [editingCategory, setEditingCategory] = useState<ForumCategory | null>(null)
|
||||||
|
|
@ -42,7 +44,7 @@ export function CategoryManagement({
|
||||||
displayOrder: 0,
|
displayOrder: 0,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
tenantId: ''
|
tenantId: '',
|
||||||
})
|
})
|
||||||
const [submitting, setSubmitting] = useState(false)
|
const [submitting, setSubmitting] = useState(false)
|
||||||
|
|
||||||
|
|
@ -55,7 +57,7 @@ export function CategoryManagement({
|
||||||
displayOrder: 0,
|
displayOrder: 0,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
tenantId: ''
|
tenantId: '',
|
||||||
})
|
})
|
||||||
setShowCreateForm(false)
|
setShowCreateForm(false)
|
||||||
setEditingCategory(null)
|
setEditingCategory(null)
|
||||||
|
|
@ -90,7 +92,7 @@ export function CategoryManagement({
|
||||||
displayOrder: category.displayOrder,
|
displayOrder: category.displayOrder,
|
||||||
isActive: category.isActive,
|
isActive: category.isActive,
|
||||||
isLocked: category.isLocked,
|
isLocked: category.isLocked,
|
||||||
tenantId: tenant.tenantId ?? ''
|
tenantId: tenant.tenantId ?? '',
|
||||||
})
|
})
|
||||||
setShowCreateForm(true)
|
setShowCreateForm(true)
|
||||||
}
|
}
|
||||||
|
|
@ -128,14 +130,16 @@ export function CategoryManagement({
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Category Management</h2>
|
<h2 className="text-2xl font-bold text-gray-900">
|
||||||
|
{translate('::App.Forum.CategoryManagement.Title')}
|
||||||
|
</h2>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCreateForm(true)}
|
onClick={() => setShowCreateForm(true)}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
<span>Add Category</span>
|
<span>{translate('::App.Forum.CategoryManagement.AddCategory')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -143,7 +147,9 @@ export function CategoryManagement({
|
||||||
{showCreateForm && (
|
{showCreateForm && (
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
||||||
{editingCategory ? 'Edit Category' : 'Create New Category'}
|
{editingCategory
|
||||||
|
? translate('::App.Forum.CategoryManagement.EditCategory')
|
||||||
|
: translate('::App.Forum.CategoryManagement.CreateCategory')}
|
||||||
</h3>
|
</h3>
|
||||||
<form onSubmit={handleSubmit} className="space-y-4">
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
|
@ -251,13 +257,13 @@ export function CategoryManagement({
|
||||||
{/* Categories List */}
|
{/* Categories List */}
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||||
<div className="px-6 py-4 border-b border-gray-200">
|
<div className="px-6 py-4 border-b border-gray-200">
|
||||||
<h3 className="text-lg font-semibold text-gray-900">Categories ({categories.length})</h3>
|
<h3 className="text-lg font-semibold text-gray-900">{translate('::App.Forum.CategoryManagement.Categories')} ({categories.length})</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="p-8 text-center">
|
<div className="p-8 text-center">
|
||||||
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||||
<p className="text-gray-500">Loading categories...</p>
|
<p className="text-gray-500">{translate('::App.Forum.CategoryManagement.Loadingcategories')}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="divide-y divide-gray-200">
|
<div className="divide-y divide-gray-200">
|
||||||
|
|
@ -327,7 +333,7 @@ export function CategoryManagement({
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEdit(category)}
|
onClick={() => handleEdit(category)}
|
||||||
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
||||||
title="Edit Category"
|
title={translate('::App.Forum.CategoryManagement.EditCategory')}
|
||||||
>
|
>
|
||||||
<Edit2 className="w-4 h-4" />
|
<Edit2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -335,7 +341,7 @@ export function CategoryManagement({
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDelete(category.id)}
|
onClick={() => handleDelete(category.id)}
|
||||||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||||
title="Delete Category"
|
title={translate('::App.Forum.CategoryManagement.DeleteCategory')}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4" />
|
<Trash2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Folder, MessageSquare, FileText, TrendingUp } from 'lucide-react';
|
import { Folder, MessageSquare, FileText, TrendingUp } from 'lucide-react';
|
||||||
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum';
|
import { ForumCategory, ForumPost, ForumTopic } from '@/proxy/forum/forum';
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization';
|
||||||
|
|
||||||
interface AdminStatsProps {
|
interface AdminStatsProps {
|
||||||
categories: ForumCategory[];
|
categories: ForumCategory[];
|
||||||
|
|
@ -9,6 +10,7 @@ interface AdminStatsProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AdminStats({ categories, topics, posts }: AdminStatsProps) {
|
export function AdminStats({ categories, topics, posts }: AdminStatsProps) {
|
||||||
|
const { translate } = useLocalization();
|
||||||
const totalCategories = categories.length;
|
const totalCategories = categories.length;
|
||||||
const activeCategories = categories.filter(c => c.isActive).length;
|
const activeCategories = categories.filter(c => c.isActive).length;
|
||||||
const totalTopics = topics.length;
|
const totalTopics = topics.length;
|
||||||
|
|
@ -18,28 +20,28 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) {
|
||||||
|
|
||||||
const stats = [
|
const stats = [
|
||||||
{
|
{
|
||||||
title: 'Total Categories',
|
title: translate('::App.Forum.Dashboard.TotalCategories'),
|
||||||
value: totalCategories,
|
value: totalCategories,
|
||||||
subtitle: `${activeCategories} active`,
|
subtitle: `${activeCategories} active`,
|
||||||
icon: Folder,
|
icon: Folder,
|
||||||
color: 'bg-blue-500',
|
color: 'bg-blue-500',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Total Topics',
|
title: translate('::App.Forum.Dashboard.TotalTopics'),
|
||||||
value: totalTopics,
|
value: totalTopics,
|
||||||
subtitle: `${solvedTopics} solved`,
|
subtitle: `${solvedTopics} solved`,
|
||||||
icon: MessageSquare,
|
icon: MessageSquare,
|
||||||
color: 'bg-emerald-500',
|
color: 'bg-emerald-500',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Total Posts',
|
title: translate('::App.Forum.Dashboard.TotalPosts'),
|
||||||
value: totalPosts,
|
value: totalPosts,
|
||||||
subtitle: `${acceptedAnswers} accepted answers`,
|
subtitle: `${acceptedAnswers} accepted answers`,
|
||||||
icon: FileText,
|
icon: FileText,
|
||||||
color: 'bg-orange-500',
|
color: 'bg-orange-500',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Engagement Rate',
|
title: translate('::App.Forum.Dashboard.EngagementRate'),
|
||||||
value: totalTopics > 0 ? Math.round((totalPosts / totalTopics) * 100) / 100 : 0,
|
value: totalTopics > 0 ? Math.round((totalPosts / totalTopics) * 100) / 100 : 0,
|
||||||
subtitle: 'posts per topic',
|
subtitle: 'posts per topic',
|
||||||
icon: TrendingUp,
|
icon: TrendingUp,
|
||||||
|
|
@ -50,7 +52,7 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-2xl font-bold text-gray-900 mb-6">Forum Statistics</h2>
|
<h2 className="text-2xl font-bold text-gray-900 mb-6">{translate('::App.Forum.Dashboard.Statistics')}</h2>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
{stats.map((stat, index) => {
|
{stats.map((stat, index) => {
|
||||||
|
|
@ -75,26 +77,26 @@ export function AdminStats({ categories, topics, posts }: AdminStatsProps) {
|
||||||
|
|
||||||
{/* Recent Activity */}
|
{/* Recent Activity */}
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Recent Activity</h3>
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">{translate('::App.Forum.Dashboard.RecentActivity')}</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
|
<div className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
|
||||||
<div className="w-2 h-2 bg-blue-500 rounded-full mt-2"></div>
|
<div className="w-2 h-2 bg-blue-500 rounded-full mt-2"></div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-900">New topic created in General Discussion</p>
|
<p className="text-sm text-gray-900">{translate('::App.Forum.Dashboard.GeneralDiscussion')}</p>
|
||||||
<p className="text-xs text-gray-500">2 hours ago</p>
|
<p className="text-xs text-gray-500">2 hours ago</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
|
<div className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
|
||||||
<div className="w-2 h-2 bg-emerald-500 rounded-full mt-2"></div>
|
<div className="w-2 h-2 bg-emerald-500 rounded-full mt-2"></div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-900">Post marked as accepted answer</p>
|
<p className="text-sm text-gray-900">{translate('::App.Forum.Dashboard.Postmarked')}</p>
|
||||||
<p className="text-xs text-gray-500">4 hours ago</p>
|
<p className="text-xs text-gray-500">4 hours ago</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
|
<div className="flex items-start space-x-3 p-3 bg-gray-50 rounded-lg">
|
||||||
<div className="w-2 h-2 bg-orange-500 rounded-full mt-2"></div>
|
<div className="w-2 h-2 bg-orange-500 rounded-full mt-2"></div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-900">New category created: Feature Requests</p>
|
<p className="text-sm text-gray-900">{translate('::App.Forum.Dashboard.FeatureRequests')}</p>
|
||||||
<p className="text-xs text-gray-500">1 day ago</p>
|
<p className="text-xs text-gray-500">1 day ago</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { ForumPost, ForumTopic } from '@/proxy/forum/forum'
|
||||||
import ReactQuill from 'react-quill'
|
import ReactQuill from 'react-quill'
|
||||||
import 'react-quill/dist/quill.snow.css'
|
import 'react-quill/dist/quill.snow.css'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface PostManagementProps {
|
interface PostManagementProps {
|
||||||
posts: ForumPost[]
|
posts: ForumPost[]
|
||||||
|
|
@ -31,6 +32,7 @@ export function PostManagement({
|
||||||
onMarkPostAsAcceptedAnswer,
|
onMarkPostAsAcceptedAnswer,
|
||||||
onUnmarkPostAsAcceptedAnswer,
|
onUnmarkPostAsAcceptedAnswer,
|
||||||
}: PostManagementProps) {
|
}: PostManagementProps) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
const { tenant } = useStoreState((state) => state.auth)
|
const { tenant } = useStoreState((state) => state.auth)
|
||||||
const [content, setContent] = useState('')
|
const [content, setContent] = useState('')
|
||||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||||
|
|
@ -131,14 +133,16 @@ export function PostManagement({
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Post Management</h2>
|
<h2 className="text-2xl font-bold text-gray-900">
|
||||||
|
{translate('::App.Forum.PostManagement.Title')}
|
||||||
|
</h2>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCreateForm(true)}
|
onClick={() => setShowCreateForm(true)}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
<span>Add Post</span>
|
<span>{translate('::App.Forum.PostManagement.AddPost')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -146,7 +150,9 @@ export function PostManagement({
|
||||||
{showCreateForm && (
|
{showCreateForm && (
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
||||||
{editingPost ? 'Edit Post' : 'Create New Post'}
|
{editingPost
|
||||||
|
? translate('::App.Forum.PostManagement.EditPost')
|
||||||
|
: translate('::App.Forum.PostManagement.AddPost')}
|
||||||
</h3>
|
</h3>
|
||||||
<form onSubmit={handleSubmit} className="space-y-4">
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -220,7 +226,7 @@ export function PostManagement({
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="p-8 text-center">
|
<div className="p-8 text-center">
|
||||||
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||||
<p className="text-gray-500">Loading posts...</p>
|
<p className="text-gray-500">{translate('::App.Forum.PostManagement.Loadingtopics')}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="divide-y divide-gray-200">
|
<div className="divide-y divide-gray-200">
|
||||||
|
|
@ -288,7 +294,7 @@ export function PostManagement({
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEdit(post)}
|
onClick={() => handleEdit(post)}
|
||||||
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
||||||
title="Edit Post"
|
title={translate('::App.Forum.PostManagement.EditPost')}
|
||||||
>
|
>
|
||||||
<Edit2 className="w-4 h-4" />
|
<Edit2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -296,7 +302,7 @@ export function PostManagement({
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDelete(post.id)}
|
onClick={() => handleDelete(post.id)}
|
||||||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||||
title="Delete Post"
|
title={translate('::App.Forum.PostManagement.DeletePost')}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4" />
|
<Trash2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import { ForumCategory, ForumTopic } from '@/proxy/forum/forum'
|
import { ForumCategory, ForumTopic } from '@/proxy/forum/forum'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface TopicManagementProps {
|
interface TopicManagementProps {
|
||||||
topics: ForumTopic[]
|
topics: ForumTopic[]
|
||||||
|
|
@ -51,6 +52,7 @@ export function TopicManagement({
|
||||||
onMarkTopicAsSolved,
|
onMarkTopicAsSolved,
|
||||||
onMarkTopicAsUnsolved,
|
onMarkTopicAsUnsolved,
|
||||||
}: TopicManagementProps) {
|
}: TopicManagementProps) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
const { tenant } = useStoreState((state) => state.auth)
|
const { tenant } = useStoreState((state) => state.auth)
|
||||||
const [showCreateForm, setShowCreateForm] = useState(false)
|
const [showCreateForm, setShowCreateForm] = useState(false)
|
||||||
const [editingTopic, setEditingTopic] = useState<ForumTopic | null>(null)
|
const [editingTopic, setEditingTopic] = useState<ForumTopic | null>(null)
|
||||||
|
|
@ -107,7 +109,7 @@ export function TopicManagement({
|
||||||
isPinned: topic.isPinned,
|
isPinned: topic.isPinned,
|
||||||
isLocked: topic.isLocked,
|
isLocked: topic.isLocked,
|
||||||
isSolved: topic.isSolved,
|
isSolved: topic.isSolved,
|
||||||
tenantId: tenant.tenantId ?? ''
|
tenantId: tenant.tenantId ?? '',
|
||||||
})
|
})
|
||||||
setShowCreateForm(true)
|
setShowCreateForm(true)
|
||||||
}
|
}
|
||||||
|
|
@ -183,14 +185,16 @@ export function TopicManagement({
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h2 className="text-2xl font-bold text-gray-900">Topic Management</h2>
|
<h2 className="text-2xl font-bold text-gray-900">
|
||||||
|
{translate('::App.Forum.TopicManagement.Title')}
|
||||||
|
</h2>
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCreateForm(true)}
|
onClick={() => setShowCreateForm(true)}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
<span>Add Topic</span>
|
<span>{translate('::App.Forum.TopicManagement.AddTopic')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -198,7 +202,9 @@ export function TopicManagement({
|
||||||
{showCreateForm && (
|
{showCreateForm && (
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
<h3 className="text-lg font-semibold text-gray-900 mb-4">
|
||||||
{editingTopic ? 'Edit Topic' : 'Create New Topic'}
|
{editingTopic
|
||||||
|
? translate('::App.Forum.TopicManagement.AddTopic')
|
||||||
|
: translate('::App.Forum.TopicManagement.EditTopic')}
|
||||||
</h3>
|
</h3>
|
||||||
<form onSubmit={handleSubmit} className="space-y-4">
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -295,13 +301,13 @@ export function TopicManagement({
|
||||||
{/* Topics List */}
|
{/* Topics List */}
|
||||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
||||||
<div className="px-6 py-4 border-b border-gray-200">
|
<div className="px-6 py-4 border-b border-gray-200">
|
||||||
<h3 className="text-lg font-semibold text-gray-900">Topics ({topics.length})</h3>
|
<h3 className="text-lg font-semibold text-gray-900">{translate('::App.Forum.TopicManagement.Topics')} ({topics.length})</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="p-8 text-center">
|
<div className="p-8 text-center">
|
||||||
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
<Loader2 className="w-8 h-8 animate-spin mx-auto mb-4 text-blue-600" />
|
||||||
<p className="text-gray-500">Loading topics...</p>
|
<p className="text-gray-500">{translate('::App.Forum.TopicManagement.Loadingtopics')}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="divide-y divide-gray-200">
|
<div className="divide-y divide-gray-200">
|
||||||
|
|
@ -393,7 +399,7 @@ export function TopicManagement({
|
||||||
<button
|
<button
|
||||||
onClick={() => handleEdit(topic)}
|
onClick={() => handleEdit(topic)}
|
||||||
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
className="p-2 text-blue-600 hover:bg-blue-100 rounded-lg transition-colors"
|
||||||
title="Edit Topic"
|
title={translate('::App.Forum.TopicManagement.EditTopic')}
|
||||||
>
|
>
|
||||||
<Edit2 className="w-4 h-4" />
|
<Edit2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -401,7 +407,7 @@ export function TopicManagement({
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDelete(topic.id)}
|
onClick={() => handleDelete(topic.id)}
|
||||||
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
className="p-2 text-red-600 hover:bg-red-100 rounded-lg transition-colors"
|
||||||
title="Delete Topic"
|
title={translate('::App.Forum.TopicManagement.DeleteTopic')}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-4 h-4" />
|
<Trash2 className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,39 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react'
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react'
|
||||||
import ReactQuill from 'react-quill';
|
import ReactQuill from 'react-quill'
|
||||||
import 'react-quill/dist/quill.snow.css';
|
import 'react-quill/dist/quill.snow.css'
|
||||||
import { useStoreState } from '@/store/store';
|
import { useStoreState } from '@/store/store'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface CreatePostModalProps {
|
interface CreatePostModalProps {
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSubmit: (data: { content: string, parentPostId?: string, tenantId?: string }) => void;
|
onSubmit: (data: { content: string; parentPostId?: string; tenantId?: string }) => void
|
||||||
parentPostId: string
|
parentPostId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostModalProps) {
|
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 { tenant } = useStoreState((state) => state.auth)
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
const plainText = content.replace(/<[^>]+>/g, '').trim(); // HTML etiketlerini temizle
|
const plainText = content.replace(/<[^>]+>/g, '').trim() // HTML etiketlerini temizle
|
||||||
if (plainText) {
|
if (plainText) {
|
||||||
onSubmit({ content, parentPostId, tenantId: tenant.tenantId });
|
onSubmit({ content, parentPostId, tenantId: tenant.tenantId })
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
|
||||||
<div className="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
|
||||||
<div className="flex items-center justify-between p-6 border-b border-gray-200">
|
<div className="flex items-center justify-between p-6 border-b border-gray-200">
|
||||||
<h3 className="text-lg font-semibold text-gray-900">
|
<h3 className="text-lg font-semibold text-gray-900">
|
||||||
{parentPostId ? 'Reply to Topic' : 'New Post'}
|
{parentPostId
|
||||||
|
? translate('::App.Forum.PostManagement.ReplytoTopic')
|
||||||
|
: translate('::App.Forum.PostManagement.NewPost')}
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition-colors">
|
||||||
onClick={onClose}
|
|
||||||
className="text-gray-400 hover:text-gray-600 transition-colors"
|
|
||||||
>
|
|
||||||
<X className="w-5 h-5" />
|
<X className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -57,18 +58,18 @@ export function CreatePostModal({ onClose, onSubmit, parentPostId }: CreatePostM
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors"
|
className="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors"
|
||||||
>
|
>
|
||||||
Cancel
|
{translate('::Cancel')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors disabled:opacity-50"
|
className="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors disabled:opacity-50"
|
||||||
disabled={!content || content.replace(/<[^>]+>/g, '').trim() === ''}
|
disabled={!content || content.replace(/<[^>]+>/g, '').trim() === ''}
|
||||||
>
|
>
|
||||||
Post Reply
|
{translate('::App.Forum.PostManagement.PostReply')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,113 @@
|
||||||
import React, { useState } from 'react';
|
import { X } from 'lucide-react'
|
||||||
import { X } from 'lucide-react';
|
import { useStoreState } from '@/store/store'
|
||||||
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 {
|
interface CreateTopicModalProps {
|
||||||
onClose: () => void;
|
onClose: () => void
|
||||||
onSubmit: (data: { title: string; content: string, tenantId?: string }) => 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) {
|
export function CreateTopicModal({ onClose, onSubmit }: CreateTopicModalProps) {
|
||||||
const [title, setTitle] = useState('');
|
const { translate } = useLocalization()
|
||||||
const [content, setContent] = useState('');
|
|
||||||
const { tenant } = useStoreState((state) => state.auth)
|
const { tenant } = useStoreState((state) => state.auth)
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (
|
||||||
e.preventDefault();
|
values: { title: string; content: string },
|
||||||
if (title.trim() && content.trim()) {
|
{ setSubmitting }: { setSubmitting: (isSubmitting: boolean) => void },
|
||||||
onSubmit({ title: title.trim(), content: content.trim(), tenantId: tenant.tenantId });
|
) => {
|
||||||
}
|
onSubmit({
|
||||||
};
|
title: values.title.trim(),
|
||||||
|
content: values.content.trim(),
|
||||||
|
tenantId: tenant.tenantId,
|
||||||
|
})
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
|
||||||
<div className="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-lg max-h-[90vh] overflow-y-auto p-6">
|
||||||
<div className="flex items-center justify-between p-6 border-b border-gray-200">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<h3 className="text-lg font-semibold text-gray-900">Create New Topic</h3>
|
<h3 className="text-lg font-semibold text-gray-900">
|
||||||
<button
|
{translate('::App.Forum.TopicManagement.NewTopic')}
|
||||||
onClick={onClose}
|
</h3>
|
||||||
className="text-gray-400 hover:text-gray-600 transition-colors"
|
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition-colors">
|
||||||
>
|
|
||||||
<X className="w-5 h-5" />
|
<X className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} className="p-6 space-y-4">
|
<Formik
|
||||||
<div>
|
initialValues={topicInitialValues}
|
||||||
<label htmlFor="title" className="block text-sm font-medium text-gray-700 mb-2">
|
validationSchema={topicValidationSchema}
|
||||||
Title
|
onSubmit={handleSubmit}
|
||||||
</label>
|
enableReinitialize={true}
|
||||||
<input
|
>
|
||||||
type="text"
|
{({ values, touched, errors, isSubmitting }) => (
|
||||||
id="title"
|
<Form>
|
||||||
value={title}
|
<FormContainer className="space-y-4">
|
||||||
onChange={(e) => setTitle(e.target.value)}
|
<FormItem
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
label={translate('::App.Forum.TopicManagement.Title')}
|
||||||
placeholder="Enter topic title..."
|
invalid={errors.title && touched.title}
|
||||||
required
|
errorMessage={errors.title}
|
||||||
autoFocus
|
>
|
||||||
/>
|
<Field
|
||||||
</div>
|
type="text"
|
||||||
|
name="title"
|
||||||
<div>
|
placeholder="Başlık girin..."
|
||||||
<label htmlFor="content" className="block text-sm font-medium text-gray-700 mb-2">
|
autoFocus
|
||||||
Content
|
className="w-full text-sm border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
</label>
|
component={Input}
|
||||||
<textarea
|
/>
|
||||||
id="content"
|
</FormItem>
|
||||||
value={content}
|
|
||||||
onChange={(e) => setContent(e.target.value)}
|
<FormItem
|
||||||
rows={8}
|
asterisk
|
||||||
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
label={translate('::App.Forum.TopicManagement.Content')}
|
||||||
placeholder="Write your topic content..."
|
invalid={errors.content && touched.content}
|
||||||
required
|
errorMessage={errors.content}
|
||||||
/>
|
>
|
||||||
</div>
|
<Field name="content">
|
||||||
|
{({ field }: FieldProps) => (
|
||||||
<div className="flex justify-end space-x-3 pt-4">
|
<textarea
|
||||||
<button
|
{...field}
|
||||||
type="button"
|
rows={6}
|
||||||
onClick={onClose}
|
placeholder="Konu içeriğini yazın..."
|
||||||
className="px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors"
|
className="w-full text-sm border border-gray-300 rounded-md px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none"
|
||||||
>
|
/>
|
||||||
Cancel
|
)}
|
||||||
</button>
|
</Field>
|
||||||
<button
|
</FormItem>
|
||||||
type="submit"
|
|
||||||
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors disabled:opacity-50"
|
<div className="flex justify-end space-x-3 pt-2">
|
||||||
disabled={!title.trim() || !content.trim()}
|
<Button variant="plain" type="button" onClick={onClose}>
|
||||||
>
|
{translate('::Cancel')}
|
||||||
Create Topic
|
</Button>
|
||||||
</button>
|
<Button
|
||||||
</div>
|
variant="solid"
|
||||||
</form>
|
type="submit"
|
||||||
|
disabled={!values.title.trim() || !values.content.trim()}
|
||||||
|
loading={isSubmitting}
|
||||||
|
>
|
||||||
|
{translate('::App.Forum.TopicManagement.AddTopic')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</FormContainer>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React from 'react'
|
||||||
import { Heart, User, CheckCircle, Reply } from 'lucide-react'
|
import { Heart, User, CheckCircle, Reply } from 'lucide-react'
|
||||||
import { ForumPost } from '@/proxy/forum/forum'
|
import { ForumPost } from '@/proxy/forum/forum'
|
||||||
import { AVATAR_URL } from '@/constants/app.constant'
|
import { AVATAR_URL } from '@/constants/app.constant'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface PostCardProps {
|
interface PostCardProps {
|
||||||
post: ForumPost
|
post: ForumPost
|
||||||
|
|
@ -18,8 +19,9 @@ export function ForumPostCard({
|
||||||
isFirst = false,
|
isFirst = false,
|
||||||
isLiked = false,
|
isLiked = false,
|
||||||
}: PostCardProps) {
|
}: PostCardProps) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
const formatDate = (value: string | Date) => {
|
const formatDate = (value: string | Date) => {
|
||||||
const date = value instanceof Date ? value : new Date(value)
|
const date = value instanceof Date ? value : new Date(value)
|
||||||
if (isNaN(date.getTime())) return 'Invalid Date'
|
if (isNaN(date.getTime())) return 'Invalid Date'
|
||||||
|
|
||||||
return new Intl.DateTimeFormat('en', {
|
return new Intl.DateTimeFormat('en', {
|
||||||
|
|
@ -55,7 +57,7 @@ export function ForumPostCard({
|
||||||
{post.isAcceptedAnswer && (
|
{post.isAcceptedAnswer && (
|
||||||
<div className="flex items-center space-x-1 bg-emerald-100 text-emerald-700 px-2 py-1 rounded-full text-xs">
|
<div className="flex items-center space-x-1 bg-emerald-100 text-emerald-700 px-2 py-1 rounded-full text-xs">
|
||||||
<CheckCircle className="w-3 h-3" />
|
<CheckCircle className="w-3 h-3" />
|
||||||
<span>Accepted Answer</span>
|
<span>{translate('::App.Forum.PostManagement.AcceptedAnswer')}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -82,13 +84,15 @@ export function ForumPostCard({
|
||||||
<span>{post.likeCount}</span>
|
<span>{post.likeCount}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{!isFirst && (<button
|
{!isFirst && (
|
||||||
onClick={() => onReply(post.id)}
|
<button
|
||||||
className="flex items-center space-x-1 px-3 py-1 rounded-full text-sm bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors"
|
onClick={() => onReply(post.id)}
|
||||||
>
|
className="flex items-center space-x-1 px-3 py-1 rounded-full text-sm bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors"
|
||||||
<Reply className="w-4 h-4" />
|
>
|
||||||
<span>Reply</span>
|
<Reply className="w-4 h-4" />
|
||||||
</button>)}
|
<span>{translate('::App.Forum.PostManagement.PostReply')}</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import React from 'react'
|
||||||
import { MessageSquare, Heart, Eye, Pin, Lock, CheckCircle } from 'lucide-react'
|
import { MessageSquare, Heart, Eye, Pin, Lock, CheckCircle } from 'lucide-react'
|
||||||
import { ForumTopic } from '@/proxy/forum/forum'
|
import { ForumTopic } from '@/proxy/forum/forum'
|
||||||
import { AVATAR_URL } from '@/constants/app.constant'
|
import { AVATAR_URL } from '@/constants/app.constant'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface TopicCardProps {
|
interface TopicCardProps {
|
||||||
topic: ForumTopic
|
topic: ForumTopic
|
||||||
|
|
@ -9,6 +10,7 @@ interface TopicCardProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ForumTopicCard({ topic, onClick }: TopicCardProps) {
|
export function ForumTopicCard({ topic, onClick }: TopicCardProps) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
const formatDate = (dateString?: string) => {
|
const formatDate = (dateString?: string) => {
|
||||||
if (!dateString) return 'Never'
|
if (!dateString) return 'Never'
|
||||||
|
|
||||||
|
|
@ -78,7 +80,7 @@ export function ForumTopicCard({ topic, onClick }: TopicCardProps) {
|
||||||
<div className="mt-4 pt-4 border-t border-gray-100">
|
<div className="mt-4 pt-4 border-t border-gray-100">
|
||||||
<div className="flex items-center justify-between text-sm text-gray-500">
|
<div className="flex items-center justify-between text-sm text-gray-500">
|
||||||
<span>
|
<span>
|
||||||
Last reply by{' '}
|
{translate('::App.Forum.TopicManagement.Lastreplyby')}{' '}
|
||||||
<span className="font-medium text-gray-700">{topic.lastPostUserName}</span>
|
<span className="font-medium text-gray-700">{topic.lastPostUserName}</span>
|
||||||
{' '}
|
{' '}
|
||||||
<span>{formatDate(topic.lastPostDate)}</span>
|
<span>{formatDate(topic.lastPostDate)}</span>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { ForumPostCard } from './ForumPostCard'
|
||||||
import { ForumCategoryCard } from './ForumCategoryCard'
|
import { ForumCategoryCard } from './ForumCategoryCard'
|
||||||
import { ForumTopicCard } from './ForumTopicCard'
|
import { ForumTopicCard } from './ForumTopicCard'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
||||||
interface ForumViewProps {
|
interface ForumViewProps {
|
||||||
categories: ForumCategory[]
|
categories: ForumCategory[]
|
||||||
|
|
@ -58,6 +59,7 @@ export function ForumView({
|
||||||
onTopicSelect,
|
onTopicSelect,
|
||||||
onViewStateChange,
|
onViewStateChange,
|
||||||
}: ForumViewProps) {
|
}: ForumViewProps) {
|
||||||
|
const { translate } = useLocalization()
|
||||||
const [localViewState, setLocalViewState] = useState<'categories' | 'topics' | 'posts'>(
|
const [localViewState, setLocalViewState] = useState<'categories' | 'topics' | 'posts'>(
|
||||||
'categories',
|
'categories',
|
||||||
)
|
)
|
||||||
|
|
@ -356,7 +358,7 @@ export function ForumView({
|
||||||
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
className="flex items-center space-x-2 bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
<span>New Topic</span>
|
<span>{translate('::App.Forum.TopicManagement.NewTopic')}</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{viewState === 'posts' && selectedTopic && !selectedTopic.isLocked && (
|
{viewState === 'posts' && selectedTopic && !selectedTopic.isLocked && (
|
||||||
|
|
@ -365,7 +367,7 @@ export function ForumView({
|
||||||
className="flex items-center space-x-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors"
|
className="flex items-center space-x-2 bg-emerald-600 text-white px-4 py-2 rounded-lg hover:bg-emerald-700 transition-colors"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4" />
|
<Plus className="w-4 h-4" />
|
||||||
<span>New Post</span>
|
<span>{translate('::App.Forum.PostManagement.NewPost')}</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -375,7 +377,7 @@ export function ForumView({
|
||||||
className="hidden md:flex items-center space-x-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
|
className="hidden md:flex items-center space-x-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
|
||||||
>
|
>
|
||||||
<Search className="w-4 h-4 text-gray-400" />
|
<Search className="w-4 h-4 text-gray-400" />
|
||||||
<span className="text-gray-500">Search topics...</span>
|
<span className="text-gray-500">{translate('::App.Forum.TopicManagement.Searchtopics')}</span>
|
||||||
<kbd className="hidden sm:inline-block px-2 py-1 text-xs font-semibold text-gray-500 bg-gray-100 border border-gray-200 rounded">
|
<kbd className="hidden sm:inline-block px-2 py-1 text-xs font-semibold text-gray-500 bg-gray-100 border border-gray-200 rounded">
|
||||||
⌘K
|
⌘K
|
||||||
</kbd>
|
</kbd>
|
||||||
|
|
@ -452,7 +454,7 @@ export function ForumView({
|
||||||
isAcceptedAnswer: false,
|
isAcceptedAnswer: false,
|
||||||
parentPostId: undefined,
|
parentPostId: undefined,
|
||||||
creationTime: selectedTopic.creationTime,
|
creationTime: selectedTopic.creationTime,
|
||||||
tenantId: selectedTopic.tenantId
|
tenantId: selectedTopic.tenantId,
|
||||||
}}
|
}}
|
||||||
onLike={handleLike}
|
onLike={handleLike}
|
||||||
onReply={handleReply}
|
onReply={handleReply}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import DataGrid, {
|
||||||
Sorting,
|
Sorting,
|
||||||
Summary,
|
Summary,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
TotalItem,
|
TotalItem
|
||||||
} from 'devextreme-react/data-grid'
|
} from 'devextreme-react/data-grid'
|
||||||
import { Item } from 'devextreme-react/toolbar'
|
import { Item } from 'devextreme-react/toolbar'
|
||||||
import { DataType } from 'devextreme/common'
|
import { DataType } from 'devextreme/common'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue