MenuGroup Entity ve Seeder

This commit is contained in:
Sedat Öztürk 2026-03-17 22:56:34 +03:00
parent ffa3ff2d63
commit cedb535734
20 changed files with 431 additions and 59 deletions

View file

@ -164,6 +164,14 @@ public static class LookupQueryValues
$"FROM \"AbpPermissionGroups\" " +
$"ORDER BY \"Name\";";
public static string MenuGroupValues =
$"SELECT " +
$"\"Id\" AS \"Key\", " +
$"\"Name\" AS \"Name\" " +
$"FROM \"{TableNameResolver.GetFullTableName(nameof(TableNameEnum.MenuGroup))}\" " +
$"WHERE \"IsDeleted\" = 'false' " +
$"ORDER BY \"Name\";";
public static string MenuCodeValues =
$"SELECT " +
$"\"Code\" AS \"Key\", " +

View file

@ -1386,6 +1386,12 @@
"en": "Menu List",
"tr": "Menü Listesi"
},
{
"resourceName": "Platform",
"key": "App.Menus.MenuGroup",
"en": "Menu Groups",
"tr": "Menü Grupları"
},
{
"resourceName": "Platform",
"key": "App.Menus.Manager",

View file

@ -206,7 +206,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
ColumnOptionJson = DefaultColumnOptionJson(),
PermissionJson = DefaultPermissionJson(AbpIdentity.Permissions.Create, listFormName, AbpIdentity.Permissions.Update, AbpIdentity.Permissions.Delete, AbpIdentity.Permissions.Export, AbpIdentity.Permissions.Import, AbpIdentity.Permissions.Note),
PagerOptionJson = DefaultPagerOptionJson,
EditingOptionJson = DefaultEditingOptionJson(listFormName, 600, 500, true, true, true, true, false),
EditingOptionJson = DefaultEditingOptionJson(listFormName, 600, 600, true, true, true, true, false),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>()
{
new() {
@ -236,7 +236,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.Guid,
FieldName = "Id",
CaptionName = "App.Listform.ListformField.Id",
CaptionName = "App.Listform.ListformField.Id",
Width = 100,
ListOrderNo = 1,
Visible = false,
@ -251,7 +251,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "GroupName",
CaptionName = "App.Listform.ListformField.GroupName",
CaptionName = "App.Listform.ListformField.GroupName",
Width = 300,
ListOrderNo = 2,
Visible = true,
@ -266,7 +266,6 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
ValueExpr = "Key",
LookupQuery = LookupQueryValues.PermissionGroupValues
}),
ValidationRuleJson = DefaultValidationRuleRequiredJson,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(AbpIdentity.Permissions.Create, AbpIdentity.Permissions.Default, AbpIdentity.Permissions.Update, true, true, false),
PivotSettingsJson = DefaultPivotSettingsJson
@ -276,13 +275,19 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "ParentName",
CaptionName = "App.Listform.ListformField.ParentName",
CaptionName = "App.Listform.ListformField.ParentName",
Width = 300,
ListOrderNo = 3,
Visible = true,
IsActive = true,
IsDeleted = false,
AllowSearch = true,
LookupJson = JsonSerializer.Serialize(new LookupDto {
DataSourceType = UiLookupDataSourceTypeEnum.Query,
DisplayExpr = "Name",
ValueExpr = "Key",
LookupQuery = LookupQueryValues.PermissionNameValues
}),
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(AbpIdentity.Permissions.Create, AbpIdentity.Permissions.Default, AbpIdentity.Permissions.Update, true, true, false),
PivotSettingsJson = DefaultPivotSettingsJson
@ -292,7 +297,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Name",
CaptionName = "App.Listform.ListformField.Name",
CaptionName = "App.Listform.ListformField.Name",
Width = 300,
ListOrderNo = 4,
Visible = true,
@ -308,7 +313,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "DisplayName",
CaptionName = "App.Listform.ListformField.DisplayName",
CaptionName = "App.Listform.ListformField.DisplayName",
Width = 400,
ListOrderNo = 5,
Visible = true,
@ -331,7 +336,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.Boolean,
FieldName = "IsEnabled",
CaptionName = "App.Listform.ListformField.IsEnabled",
CaptionName = "App.Listform.ListformField.IsEnabled",
Width = 100,
ListOrderNo = 6,
Visible = true,
@ -346,7 +351,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
CultureName = LanguageCodes.En,
SourceDbType = DbType.Int16,
FieldName = "MultiTenancySide",
CaptionName = "App.Listform.ListformField.MultiTenancySide",
CaptionName = "App.Listform.ListformField.MultiTenancySide",
Width = 100,
ListOrderNo = 7,
Visible = true,
@ -381,13 +386,10 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
IsDeleted = false,
LookupJson = JsonSerializer.Serialize(new LookupDto
{
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
DataSourceType = UiLookupDataSourceTypeEnum.Query,
DisplayExpr = "name",
ValueExpr = "key",
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
new () { Key="Kurs",Name="Kurs" },
new () { Key="Erp",Name="Erp" },
}),
LookupQuery = LookupQueryValues.MenuGroupValues
}),
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(AbpIdentity.Permissions.Create, AbpIdentity.Permissions.Default, AbpIdentity.Permissions.Update, true, true, false),
@ -788,7 +790,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
PermissionJson = DefaultPermissionJson(PlatformConsts.IdentityPermissions.Users.Create, listFormName, PlatformConsts.IdentityPermissions.Users.Update, PlatformConsts.IdentityPermissions.Users.Delete, PlatformConsts.IdentityPermissions.Users.Export, PlatformConsts.IdentityPermissions.Users.Import, PlatformConsts.IdentityPermissions.Users.Note),
DeleteCommand = $"UPDATE \"AbpUsers\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id",
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 450, true, true, true, true, false),
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 550, true, true, true, true, false),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>() {
new () { Order=1,ColCount=1,ColSpan=1,ItemType="group",Items=[
new EditingFormItemDto { Order=1, DataField="Email", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox },

View file

@ -538,13 +538,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
IsActive = true,
IsDeleted = false,
LookupJson = JsonSerializer.Serialize(new LookupDto {
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
DataSourceType = UiLookupDataSourceTypeEnum.Query,
DisplayExpr = "name",
ValueExpr = "key",
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
new () { Key="Kurs", Name="Kurs" },
new () { Key="Erp", Name="Erp" },
}),
LookupQuery = LookupQueryValues.MenuGroupValues,
}),
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(TenantManagementPermissions.Tenants.Create, TenantManagementPermissions.Tenants.Default, TenantManagementPermissions.Tenants.Update, true, true, false),
@ -5065,6 +5062,98 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
}
#endregion
#region MenuGroup
listFormName = AppCodes.Menus.MenuGroup;
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
{
var listForm = await _listFormRepository.InsertAsync(
new ListForm
{
ListFormType = ListFormTypeEnum.List,
PageSize = 10,
ExportJson = DefaultExportJson,
IsSubForm = false,
ShowNote = true,
LayoutJson = DefaultLayoutJson(),
CultureName = LanguageCodes.En,
ListFormCode = listFormName,
Name = listFormName,
Title = listFormName,
DataSourceCode = SeedConsts.DataSources.DefaultCode,
IsTenant = false,
IsBranch = false,
IsOrganizationUnit = false,
Description = listFormName,
SelectCommandType = SelectCommandTypeEnum.Table,
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.MenuGroup)),
KeyFieldName = "Id",
KeyFieldDbSourceType = DbType.String,
SortMode = GridOptions.SortModeSingle,
DefaultFilter = DefaultFilterJson,
FilterRowJson = DefaultFilterRowJson,
HeaderFilterJson = DefaultHeaderFilterJson,
SearchPanelJson = DefaultSearchPanelJson,
GroupPanelJson = JsonSerializer.Serialize(new { Visible = false }),
SelectionJson = DefaultSelectionSingleJson,
ColumnOptionJson = DefaultColumnOptionJson(),
PermissionJson = DefaultPermissionJson(listFormName),
PagerOptionJson = DefaultPagerOptionJson,
EditingOptionJson = DefaultEditingOptionJson(listFormName, 500, 350, true, true, true, true, false),
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
{
new() { Order = 1, ColCount = 1, ColSpan = 1, ItemType = "group", Items =
[
new EditingFormItemDto { Order = 1, DataField = "Name", ColSpan = 1, IsRequired = true, EditorType2 = EditorTypes.dxTextBox },
]
}
}),
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.MenuGroup)),
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
});
#region MenuGroup Fields
await _listFormFieldRepository.InsertManyAsync([
new()
{
ListFormCode = listForm.ListFormCode,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Id",
CaptionName = "App.Listform.ListformField.Id",
Width = 100,
ListOrderNo = 1,
Visible = false,
IsActive = true,
IsDeleted = false,
ValidationRuleJson = DefaultValidationRuleRequiredJson,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
PivotSettingsJson = DefaultPivotSettingsJson,
},
new()
{
ListFormCode = listForm.ListFormCode,
CultureName = LanguageCodes.En,
SourceDbType = DbType.String,
FieldName = "Name",
CaptionName = "App.Listform.ListformField.Name",
Width = 300,
ListOrderNo = 2,
Visible = true,
IsActive = true,
IsDeleted = false,
AllowSearch = true,
ValidationRuleJson = DefaultValidationRuleRequiredJson,
ColumnCustomizationJson = DefaultColumnCustomizationJson,
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
PivotSettingsJson = DefaultPivotSettingsJson,
},
]);
#endregion
}
#endregion
#region Menu
listFormName = AppCodes.Menus.Menu;
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))

View file

@ -19,6 +19,11 @@ public class RouteSeedDto
public string[] Authority { get; set; }
}
public class MenuGroupSeedDto
{
public string Name { get; set; }
}
public class MenuSeedDto
{
public string ParentCode { get; set; }
@ -36,20 +41,24 @@ public class MenuSeederDto
{
public List<RouteSeedDto> Routes { get; set; }
public List<MenuSeedDto> Menus { get; set; }
public List<MenuGroupSeedDto> MenuGroups { get; set; }
}
public class MenuDataSeeder : IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Route, Guid> _routeRepository;
private readonly IRepository<Menu, Guid> _menuRepository;
private readonly IRepository<MenuGroup, string> _menuGroupRepository;
public MenuDataSeeder(
IRepository<Route, Guid> routeRepository,
IRepository<Menu, Guid> menuRepository
IRepository<Menu, Guid> menuRepository,
IRepository<MenuGroup, string> menuGroupRepository
)
{
_routeRepository = routeRepository;
_menuRepository = menuRepository;
_menuGroupRepository = menuGroupRepository;
}
public async Task SeedAsync(DataSeedContext context)
@ -77,6 +86,19 @@ public class MenuDataSeeder : IDataSeedContributor, ITransientDependency
}
}
foreach (var item in items.MenuGroups)
{
var exists = await _menuGroupRepository.AnyAsync(x => x.Name == item.Name);
if (!exists)
{
await _menuGroupRepository.InsertAsync(new MenuGroup(item.Name)
{
Name = item.Name
});
}
}
foreach (var item in items.Menus)
{
var exists = await _menuRepository.AnyAsync(x => x.Code == item.Code);

View file

@ -400,6 +400,14 @@
"authority": ["App.Contact"]
}
],
"MenuGroups": [
{
"Name": "Erp"
},
{
"Name": "Kurs"
}
],
"Menus": [
{
"ParentCode": null,
@ -784,11 +792,21 @@
"RequiredPermissionName": "App.Routes",
"IsDisabled": false
},
{
"ParentCode": "App.Menus",
"Code": "App.Menus.MenuGroup",
"DisplayName": "App.Menus.MenuGroup",
"Order": 2,
"Url": "/admin/list/App.Menus.MenuGroup",
"Icon": "FcGrid",
"RequiredPermissionName": "App.Menus.MenuGroup",
"IsDisabled": false
},
{
"ParentCode": "App.Menus",
"Code": "App.Menus.Menu",
"DisplayName": "App.Menus.Menu",
"Order": 2,
"Order": 3,
"Url": "/admin/list/App.Menus.Menu",
"Icon": "FcMenu",
"RequiredPermissionName": "App.Menus.Menu",
@ -798,7 +816,7 @@
"ParentCode": "App.Menus",
"Code": "App.Menus.Manager",
"DisplayName": "App.Menus.Manager",
"Order": 3,
"Order": 4,
"Url": "/admin/menuManager",
"Icon": "FaRegListAlt",
"RequiredPermissionName": "App.Menus.Manager",

View file

@ -1549,7 +1549,6 @@
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Home",
@ -1577,7 +1576,6 @@
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Orders.Products",
@ -2109,6 +2107,69 @@
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup",
"ParentName": null,
"DisplayName": "App.Menus.MenuGroup",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup.Create",
"ParentName": "App.Menus.MenuGroup",
"DisplayName": "Create",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup.Delete",
"ParentName": "App.Menus.MenuGroup",
"DisplayName": "Delete",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup.Export",
"ParentName": "App.Menus.MenuGroup",
"DisplayName": "Export",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup.Import",
"ParentName": "App.Menus.MenuGroup",
"DisplayName": "Import",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup.Note",
"ParentName": "App.Menus.MenuGroup",
"DisplayName": "Note",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.MenuGroup.Update",
"ParentName": "App.Menus.MenuGroup",
"DisplayName": "Update",
"IsEnabled": true,
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.Menus.Menu",
@ -2271,7 +2332,6 @@
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Saas",
"Name": "App.DeveloperKit",
@ -2470,7 +2530,6 @@
"MultiTenancySide": 2,
"MenuGroup": "Erp|Kurs"
},
{
"GroupName": "App.Administration",
"Name": "App.Setting",

View file

@ -18,6 +18,7 @@ public enum TableNameEnum
BranchUsers,
GlobalSearch,
Route,
MenuGroup,
Menu,
DataSource,
ListForm,

View file

@ -60,6 +60,7 @@ public static class TableNameResolver
{ nameof(TableNameEnum.Demo), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.Contact), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.Route), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.MenuGroup), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.Menu), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.CrudEndpoint), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.CustomEndpoint), (TablePrefix.PlatformByName, MenuPrefix.Saas) },

