Menu list ve Permission listesine MenuGroup eklendi
This commit is contained in:
parent
c0aec43620
commit
3e6cce6982
30 changed files with 2474 additions and 1164 deletions
|
|
@ -27,4 +27,5 @@ public class CreateUpdateTenantInput
|
||||||
public string Fax { get; set; }
|
public string Fax { get; set; }
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
public string Website { get; set; }
|
public string Website { get; set; }
|
||||||
|
public string MenuGroup { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,5 @@ public class MenuDto : FullAuditedEntityDto<Guid>
|
||||||
public string UserId { get; set; } // External kullanici id (orn: ali.akman. ihtiyaca gore guid veya int de olabilir)
|
public string UserId { get; set; } // External kullanici id (orn: ali.akman. ihtiyaca gore guid veya int de olabilir)
|
||||||
public string RoleId { get; set; } // External role id (orn: ihracat)
|
public string RoleId { get; set; } // External role id (orn: ihracat)
|
||||||
public string CultureName { get; set; } // Bu tanim hangi dil icin "en", "tr"
|
public string CultureName { get; set; } // Bu tanim hangi dil icin "en", "tr"
|
||||||
|
public string[] Group { get; set; } // Menu grubu (her tenant farklı menu grupları kullanabilir)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,5 @@ public class CustomTenantDto
|
||||||
public string Fax { get; set; }
|
public string Fax { get; set; }
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
public string Website { get; set; }
|
public string Website { get; set; }
|
||||||
|
public string MenuGroup { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
entity.SetFax(input.Data.Fax);
|
entity.SetFax(input.Data.Fax);
|
||||||
entity.SetEmail(input.Data.Email);
|
entity.SetEmail(input.Data.Email);
|
||||||
entity.SetWebsite(input.Data.Website);
|
entity.SetWebsite(input.Data.Website);
|
||||||
|
entity.SetMenuGroup(input.Data.MenuGroup);
|
||||||
|
|
||||||
await tenantRepository.UpdateAsync(entity, autoSave: true);
|
await tenantRepository.UpdateAsync(entity, autoSave: true);
|
||||||
}
|
}
|
||||||
|
|
@ -163,6 +164,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
||||||
entity.SetFax(input.Data.Fax);
|
entity.SetFax(input.Data.Fax);
|
||||||
entity.SetEmail(input.Data.Email);
|
entity.SetEmail(input.Data.Email);
|
||||||
entity.SetWebsite(input.Data.Website);
|
entity.SetWebsite(input.Data.Website);
|
||||||
|
entity.SetMenuGroup(input.Data.MenuGroup);
|
||||||
|
|
||||||
await tenantRepository.UpdateAsync(entity, autoSave: true);
|
await tenantRepository.UpdateAsync(entity, autoSave: true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,19 @@ public class MenuAppService : CrudAppService<
|
||||||
DeletePolicyName = $"{AppCodes.Menus.Menu}.Delete";
|
DeletePolicyName = $"{AppCodes.Menus.Menu}.Delete";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<PagedResultDto<MenuDto>> GetListAsync(PagedAndSortedResultRequestDto input)
|
public async Task<PagedResultDto<MenuDto>> GetListByGroupAsync(PagedAndSortedResultRequestDto input, string? group = null)
|
||||||
{
|
{
|
||||||
await CheckGetListPolicyAsync();
|
await CheckGetListPolicyAsync();
|
||||||
|
|
||||||
var query = await CreateFilteredQueryAsync(input);
|
var query = await CreateFilteredQueryAsync(input);
|
||||||
query = query.Where(a => !a.IsDisabled);
|
query = query.Where(a => !a.IsDisabled);
|
||||||
|
|
||||||
|
// Group filtrelemesi ekle
|
||||||
|
if (!string.IsNullOrEmpty(group))
|
||||||
|
{
|
||||||
|
query = query.Where(a => a.Group.Contains(group) || a.Group.Any(g => g == group));
|
||||||
|
}
|
||||||
|
|
||||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
var totalCount = await AsyncExecuter.CountAsync(query);
|
||||||
|
|
||||||
var entities = new List<Menu>();
|
var entities = new List<Menu>();
|
||||||
|
|
@ -84,6 +91,11 @@ public class MenuAppService : CrudAppService<
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task<PagedResultDto<MenuDto>> GetListAsync(PagedAndSortedResultRequestDto input)
|
||||||
|
{
|
||||||
|
return await GetListByGroupAsync(input, null);
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<MenuDto> CreateAsync(MenuDto input)
|
public override async Task<MenuDto> CreateAsync(MenuDto input)
|
||||||
{
|
{
|
||||||
await CheckCreatePolicyAsync();
|
await CheckCreatePolicyAsync();
|
||||||
|
|
@ -150,7 +162,7 @@ public class MenuAppService : CrudAppService<
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var updated = await base.UpdateAsync(input.Id, input);
|
var updated = await base.UpdateAsync(input.Id, input);
|
||||||
result.Add(updated);
|
result.Add(updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Volo.Abp.Authorization.Permissions;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.SimpleStateChecking;
|
||||||
|
using Volo.Abp.PermissionManagement;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Volo.Abp;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.PermissionManagement;
|
||||||
|
|
||||||
|
public class PlatformGetPermissionListResultDto : GetPermissionListResultDto
|
||||||
|
{
|
||||||
|
// ABP’nin orijinalinde PermissionGroupDto kullanıyor,
|
||||||
|
// biz de kendi alt tipimizi yaratıyoruz.
|
||||||
|
public new List<PlatformPermissionGroupDto> Groups { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlatformPermissionGroupDto : PermissionGroupDto
|
||||||
|
{
|
||||||
|
public new List<PlatformPermissionGrantInfoDto> Permissions { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlatformPermissionGrantInfoDto : PermissionGrantInfoDto
|
||||||
|
{
|
||||||
|
public string[] MenuGroup { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
[Dependency(ReplaceServices = true)]
|
||||||
|
[RemoteService(false)]
|
||||||
|
public class PlatformPermissionAppService : PermissionAppService
|
||||||
|
{
|
||||||
|
public PlatformPermissionAppService(
|
||||||
|
IPermissionManager permissionManager,
|
||||||
|
IPermissionDefinitionManager permissionDefinitionManager,
|
||||||
|
IOptions<PermissionManagementOptions> options,
|
||||||
|
ISimpleStateCheckerManager<PermissionDefinition> simpleStateCheckerManager)
|
||||||
|
: base(permissionManager, permissionDefinitionManager, options, simpleStateCheckerManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<GetPermissionListResultDto> GetAsync(string providerName, string providerKey)
|
||||||
|
{
|
||||||
|
var baseResult = await base.GetAsync(providerName, providerKey);
|
||||||
|
var allDefinitions = await PermissionDefinitionManager.GetPermissionsAsync();
|
||||||
|
|
||||||
|
// Yeni tipte result
|
||||||
|
var result = new PlatformGetPermissionListResultDto
|
||||||
|
{
|
||||||
|
EntityDisplayName = baseResult.EntityDisplayName
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var group in baseResult.Groups)
|
||||||
|
{
|
||||||
|
var newGroup = new PlatformPermissionGroupDto
|
||||||
|
{
|
||||||
|
Name = group.Name,
|
||||||
|
DisplayName = group.DisplayName,
|
||||||
|
DisplayNameKey = group.DisplayNameKey,
|
||||||
|
DisplayNameResource = group.DisplayNameResource
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var permission in group.Permissions)
|
||||||
|
{
|
||||||
|
var definition = allDefinitions.FirstOrDefault(x => x.Name == permission.Name);
|
||||||
|
var menuGroup = definition?.Properties.GetOrDefault(PlatformConsts.Permissions.MenuGroup)?.ToString();
|
||||||
|
|
||||||
|
var newPermission = new PlatformPermissionGrantInfoDto
|
||||||
|
{
|
||||||
|
Name = permission.Name,
|
||||||
|
DisplayName = permission.DisplayName,
|
||||||
|
ParentName = permission.ParentName,
|
||||||
|
AllowedProviders = permission.AllowedProviders,
|
||||||
|
GrantedProviders = permission.GrantedProviders,
|
||||||
|
IsGranted = permission.IsGranted,
|
||||||
|
MenuGroup = JsonSerializer.Deserialize<string[]>(menuGroup) ?? []
|
||||||
|
};
|
||||||
|
|
||||||
|
newGroup.Permissions.Add(newPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Groups.Add(newGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -91,6 +91,7 @@ public class PlatformTenantAppService : TenantAppService, IPlatformTenantAppServ
|
||||||
dto.Fax = tenant.GetFax();
|
dto.Fax = tenant.GetFax();
|
||||||
dto.Email = tenant.GetEmail();
|
dto.Email = tenant.GetEmail();
|
||||||
dto.Website = tenant.GetWebsite();
|
dto.Website = tenant.GetWebsite();
|
||||||
|
dto.MenuGroup = tenant.GetMenuGroup();
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,7 @@ using EFCore.BulkExtensions;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Kurs.Platform.Public;
|
using Kurs.Platform.Public;
|
||||||
using static Kurs.Settings.SettingsConsts;
|
using static Kurs.Settings.SettingsConsts;
|
||||||
|
using Kurs.Platform.Extensions;
|
||||||
|
|
||||||
namespace Kurs.Platform.Data.Seeds;
|
namespace Kurs.Platform.Data.Seeds;
|
||||||
|
|
||||||
|
|
@ -468,7 +469,8 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
Url = item.Url,
|
Url = item.Url,
|
||||||
Icon = item.Icon,
|
Icon = item.Icon,
|
||||||
RequiredPermissionName = item.RequiredPermissionName,
|
RequiredPermissionName = item.RequiredPermissionName,
|
||||||
IsDisabled = item.IsDisabled
|
IsDisabled = item.IsDisabled,
|
||||||
|
Group = item.Group
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -493,15 +495,19 @@ public class HostDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
|
|
||||||
if (!exists)
|
if (!exists)
|
||||||
{
|
{
|
||||||
await _permissionRepository.InsertAsync(new PermissionDefinitionRecord
|
var perm = new PermissionDefinitionRecord
|
||||||
{
|
{
|
||||||
GroupName = item.GroupName,
|
GroupName = item.GroupName,
|
||||||
Name = item.Name,
|
Name = item.Name,
|
||||||
ParentName = string.IsNullOrWhiteSpace(item.ParentName) ? null : item.ParentName,
|
ParentName = string.IsNullOrWhiteSpace(item.ParentName) ? null : item.ParentName,
|
||||||
DisplayName = item.DisplayName,
|
DisplayName = item.DisplayName,
|
||||||
IsEnabled = item.IsEnabled,
|
IsEnabled = item.IsEnabled,
|
||||||
MultiTenancySide = (MultiTenancySides)item.MultiTenancySide
|
MultiTenancySide = (MultiTenancySides)item.MultiTenancySide,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
perm.SetMenuGroup(item.MenuGroup);
|
||||||
|
|
||||||
|
await _permissionRepository.InsertAsync(perm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ public class MenuSeedDto
|
||||||
public string Icon { get; set; }
|
public string Icon { get; set; }
|
||||||
public string RequiredPermissionName { get; set; }
|
public string RequiredPermissionName { get; set; }
|
||||||
public bool IsDisabled { get; set; }
|
public bool IsDisabled { get; set; }
|
||||||
|
public string[] Group { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PermissionGroupDefinitionRecordSeedDto
|
public class PermissionGroupDefinitionRecordSeedDto
|
||||||
|
|
@ -82,6 +83,7 @@ public class PermissionDefinitionRecordSeedDto
|
||||||
public string DisplayName { get; set; }
|
public string DisplayName { get; set; }
|
||||||
public bool IsEnabled { get; set; }
|
public bool IsEnabled { get; set; }
|
||||||
public int MultiTenancySide { get; set; }
|
public int MultiTenancySide { get; set; }
|
||||||
|
public string[] MenuGroup { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CurrencySeedDto
|
public class CurrencySeedDto
|
||||||
|
|
|
||||||
|
|
@ -1394,8 +1394,8 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
}),
|
}),
|
||||||
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
|
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
|
||||||
new() {
|
new() {
|
||||||
Hint = "Manage",
|
Hint = "Seed",
|
||||||
Text = "Manage",
|
Text = "Seed",
|
||||||
AuthName = TenantManagementPermissions.Tenants.ManageConnectionStrings,
|
AuthName = TenantManagementPermissions.Tenants.ManageConnectionStrings,
|
||||||
DialogName = "TenantsConnectionString",
|
DialogName = "TenantsConnectionString",
|
||||||
DialogParameters = JsonSerializer.Serialize(new {
|
DialogParameters = JsonSerializer.Serialize(new {
|
||||||
|
|
@ -2215,6 +2215,7 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
new EditingFormItemDto { Order=7, DataField = "Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order=7, DataField = "Address2", ColSpan=2, IsRequired=false, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=8, DataField = "Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order=8, DataField = "Email", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
new EditingFormItemDto { Order=9, DataField = "Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
new EditingFormItemDto { Order=9, DataField = "Website", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxTextBox },
|
||||||
|
new EditingFormItemDto { Order=10, DataField = "MenuGroup", ColSpan=2, IsRequired=true, EditorType2=EditorTypes.dxSelectBox },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
@ -2897,6 +2898,47 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
||||||
Visible = true,
|
Visible = true,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
IsDeleted = false,
|
IsDeleted = false,
|
||||||
|
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
|
||||||
|
{
|
||||||
|
AllowReordering = true,
|
||||||
|
}),
|
||||||
|
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
|
||||||
|
{
|
||||||
|
C = TenantManagementPermissions.Tenants.Create,
|
||||||
|
R = TenantManagementPermissions.Tenants.Default,
|
||||||
|
U = TenantManagementPermissions.Tenants.Update,
|
||||||
|
E = true,
|
||||||
|
I = true,
|
||||||
|
Deny = false
|
||||||
|
}),
|
||||||
|
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
|
||||||
|
{
|
||||||
|
IsPivot = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
new ListFormField
|
||||||
|
{
|
||||||
|
ListFormCode = listFormTenants.ListFormCode,
|
||||||
|
RoleId = null,
|
||||||
|
UserId = null,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "MenuGroup",
|
||||||
|
Width = 100,
|
||||||
|
ListOrderNo = 20,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
LookupJson = JsonSerializer.Serialize(new LookupDto {
|
||||||
|
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
|
||||||
|
DisplayExpr = "name",
|
||||||
|
ValueExpr = "key",
|
||||||
|
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
|
||||||
|
new () { Key="Kurs", Name="Kurs" },
|
||||||
|
new () { Key="Erp", Name="Erp" },
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
|
||||||
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
|
ColumnCustomizationJson = JsonSerializer.Serialize(new ColumnCustomizationDto
|
||||||
{
|
{
|
||||||
AllowReordering = true,
|
AllowReordering = true,
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,11 @@ public static class PlatformConsts
|
||||||
public const string DbSchema = null;
|
public const string DbSchema = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Permissions
|
||||||
|
{
|
||||||
|
public const string MenuGroup = "MenuGroup";
|
||||||
|
}
|
||||||
|
|
||||||
public static class Tenants
|
public static class Tenants
|
||||||
{
|
{
|
||||||
public const string IsActive = "IsActive";
|
public const string IsActive = "IsActive";
|
||||||
|
|
@ -181,6 +186,7 @@ public static class PlatformConsts
|
||||||
public const string Fax = "Fax";
|
public const string Fax = "Fax";
|
||||||
public const string Email = "Email";
|
public const string Email = "Email";
|
||||||
public const string Website = "Website";
|
public const string Website = "Website";
|
||||||
|
public const string MenuGroup = "MenuGroup";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AbpIdentity
|
public static class AbpIdentity
|
||||||
|
|
|
||||||
|
|
@ -21,5 +21,6 @@ public class Menu : FullAuditedEntity<Guid>
|
||||||
public string UserId { get; set; } // External kullanici id (orn: ali.akman. ihtiyaca gore guid veya int de olabilir)
|
public string UserId { get; set; } // External kullanici id (orn: ali.akman. ihtiyaca gore guid veya int de olabilir)
|
||||||
public string RoleId { get; set; } // External role id (orn: ihracat)
|
public string RoleId { get; set; } // External role id (orn: ihracat)
|
||||||
public string CultureName { get; set; } // Bu tanim hangi dil icin "en", "tr"
|
public string CultureName { get; set; } // Bu tanim hangi dil icin "en", "tr"
|
||||||
|
public string[] Group { get; set; } // Menu grubu (her tenant farklı menu grupları kullanabilir)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Volo.Abp.Data;
|
||||||
|
using Volo.Abp.PermissionManagement;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Extensions;
|
||||||
|
|
||||||
|
public static class AbpPermissionsExtensions
|
||||||
|
{
|
||||||
|
public static void SetMenuGroup(this PermissionDefinitionRecord permission, string[] menuGroup)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(menuGroup);
|
||||||
|
permission.SetProperty(PlatformConsts.Permissions.MenuGroup, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetMenuGroup(this PermissionDefinitionRecord permission)
|
||||||
|
{
|
||||||
|
var json = permission.GetProperty<string>(PlatformConsts.Permissions.MenuGroup);
|
||||||
|
return string.IsNullOrWhiteSpace(json)
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<string[]>(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -156,4 +156,13 @@ public static class AbpTenantExtensions
|
||||||
{
|
{
|
||||||
return tenant.GetProperty<string>(PlatformConsts.Tenants.Website);
|
return tenant.GetProperty<string>(PlatformConsts.Tenants.Website);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetMenuGroup(this Tenant tenant, string menuGroup)
|
||||||
|
{
|
||||||
|
tenant.SetProperty(PlatformConsts.Tenants.MenuGroup, menuGroup);
|
||||||
|
}
|
||||||
|
public static string GetMenuGroup(this Tenant tenant)
|
||||||
|
{
|
||||||
|
return tenant.GetProperty<string>(PlatformConsts.Tenants.MenuGroup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,8 +165,8 @@ public class DynamicEntityManager : IDynamicEntityManager
|
||||||
|
|
||||||
private async Task<CustomEntity> GetEntityDefinitionAsync(string entityName)
|
private async Task<CustomEntity> GetEntityDefinitionAsync(string entityName)
|
||||||
{
|
{
|
||||||
var entity = await _customEntityRepository.WithDetails(x => x.Fields)
|
var queryable = await _customEntityRepository.WithDetailsAsync(x => x.Fields);
|
||||||
.FirstOrDefaultAsync(x => x.Name.ToLower() == entityName.ToLower());
|
var entity = await queryable.FirstOrDefaultAsync(x => x.Name.ToLower() == entityName.ToLower());
|
||||||
|
|
||||||
return entity ?? throw new UserFriendlyException($"Entity '{entityName}' not found.");
|
return entity ?? throw new UserFriendlyException($"Entity '{entityName}' not found.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ public class PlatformDbContext :
|
||||||
b.Property(a => a.UserId).HasMaxLength(256);
|
b.Property(a => a.UserId).HasMaxLength(256);
|
||||||
b.Property(a => a.RoleId).HasMaxLength(256);
|
b.Property(a => a.RoleId).HasMaxLength(256);
|
||||||
b.Property(a => a.CultureName).HasMaxLength(50);
|
b.Property(a => a.CultureName).HasMaxLength(50);
|
||||||
|
b.Property(a => a.Group).HasMaxLength(64);
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Entity<DataSource>(b =>
|
builder.Entity<DataSource>(b =>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
using Volo.Abp.Identity;
|
using Volo.Abp.Identity;
|
||||||
using Volo.Abp.ObjectExtending;
|
using Volo.Abp.ObjectExtending;
|
||||||
|
using Volo.Abp.PermissionManagement;
|
||||||
using Volo.Abp.TenantManagement;
|
using Volo.Abp.TenantManagement;
|
||||||
using Volo.Abp.Threading;
|
using Volo.Abp.Threading;
|
||||||
|
|
||||||
|
|
@ -199,6 +200,24 @@ public static class PlatformEfCoreEntityExtensionMappings
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ObjectExtensionManager.Instance
|
||||||
|
.MapEfCoreProperty<Tenant, string>(
|
||||||
|
PlatformConsts.Tenants.MenuGroup,
|
||||||
|
(entityBuilder, propertyBuilder) =>
|
||||||
|
{
|
||||||
|
propertyBuilder.HasMaxLength(64).HasDefaultValue(null);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ObjectExtensionManager.Instance
|
||||||
|
.MapEfCoreProperty<PermissionDefinitionRecord, string>(
|
||||||
|
PlatformConsts.Permissions.MenuGroup,
|
||||||
|
(entityBuilder, propertyBuilder) =>
|
||||||
|
{
|
||||||
|
propertyBuilder.HasMaxLength(64).HasDefaultValue(null);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/* You can configure extra properties for the
|
/* You can configure extra properties for the
|
||||||
* entities defined in the modules used by your application.
|
* entities defined in the modules used by your application.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Kurs.Platform.Migrations
|
namespace Kurs.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20251010230305_Initial")]
|
[Migration("20251011214108_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -4482,6 +4482,10 @@ namespace Kurs.Platform.Migrations
|
||||||
.HasMaxLength(50)
|
.HasMaxLength(50)
|
||||||
.HasColumnType("nvarchar(50)");
|
.HasColumnType("nvarchar(50)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Group")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
b.Property<string>("Icon")
|
b.Property<string>("Icon")
|
||||||
.HasMaxLength(50)
|
.HasMaxLength(50)
|
||||||
.HasColumnType("nvarchar(50)");
|
.HasColumnType("nvarchar(50)");
|
||||||
|
|
@ -8216,6 +8220,10 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Property<bool>("IsEnabled")
|
b.Property<bool>("IsEnabled")
|
||||||
.HasColumnType("bit");
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("MenuGroup")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
b.Property<byte>("MultiTenancySide")
|
b.Property<byte>("MultiTenancySide")
|
||||||
.HasColumnType("tinyint");
|
.HasColumnType("tinyint");
|
||||||
|
|
||||||
|
|
@ -8476,6 +8484,10 @@ namespace Kurs.Platform.Migrations
|
||||||
.HasColumnType("uniqueidentifier")
|
.HasColumnType("uniqueidentifier")
|
||||||
.HasColumnName("LastModifierId");
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("MenuGroup")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
b.Property<string>("Mobile")
|
b.Property<string>("Mobile")
|
||||||
.HasMaxLength(20)
|
.HasMaxLength(20)
|
||||||
.HasColumnType("nvarchar(20)");
|
.HasColumnType("nvarchar(20)");
|
||||||
|
|
@ -224,7 +224,8 @@ namespace Kurs.Platform.Migrations
|
||||||
MultiTenancySide = table.Column<byte>(type: "tinyint", nullable: false),
|
MultiTenancySide = table.Column<byte>(type: "tinyint", nullable: false),
|
||||||
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||||
StateCheckers = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
StateCheckers = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)
|
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
|
|
@ -349,6 +350,7 @@ namespace Kurs.Platform.Migrations
|
||||||
Fax = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
Fax = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||||
Founder = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
Founder = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
||||||
|
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||||
Mobile = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
Mobile = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||||
OrganizationName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
OrganizationName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||||
Phone = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
Phone = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||||
|
|
@ -1687,6 +1689,7 @@ namespace Kurs.Platform.Migrations
|
||||||
UserId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
UserId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||||
RoleId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
RoleId = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||||
CultureName = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
|
CultureName = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
|
||||||
|
Group = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
|
@ -4479,6 +4479,10 @@ namespace Kurs.Platform.Migrations
|
||||||
.HasMaxLength(50)
|
.HasMaxLength(50)
|
||||||
.HasColumnType("nvarchar(50)");
|
.HasColumnType("nvarchar(50)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Group")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
b.Property<string>("Icon")
|
b.Property<string>("Icon")
|
||||||
.HasMaxLength(50)
|
.HasMaxLength(50)
|
||||||
.HasColumnType("nvarchar(50)");
|
.HasColumnType("nvarchar(50)");
|
||||||
|
|
@ -8213,6 +8217,10 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Property<bool>("IsEnabled")
|
b.Property<bool>("IsEnabled")
|
||||||
.HasColumnType("bit");
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("MenuGroup")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
b.Property<byte>("MultiTenancySide")
|
b.Property<byte>("MultiTenancySide")
|
||||||
.HasColumnType("tinyint");
|
.HasColumnType("tinyint");
|
||||||
|
|
||||||
|
|
@ -8473,6 +8481,10 @@ namespace Kurs.Platform.Migrations
|
||||||
.HasColumnType("uniqueidentifier")
|
.HasColumnType("uniqueidentifier")
|
||||||
.HasColumnName("LastModifierId");
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("MenuGroup")
|
||||||
|
.HasMaxLength(64)
|
||||||
|
.HasColumnType("nvarchar(64)");
|
||||||
|
|
||||||
b.Property<string>("Mobile")
|
b.Property<string>("Mobile")
|
||||||
.HasMaxLength(20)
|
.HasMaxLength(20)
|
||||||
.HasColumnType("nvarchar(20)");
|
.HasColumnType("nvarchar(20)");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ExtensibleEntityDto } from '../abp'
|
import { ExtensibleEntityDto } from '../abp'
|
||||||
import { ObjectExtensionsDto } from '../object-extending'
|
import { ObjectExtensionsDto } from '../object-extending/models'
|
||||||
|
|
||||||
export interface NameValue<T = string> {
|
export interface NameValue<T = string> {
|
||||||
name?: string
|
name?: string
|
||||||
|
|
@ -42,6 +42,7 @@ export interface CustomTenantDto extends TenantDto {
|
||||||
fax: number
|
fax: number
|
||||||
email: string
|
email: string
|
||||||
website: string
|
website: string
|
||||||
|
menuGroup?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MultiTenancyInfoDto {
|
export interface MultiTenancyInfoDto {
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,5 @@ export interface MenuDto extends FullAuditedEntityDto<string> {
|
||||||
userId?: string
|
userId?: string
|
||||||
roleId?: string
|
roleId?: string
|
||||||
cultureName?: string
|
cultureName?: string
|
||||||
|
group?: string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy/abp'
|
import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy/abp'
|
||||||
import { MenuDto } from '@/proxy/menus/models'
|
import { MenuDto } from '@/proxy/menus/models'
|
||||||
import apiService, { Config } from '@/services/api.service'
|
import apiService, { Config } from '@/services/api.service'
|
||||||
|
import { useStoreState } from '@/store/store'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
export class MenuService {
|
export class MenuService {
|
||||||
apiName = 'Default'
|
apiName = 'Default'
|
||||||
|
|
@ -43,15 +45,16 @@ export class MenuService {
|
||||||
{ apiName: this.apiName },
|
{ apiName: this.apiName },
|
||||||
)
|
)
|
||||||
|
|
||||||
getList = (input: PagedAndSortedResultRequestDto) =>
|
getList = (input: PagedAndSortedResultRequestDto, group?: string | null) =>
|
||||||
apiService.fetchData<PagedResultDto<MenuDto>, PagedAndSortedResultRequestDto>(
|
apiService.fetchData<PagedResultDto<MenuDto>, PagedAndSortedResultRequestDto>(
|
||||||
{
|
{
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: '/api/app/menu',
|
url: '/api/app/menu/by-group',
|
||||||
params: {
|
params: {
|
||||||
sorting: input.sorting,
|
sorting: input.sorting,
|
||||||
skipCount: input.skipCount,
|
skipCount: input.skipCount,
|
||||||
maxResultCount: input.maxResultCount,
|
maxResultCount: input.maxResultCount,
|
||||||
|
group: group,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ apiName: this.apiName },
|
{ apiName: this.apiName },
|
||||||
|
|
@ -70,10 +73,14 @@ export class MenuService {
|
||||||
|
|
||||||
export const getMenus = async (skipCount = 0, maxResultCount = 1000, sorting = 'order') => {
|
export const getMenus = async (skipCount = 0, maxResultCount = 1000, sorting = 'order') => {
|
||||||
const menuService = new MenuService()
|
const menuService = new MenuService()
|
||||||
|
const tenant = useStoreState((state) => state.auth.tenant)
|
||||||
|
|
||||||
return await menuService.getList({
|
return await menuService.getList(
|
||||||
sorting,
|
{
|
||||||
skipCount,
|
sorting,
|
||||||
maxResultCount,
|
skipCount,
|
||||||
})
|
maxResultCount,
|
||||||
|
},
|
||||||
|
null, //tenant.menuGroup ?? null,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ export const getTenants = (skipCount = 0, maxResultCount = 10) =>
|
||||||
})
|
})
|
||||||
|
|
||||||
export const getTenantByName = (name: string) =>
|
export const getTenantByName = (name: string) =>
|
||||||
apiService.fetchData<TenantDto>({
|
apiService.fetchData<CustomTenantDto>({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: `/api/app/platform-tenant/by-name?name=${encodeURIComponent(name)}`,
|
url: `/api/app/platform-tenant/by-name?name=${encodeURIComponent(name)}`,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -85,23 +85,27 @@ export const abpConfigModel: AbpConfigModel = {
|
||||||
state.menu.mainMenu = [...payload]
|
state.menu.mainMenu = [...payload]
|
||||||
}),
|
}),
|
||||||
getMenu: thunk(async (actions, _, { injections, getState, getStoreState }) => {
|
getMenu: thunk(async (actions, _, { injections, getState, getStoreState }) => {
|
||||||
const { signedIn } = getStoreState().auth.session
|
const { session, tenant } = getStoreState().auth
|
||||||
if (!signedIn) {
|
if (!session.signedIn) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await injections.menuService.getList({
|
const menuGroup = tenant.menuGroup ?? null
|
||||||
sorting: 'order',
|
const result = await injections.menuService.getList(
|
||||||
skipCount: 0,
|
{
|
||||||
maxResultCount: 1000,
|
sorting: 'order',
|
||||||
})
|
skipCount: 0,
|
||||||
|
maxResultCount: 1000,
|
||||||
|
},
|
||||||
|
menuGroup,
|
||||||
|
)
|
||||||
|
|
||||||
const texts = getState().texts
|
const texts = getState().texts
|
||||||
const defaultResourceName = getState().config?.localization.defaultResourceName
|
const defaultResourceName = getState().config?.localization.defaultResourceName
|
||||||
|
|
||||||
result.data.items?.forEach((menu: MenuDto) => {
|
result.data.items?.forEach((menu: MenuDto) => {
|
||||||
const displayName = '::' + menu.displayName
|
const displayName = '::' + menu.displayName
|
||||||
menu.displayName = getLocalization(texts, defaultResourceName, displayName)
|
menu.displayName = getLocalization(texts || {}, defaultResourceName, displayName)
|
||||||
})
|
})
|
||||||
|
|
||||||
const menu = getChildren(result.data.items ?? [], null)
|
const menu = getChildren(result.data.items ?? [], null)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ export interface AuthStoreModel {
|
||||||
tenant?: {
|
tenant?: {
|
||||||
tenantId?: string
|
tenantId?: string
|
||||||
tenantName?: string
|
tenantName?: string
|
||||||
|
menuGroup?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,6 +63,7 @@ export const initialState: AuthStoreModel = {
|
||||||
tenant: {
|
tenant: {
|
||||||
tenantId: '',
|
tenantId: '',
|
||||||
tenantName: '',
|
tenantName: '',
|
||||||
|
menuGroup: '',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,6 +113,7 @@ export const authModel: AuthModel = {
|
||||||
setTenant: action((state, payload) => {
|
setTenant: action((state, payload) => {
|
||||||
state.tenantId = payload?.tenantId
|
state.tenantId = payload?.tenantId
|
||||||
state.tenantName = payload?.tenantName
|
state.tenantName = payload?.tenantName
|
||||||
|
state.menuGroup = payload?.menuGroup
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,19 +35,39 @@ function RolesPermission({
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
|
|
||||||
const mode = useStoreState((state) => state.theme.mode)
|
const mode = useStoreState((state) => state.theme.mode)
|
||||||
|
const tenant = useStoreState((state) => state.auth.tenant)
|
||||||
|
|
||||||
const { direction } = useConfig()
|
const { direction } = useConfig()
|
||||||
const className = `m${direction[0]}-`
|
const className = `m${direction[0]}-`
|
||||||
|
|
||||||
const fetchDataPermissions = async () => {
|
const fetchDataPermissions = async () => {
|
||||||
if (!name) {
|
if (!name) return
|
||||||
|
|
||||||
|
const response = await getPermissions(providerName, name)
|
||||||
|
const data = response.data
|
||||||
|
|
||||||
|
const tenantGroup = tenant?.menuGroup?.trim()
|
||||||
|
if (!tenantGroup) {
|
||||||
|
console.warn('Tenant menuGroup boş, tüm izinler gösterilecek')
|
||||||
|
setPermissionList(data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await getPermissions(providerName, name)
|
const filteredGroups = data.groups
|
||||||
setPermissionList(response.data)
|
.map((group: any) => {
|
||||||
|
const filteredPermissions = group.permissions.filter(
|
||||||
|
(perm: any) => Array.isArray(perm.menuGroup) && perm.menuGroup.includes(tenantGroup),
|
||||||
|
)
|
||||||
|
|
||||||
|
return { ...group, permissions: filteredPermissions }
|
||||||
|
})
|
||||||
|
.filter((group: any) => group.permissions.length > 0)
|
||||||
|
|
||||||
|
const filteredData = { ...data, groups: filteredGroups }
|
||||||
|
|
||||||
|
console.log('Filtered permissions by tenant group:', tenantGroup, filteredData)
|
||||||
|
setPermissionList(filteredData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeGroup = (groupName?: string) => {
|
const changeGroup = (groupName?: string) => {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { FormContainer, FormItem } from '@/components/ui/Form'
|
||||||
import Input from '@/components/ui/Input'
|
import Input from '@/components/ui/Input'
|
||||||
import PlatformLoginResultType from '@/constants/login.result.enum'
|
import PlatformLoginResultType from '@/constants/login.result.enum'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import { getTenantByName } from '@/services/tenant.service'
|
import { getTenantByNameDetail } from '@/services/tenant.service'
|
||||||
import { useStoreActions, useStoreState } from '@/store'
|
import { useStoreActions, useStoreState } from '@/store'
|
||||||
import useAuth from '@/utils/hooks/useAuth'
|
import useAuth from '@/utils/hooks/useAuth'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
@ -168,10 +168,10 @@ const Login = () => {
|
||||||
|
|
||||||
const fetchDataByName = async (name: string) => {
|
const fetchDataByName = async (name: string) => {
|
||||||
if (name) {
|
if (name) {
|
||||||
const response = await getTenantByName(name)
|
const response = await getTenantByNameDetail(name)
|
||||||
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
setTenant({ tenantId: response.data.id, tenantName: response.data.name })
|
setTenant({ tenantId: response.data.id, tenantName: response.data.name, menuGroup: response.data.menuGroup });
|
||||||
} else {
|
} else {
|
||||||
setTenant(undefined)
|
setTenant(undefined)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ const useFilters = ({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkPermission("App.ListForms.ListForm.Update")) {
|
if (checkPermission("App.Listforms.Listform.Update")) {
|
||||||
menus.push({
|
menus.push({
|
||||||
text: translate('::ListForms.ListForm.Manage'),
|
text: translate('::ListForms.ListForm.Manage'),
|
||||||
id: 'openManage',
|
id: 'openManage',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue