MenuGroup güncellemesi

This commit is contained in:
Sedat Öztürk 2025-10-12 21:45:03 +03:00
parent a6490b5153
commit 8c0863b11c
9 changed files with 970 additions and 932 deletions

View file

@ -54,7 +54,6 @@ public class MenuAppService : CrudAppService<
query = query.Where(a => !a.IsDisabled);
//Tenant üzerinden MenuGrup bilgisi alınıp sadece o menüler listelenecek
// 🔹 Tenant'a göre filtrele
if (CurrentTenant.IsAvailable)
{
var tenant = await _tenantRepository.FindAsync(CurrentTenant.Id.Value);

View file

@ -25,7 +25,7 @@ public class PlatformPermissionGroupDto : PermissionGroupDto
public class PlatformPermissionGrantInfoDto : PermissionGrantInfoDto
{
public string[] MenuGroup { get; set; } = [];
public string MenuGroup { get; set; } = string.Empty;
}
[Dependency(ReplaceServices = true)]
@ -75,7 +75,7 @@ public class PlatformPermissionAppService : PermissionAppService
AllowedProviders = permission.AllowedProviders,
GrantedProviders = permission.GrantedProviders,
IsGranted = permission.IsGranted,
MenuGroup = JsonSerializer.Deserialize<string[]>(menuGroup) ?? []
MenuGroup = menuGroup ?? string.Empty
};
newGroup.Permissions.Add(newPermission);

File diff suppressed because it is too large Load diff

View file

@ -82,7 +82,7 @@ public class PermissionDefinitionRecordSeedDto
public string DisplayName { get; set; }
public bool IsEnabled { get; set; }
public int MultiTenancySide { get; set; }
public string[] MenuGroup { get; set; }
public string MenuGroup { get; set; }
}
public class CurrencySeedDto

View file

@ -2221,8 +2221,8 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
}),
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
new() {
Hint = "Manage",
Text = "Manage",
Hint = "Seed",
Text = "Seed",
AuthName = TenantManagementPermissions.Tenants.ManageConnectionStrings,
DialogName = "TenantsConnectionString",
DialogParameters = JsonSerializer.Serialize(new {
@ -4099,11 +4099,6 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
{
Visible = true
}),
SelectionJson = JsonSerializer.Serialize(new SelectionDto
{
Mode = GridOptions.SelectionModeSingle,
AllowSelectAll = false
}),
ColumnOptionJson = JsonSerializer.Serialize(new
{
ColumnFixingEnabled = true,

View file

@ -1,5 +1,5 @@
using System;
using System.Text.Json;
using System.Linq;
using Volo.Abp.Data;
using Volo.Abp.PermissionManagement;
@ -7,17 +7,45 @@ namespace Kurs.Platform.Extensions;
public static class AbpPermissionsExtensions
{
public static void SetMenuGroup(this PermissionDefinitionRecord permission, string[] menuGroup)
/// <summary>
/// Menü gruplarını pipe karakteriyle ayrılmış string olarak kaydeder. (örnek: "Erp|Kurs")
/// </summary>
public static void SetMenuGroup(this PermissionDefinitionRecord permission, string menuGroup)
{
var json = JsonSerializer.Serialize(menuGroup);
permission.SetProperty(PlatformConsts.Permissions.MenuGroup, json);
if (string.IsNullOrWhiteSpace(menuGroup))
{
permission.SetProperty(PlatformConsts.Permissions.MenuGroup, null);
return;
}
// 🔹 Gereksiz boşlukları temizle
var cleaned = string.Join(
'|',
menuGroup
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Distinct()
);
// 🔹 Veritabanına "Erp|Kurs" formatında kaydet
permission.SetProperty(PlatformConsts.Permissions.MenuGroup, cleaned);
}
/// <summary>
/// Menü gruplarını veritabanındaki pipe formatından string[] olarak döndürür. (örnek: "Erp|Kurs" → ["Erp", "Kurs"])
/// </summary>
public static string[] GetMenuGroup(this PermissionDefinitionRecord permission)
{
var json = permission.GetProperty<string>(PlatformConsts.Permissions.MenuGroup);
return string.IsNullOrWhiteSpace(json)
? []
: JsonSerializer.Deserialize<string[]>(json);
var value = permission.GetProperty<string>(PlatformConsts.Permissions.MenuGroup);
if (string.IsNullOrWhiteSpace(value))
{
return Array.Empty<string>();
}
// 🔹 "Erp|Kurs" -> ["Erp", "Kurs"]
return value
.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Distinct()
.ToArray();
}
}

View file

@ -1,18 +1,24 @@
import * as fc from 'react-icons/fc'
import * as fa from 'react-icons/fa'
import type { ComponentType } from 'react'
export type NavigationIcons = Record<string, React.ComponentType<any>>;
export type NavigationIcons = Record<string, ComponentType<any>>
const navigationIcon: NavigationIcons = {};
const navigationIcon: NavigationIcons = {}
// fc (Font Awesome) ikonlarıyla dinamik olarak navigationIcon nesnesini doldur
for (const [key, Icon] of Object.entries(fc)) {
navigationIcon[key] = Icon; // Icon bileşenini doğrudan kullanıyoruz
function registerIcons(iconModule: Record<string, any>) {
for (const [key, Icon] of Object.entries(iconModule)) {
if (
Icon &&
(typeof Icon === 'function' ||
(typeof Icon === 'object' && 'render' in Icon))
) {
navigationIcon[key] = Icon as ComponentType<any>
}
}
}
// fa (Font Awesome) ikonlarıyla navigationIcon nesnesini doldur
for (const [key, Icon] of Object.entries(fa)) {
navigationIcon[key] = Icon; // Icon bileşenini doğrudan kullanıyoruz
}
registerIcons(fc)
registerIcons(fa)
export default navigationIcon;
export default navigationIcon

View file

@ -121,21 +121,23 @@ const FormButtons = (props: {
item.name != 'deleteSelectedRecords',
)
.map((item, i) => {
const IconComp = navigationIcon[item.options?.icon] // React bileşeni olabilir ya da undefined
const hasValidIcon =
IconComp &&
(typeof IconComp === 'function' ||
(typeof IconComp === 'object' && 'render' in IconComp))
return (
<Button
key={'toolbarButton-' + i}
variant="default"
size="xs"
{...(item.options?.icon
? {
icon: React.createElement(navigationIcon[item.options.icon], {
className: 'text-gray-400',
}),
}
: {})}
onClick={item.options.onClick}
icon={
hasValidIcon ? <IconComp className="text-gray-400" /> : null // 🔒 güvenli render
}
onClick={item.options?.onClick}
>
{item.options.text}
{item.options?.text}
</Button>
)
})}

View file

@ -8,6 +8,7 @@ import { ToolbarItem } from 'devextreme/ui/data_grid_types'
import { useEffect, useState } from 'react'
import { useDialogContext } from '../shared/DialogContext'
import { usePWA } from '@/utils/hooks/usePWA'
import { text } from 'stream/consumers'
type ToolbarModalData = {
open: boolean
@ -68,6 +69,7 @@ const useToolbar = ({
options: {
icon: 'refresh',
onClick: refreshData,
text: translate('::ListForms.ListForm.Refresh'),
},
location: 'after',
})