View file

@ -341,6 +341,7 @@ public static class SeedConsts
{
public const string Default = Prefix.App + ".Menus";
public const string MenuGroup = Default + ".MenuGroup";
public const string Menu = Default + ".Menu";
public const string Manager = Default + ".Manager";
}

View file

@ -23,4 +23,3 @@ public class Menu : FullAuditedEntity<Guid>
public string RoleId { get; set; } // External role id (orn: ihracat)
public string CultureName { get; set; } // Bu tanim hangi dil icin "en", "tr"
}

View file

@ -0,0 +1,13 @@
using Volo.Abp.Domain.Entities.Auditing;
namespace Sozsoft.Platform.Entities;
public class MenuGroup : FullAuditedEntity<string>
{
public string Name { get; set; }
public MenuGroup(string id)
{
Id = id;
}
}

View file

@ -1,6 +1,5 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace Sozsoft.Platform.Entities;

View file

@ -48,6 +48,7 @@ public class PlatformDbContext :
public DbSet<GlobalSearch> GlobalSearchs { get; set; }
public DbSet<Route> Routes { get; set; }
public DbSet<Menu> Menus { get; set; }
public DbSet<MenuGroup> MenuGroups { get; set; }
public DbSet<DataSource> DataSources { get; set; }
public DbSet<ListForm> ListForms { get; set; }
public DbSet<ListFormField> ListFormFields { get; set; }
@ -227,6 +228,14 @@ public class PlatformDbContext :
);
});
builder.Entity<MenuGroup>(b =>
{
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.MenuGroup)), Prefix.DbSchema);
b.ConfigureByConvention();
b.Property(a => a.Name).IsRequired().HasMaxLength(128);
});
builder.Entity<Menu>(b =>
{
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.Menu)), Prefix.DbSchema);

View file

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Sozsoft.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20260317120000_Initial")]
[Migration("20260317181749_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -2954,6 +2954,51 @@ namespace Sozsoft.Platform.Migrations
b.ToTable("Sas_H_Menu", (string)null);
});
modelBuilder.Entity("Sozsoft.Platform.Entities.MenuGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("Id");
b.ToTable("Sas_H_MenuGroup", (string)null);
});
modelBuilder.Entity("Sozsoft.Platform.Entities.Note", b =>
{
b.Property<Guid>("Id")

View file

@ -1228,6 +1228,25 @@ namespace Sozsoft.Platform.Migrations
table.PrimaryKey("PK_Sas_H_Menu", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Sas_H_MenuGroup",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Sas_H_MenuGroup", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Sas_H_NotificationRule",
columns: table => new
@ -3101,6 +3120,9 @@ namespace Sozsoft.Platform.Migrations
migrationBuilder.DropTable(
name: "Sas_H_Menu");
migrationBuilder.DropTable(
name: "Sas_H_MenuGroup");
migrationBuilder.DropTable(
name: "Sas_H_Notification");

View file

@ -2951,6 +2951,51 @@ namespace Sozsoft.Platform.Migrations
b.ToTable("Sas_H_Menu", (string)null);
});
modelBuilder.Entity("Sozsoft.Platform.Entities.MenuGroup", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("bit")
.HasDefaultValue(false)
.HasColumnName("IsDeleted");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.HasKey("Id");
b.ToTable("Sas_H_MenuGroup", (string)null);
});
modelBuilder.Entity("Sozsoft.Platform.Entities.Note", b =>
{
b.Property<Guid>("Id")

View file

@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react'
import React, { useState } from 'react'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { MenuItem } from '@/proxy/menus/menu'
@ -74,7 +74,9 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
const [isExpanded, setIsExpanded] = useState(true)
const [isModalOpen, setIsModalOpen] = useState(false)
const [formData, setFormData] = useState<Partial<MenuDto>>({
const [modalMode, setModalMode] = useState<'create' | 'edit'>('create')
const getCreateInitialValues = (): Partial<MenuDto> => ({
code: '',
displayName: '',
order: (item.children?.length || 0) + 1,
@ -88,15 +90,39 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
elementId: '',
})
const getEditInitialValues = (): Partial<MenuDto> => ({
id: item.id,
code: item.code || '',
displayName: item.displayName || '',
order: item.order,
parentCode: item.parentCode || '',
url: item.url || '',
icon: item.icon || '',
cssClass: item.cssClass || '',
requiredPermissionName: item.requiredPermissionName || '',
target: item.target || '',
isDisabled: item.isDisabled ?? false,
elementId: item.elementId || '',
})
const [formData, setFormData] = useState<Partial<MenuDto>>(getCreateInitialValues())
const toggleExpanded = () => {
if (!isDesignMode) setIsExpanded(!isExpanded)
}
const handleCreate = async () => {
const menuService = new MenuService()
await menuService.create(formData as MenuDto)
setIsModalOpen(false)
refetch()
const openCreateModal = () => {
setModalMode('create')
setFormData(getCreateInitialValues())
setIsModalOpen(true)
}
const openEditModal = (event: React.MouseEvent) => {
if (!isDesignMode) return
event.stopPropagation()
setModalMode('edit')
setFormData(getEditInitialValues())
setIsModalOpen(true)
}
const handleDelete = async () => {
@ -123,7 +149,7 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
>
{isDesignMode && (
<div className="flex gap-2 items-center mr-2">
<button onClick={() => setIsModalOpen(true)} title="New Item">
<button onClick={openCreateModal} title="New Item">
<FaPlus size={16} className="text-green-600 hover:text-green-800" />
</button>
<button onClick={handleDelete} title="Delete Item">
@ -141,14 +167,17 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
)}
</div>
<span
<button
type="button"
onClick={openEditModal}
className={`
truncate text-gray-800 leading-6 text-sm
truncate text-gray-800 leading-6 text-sm text-left
${item.children && item.children.length > 0 ? 'font-semibold' : 'font-normal'}
${isDesignMode ? 'hover:text-blue-600' : ''}
`}
>
{translate('::' + item.displayName)}
</span>
</button>
{item.url && <FaExternalLinkAlt size={12} className="flex-shrink-0 text-gray-400" />}
</div>
@ -177,7 +206,9 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
onRequestClose={() => setIsModalOpen(false)}
width={600}
>
<h5 className="mb-4">{translate('::New Item')}</h5>
<h5 className="mb-4">
{modalMode === 'edit' ? translate('::Edit Menu Item') : translate('::New Item')}
</h5>
<Formik
validationSchema={validationSchema}
initialValues={formData}
@ -185,10 +216,14 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
onSubmit={async (values, { setSubmitting }) => {
try {
const menuService = new MenuService()
await menuService.create(values as MenuDto)
if (modalMode === 'edit' && item.id) {
await menuService.update(item.id, values as MenuDto)
} else {
await menuService.create(values as MenuDto)
}
toast.push(
<Notification title="Başarılı" type="success">
{translate('::KayitEklendi')}
{modalMode === 'edit' ? translate('::KayitGuncellendi') : translate('::KayitEklendi')}
</Notification>,
{ placement: 'top-end' },
)
@ -206,13 +241,12 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
}
}}
>
{({ values, errors, touched, isSubmitting, handleChange }) => (
{({ values, isSubmitting }) => (
<Form>
<FormContainer>
<FormItem label="Code *" className="mb-2">
<Field
type="text"
au
name="code"
component={Input}
className="h-8 text-sm px-2"
@ -247,7 +281,11 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
</FormItem>
<FormItem label="Parent Code" className="mb-2">
<Input disabled value={item.code} className="h-8 text-sm px-2 bg-gray-100" />
<Input
disabled
value={values.parentCode || ''}
className="h-8 text-sm px-2 bg-gray-100"
/>
</FormItem>
<FormItem label="CSS Class" className="mb-2">
@ -308,7 +346,7 @@ export const MenuItemComponent: React.FC<MenuItemComponentProps> = ({
{translate('::Cancel')}
</Button>
<Button type="submit" variant="solid" size="sm" loading={isSubmitting}>
{translate('::Create')}
{modalMode === 'edit' ? translate('::Save') : translate('::Create')}
</Button>
</div>
</FormContainer>

View file

@ -2,16 +2,11 @@ import React, { useState } from 'react'
import { SortableMenuTree } from './SortableMenuTree'
import { MenuItem } from '@/proxy/menus/menu'
import { useMenuData } from '@/utils/hooks/useMenuData'
import {
FaRegBell,
FaSpinner,
FaBars,
FaRegSave
} from 'react-icons/fa';
import { FaRegBell, FaSpinner, FaBars, FaRegSave } from 'react-icons/fa'
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { APP_NAME } from '@/constants/app.constant';
import { APP_NAME } from '@/constants/app.constant'
export const MenuManager = () => {
const { menuItems, setMenuItems, loading, error, refetch, saveMenuData } = useMenuData()
@ -95,7 +90,7 @@ export const MenuManager = () => {
></Helmet>
<div className="bg-white rounded px-2 sm:px-2 lg:px-3 py-3">
<div className="flex items-center justify-between mb-6 flex-wrap gap-4">
<div className="flex items-center justify-between mb-2 flex-wrap gap-4">
{/* Sol kısım: Başlık */}
<div className="flex items-center gap-2">
<FaBars size={20} className="text-gray-600" />

View file

@ -942,7 +942,7 @@ const Home: React.FC = () => {
isDesignMode={isDesignMode}
onSelect={handleSelectBlock}
>
<div className="relative min-h-screen overflow-hidden">
<div className="relative min-h-screen p-20 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-blue-900 via-indigo-900 to-purple-900"></div>
<div
className="absolute inset-0 opacity-20"
@ -976,7 +976,7 @@ const Home: React.FC = () => {
}}
className="h-full"
>
<div className={`container mx-auto px-4 pt-32 ${slide.styleClass || ''}`}>
<div className={`container mx-auto px-4 pt-16 ${slide.styleClass || ''}`}>
<div className="max-w-4xl mx-auto text-center">
<h1 className="text-3xl md:text-6xl font-bold mb-6 text-white animate-fade-in">
{slide.title}