Module ve Menu yapısı değiştirildi.
This commit is contained in:
parent
1fc7111da2
commit
462dd20edb
82 changed files with 4392 additions and 3853 deletions
4
.github/instructions/list.instructions.md
vendored
4
.github/instructions/list.instructions.md
vendored
|
|
@ -28,7 +28,7 @@ This document summarizes the rules, standards, and step-by-step instructions for
|
|||
## Special File Handling Rules
|
||||
|
||||
- **MenusData.json:**
|
||||
- Never modify the `Routes` section directly. Only `MenuGroups` and `Menus` sections can be changed for menu additions or updates. All menu additions must use the platform's configuration mechanisms or be added to `MenuGroups` and `Menus` as required by platform design.
|
||||
- Never modify the `Routes` section directly. Only `Modules` and `Menus` sections can be changed for menu additions or updates. All menu additions must use the platform's configuration mechanisms or be added to `Modules` and `Menus` as required by platform design.
|
||||
|
||||
- **LanguagesData.json:**
|
||||
- When adding a new key, always check if the key already exists. Only add the key if it does not exist to prevent duplicates.
|
||||
|
|
@ -39,7 +39,7 @@ This document summarizes the rules, standards, and step-by-step instructions for
|
|||
|
||||
|
||||
### 1. MenusData.json
|
||||
- **{Modul} menu** added as a top-level menu with `ShortName: {Modul}`.
|
||||
- **{Modul} menu** added as a top-level menu with `ModuleId: {Modul}`.
|
||||
- **{Liste}** added as a child menu under {Modul}.
|
||||
|
||||
### 2. PermissionsData.json
|
||||
|
|
|
|||
|
|
@ -1164,7 +1164,7 @@ soneklerini alır.
|
|||
| **Data Source** | `App.DataSource` | `Sas_H_DataSource` | host | `Code`, `DataSourceType`, `ConnectionString`. **İki tür kayıt bir arada:** elle tanımlanan host/harici bağlantılar ve `Code = tenant adı` olan otomatik tenant bağlantıları (Tenants ekranındaki bağlantı diyaloğu yönetir, elle dokunma). `IsTenant` ekran önce tenant kaydını, yoksa `DataSourceCode`'u kullanır — çözüm kuralı `lowcode` §9.3.3. Bağlantı dizesi koda/JSON'a yazılmaz. |
|
||||
| **Notifications › Types / Rules / Notifications** | `App.Notifications.NotificationTypes` · `.NotificationRules` · `.Notification` | `Sas_H_NotificationType` · `Sas_H_NotificationRule` · `Sas_H_Notification` | host | Olay bazlı bildirim (7 kanal); kural ekranındaki `CreateNotification` diyaloğu ile elle bildirim üretilir. Ayrıntı: §9.11. |
|
||||
| **Background Workers › Recurring Jobs / Jobs** | `App.BackgroundWorkers.RecurringJobs` · `.Jobs` | `Sas_H_BackgroundWorker` · `Sas_H_BackgroundWorker_JobFlow` | host | Cron'lu işler ve çalıştırma geçmişi (`ExecutionDate`, `Duration`, `Status`, `FailureReason`, `ExceptionDetails`). Ayrıntı: §9.10 ve bu dosyanın §11'i. |
|
||||
| **Menus › Routes / Menu Group / Menu / Manager** | `App.Menus.Routes` · `.MenuGroup` · `.Menu` · `.Manager` (`/admin/menuManager`) | `Sas_H_Route` · `Sas_H_MenuGroup` · `Sas_H_Menu` | host | Menü ve route veritabanından gelir; üretilen ekranın menü kaydı buradan açılır. `Menu` ekranı ağaç düzeninin referansıdır, `Routes` yalnızca özel React sayfası eklenirken kullanılır. |
|
||||
| **Menus › Routes / Module / Menu / Manager** | `App.Menus.Routes` · `.Module` · `.Menu` · `.Manager` (`/admin/menuManager`) | `Sas_H_Route` · `Sas_H_Module` · `Sas_H_Menu` | host | Menü ve route veritabanından gelir; üretilen ekranın menü kaydı buradan açılır. `Menu` ekranı ağaç düzeninin referansıdır, `Routes` yalnızca özel React sayfası eklenirken kullanılır. |
|
||||
| **Developer Kit › SQL Query Manager** | `App.SqlQueryManager` · `/admin/sqlQueryManager` | — | — | View/procedure/function yazma ve çalıştırma; karar sırasının 2. adımı buradan başlar. |
|
||||
| **Developer Kit › Custom Endpoints** | `App.DeveloperKit.CustomEndpoints` | `Sas_H_CustomEndpoint` | tenant | `Name`, `Url`, `Method`, `DataSourceCode`, `Sql`, `ParametersJson`, `PermissionsJson` — parametreli SQL'i yetkili bir HTTP ucuna çevirir. |
|
||||
| **Developer Kit › Dynamic Services** | `App.DeveloperKit.DynamicServices` · `/admin/developerkit/dynamic-services` | `Sas_H_DynamicService` | host | Monaco editöründe yazılan, derlenip yayınlanan C# servisi; SQL'in yetmediği iş kuralı için 3. adım. |
|
||||
|
|
@ -1198,7 +1198,7 @@ Kök menü `App.Administration`. Bu menünün tabloları `Adm_T_*` — yani **ki
|
|||
| **Intranet › Event Type / Category / Event (+Like/Comment)** | `App.Intranet.Events.*` | `Adm_T_EventType` · `Adm_T_EventCategory` · `Adm_T_Event` · `Adm_T_EventPhoto` · `Adm_T_EventLike` · `Adm_T_EventComment` | Etkinlik yönetimi; foto ve katılımcı sayacı olan kayıt kalıbı. |
|
||||
| **Restrictions › Work Hour** | `App.Restrictions.WorkHour` | `Adm_T_WorkHour` | Gün bazlı çalışma saati (`Monday`…`Sunday`, `StartTime`, `EndTime`); kullanıcıya `AbpUsers.WorkHour` ile bağlanır. "Sadece mesai saatinde girilebilsin" burada çözülür. |
|
||||
| **Restrictions › IP Restrictions** | `App.Restrictions.IpRestrictions` | `Adm_T_IpRestriction` | `ResourceType` + `ResourceId` + `IP` — kullanıcı/rol bazlı IP kısıtı. |
|
||||
| **Identity › Permission Groups / Permissions** | `Abp.Identity.PermissionGroups` · `Abp.Identity.Permissions` | `AbpPermissionGroups` · `AbpPermissions` | Yetki ağacı (tree düzeni). Yeni ekranın yetkileri burada görünür; `MenuGroup` kolonu yetkiyi modüle bağlar. |
|
||||
| **Identity › Permission Groups / Permissions** | `Abp.Identity.PermissionGroups` · `Abp.Identity.Permissions` | `AbpPermissionGroups` · `AbpPermissions` | Yetki ağacı (tree düzeni). Yeni ekranın yetkileri burada görünür; `Modules` kolonu yetkiyi modüllere bağlar (pipe ile çoklu). |
|
||||
| **Identity › Claim Type** | `App.IdentityManagement.ClaimType` | `AbpClaimTypes` | Kullanıcıya ek alan (claim) tanımı: `ValueType`, `Regex`, `Required`, `IsStatic`. |
|
||||
| **Identity › Roles** | `AbpIdentity.Roles` | `AbpRoles` | Rol yönetimi + `RolesPermission` diyaloğu; yeni ekranın yetkisi role buradan verilir. |
|
||||
| **Identity › Users** | `AbpIdentity.Users` | `AbpUsers` | Kullanıcı yönetimi + `UsersPermission` diyaloğu, **KPI widget'ları** ve `list-form-dynamic-api/user-*` ile devredilen yazma. Kullanıcı `WorkHour`, `DepartmentId`, `JobPositionId` alanlarını taşır. |
|
||||
|
|
|
|||
8
.github/instructions/lowcode.instructions.md
vendored
8
.github/instructions/lowcode.instructions.md
vendored
|
|
@ -601,7 +601,7 @@ Elle dosya yazarken buraya var olan bir kaydı koyma — silme onu da götürür
|
|||
| Alan | Anlam |
|
||||
| --- | --- |
|
||||
| `CreateMenu` | `false` ise menü ve üst menü kaydı **hiç üretilmez**; ListForm, yetki ve dil anahtarları yine üretilir. SubGrid/parça olarak kullanılacak ekranlar için. Varsayılan `true`. |
|
||||
| `MenuParentCode` / `MenuParentShortName` / `MenuParentIcon` | Üst menü; yoksa oluşturulur. |
|
||||
| `MenuParentCode` / `MenuParentModuleId` / `MenuParentIcon` | Üst menü; yoksa oluşturulur. |
|
||||
| `MenuIcon` | React-icons adı (`FcBiohazard`, `FaBox`…). |
|
||||
| `MenuOrder` | Kardeşler arası sıra. |
|
||||
|
||||
|
|
@ -986,7 +986,7 @@ varsayılan değeri olur ve **yeni kayıtta o alanı otomatik doldurur**.
|
|||
|
||||
"PermissionGroupName": "App.Mrp",
|
||||
"PermissionGroupDisplayNameEn": "MRP", "PermissionGroupDisplayNameTr": "MRP",
|
||||
"MenuParentCode": "App.Mrp", "MenuParentShortName": "MRP", "MenuParentIcon": "FcFactory",
|
||||
"MenuParentCode": "App.Mrp", "MenuParentModuleId": "MRP", "MenuParentIcon": "FcFactory",
|
||||
"MenuIcon": "FcShipped",
|
||||
|
||||
"DataSourceCode": "Default", "DataSourceConnectionString": "",
|
||||
|
|
@ -3035,7 +3035,7 @@ elle düzeltme ve wizard'ın kapsamadığı düzenlemeler içindir.
|
|||
| Ekran | Route | Yetki | Ne yapar |
|
||||
| --- | --- | --- | --- |
|
||||
| **Routes** | `/admin/list/App.Menus.Routes` | `App.Menus.Routes` | Fiziksel React sayfalarının route kayıtları (`Key`, `Path`, `ComponentType`, `ComponentPath`, `RouteType`, `Authority[]`) |
|
||||
| **Menu Groups** | `/admin/list/App.Menus.MenuGroup` | `App.Menus.MenuGroup` | Menü grubu adları (`Erp`, `Kurs` gibi üst kümeler) |
|
||||
| **Modules** | `/admin/list/App.Menus.Module` | `App.Menus.Module` | Modül adları (`Sas`, `Adm` gibi üst kümeler); kök menü `ModuleId` ile buraya bağlanır |
|
||||
| **Menu List** | `/admin/list/App.Menus.Menu` | `App.Menus.Menu` | Menü kayıtlarının ham listesi |
|
||||
| **Menu Manager** | `/admin/menuManager` | `App.Menus.Manager` | Sürükle-bırak menü ağacı; sıra ve hiyerarşi düzenleme |
|
||||
|
||||
|
|
@ -3049,7 +3049,7 @@ elle düzeltme ve wizard'ın kapsamadığı düzenlemeler içindir.
|
|||
| `Url` | Açılacak adres |
|
||||
| `Icon` | react-icons adı |
|
||||
| `Order` | Kardeşler arası sıra |
|
||||
| `ShortName` | Kısa rozet (`HR`, `MRP`) — kök menülerde kullanılır |
|
||||
| `ModuleId` | Kısa rozet (`HR`, `MRP`) — kök menülerde kullanılır |
|
||||
| `RequiredPermissionName` | Görünürlük yetkisi |
|
||||
| `Target` / `CssClass` / `ElementId` / `IsDisabled` | Bağlantı davranışı ve görünüm |
|
||||
| `UserId` / `RoleId` / `CultureName` | Kullanıcı, rol ve dil bazlı menü varyantı |
|
||||
|
|
|
|||
|
|
@ -1151,7 +1151,7 @@ Platformun kendi ekranları, menüleri, yetkileri ve dil metinleri buradadır; d
|
|||
derlenip yayınlanır. Yeni bir modülün nasıl kurulacağını öğrenmek için başvurulacak dosyalar:
|
||||
|
||||
- `ListFormSeeder_Saas.cs`, `ListFormSeeder_Administration.cs` — ListForm + alan tanımları
|
||||
- `MenusData.json` — `Routes`, `MenuGroups`, `Menus`
|
||||
- `MenusData.json` — `Routes`, `Modules`, `Menus`
|
||||
- `PermissionsData.json` — yetki grupları ve tanımları
|
||||
- `HostData.json` — ayar/entegrasyon değerleri
|
||||
- `LanguagesData.json` — dil anahtarları (EN/TR)
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ public class CreateTenantFromOrderInput
|
|||
{
|
||||
public Guid OrderId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string MenuGroup { get; set; }
|
||||
public string Modules { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,6 @@ public class CreateUpdateTenantInput
|
|||
public string FaxNumber { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Website { get; set; }
|
||||
public string MenuGroup { get; set; }
|
||||
public string Modules { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ public class ListFormWizardDto
|
|||
/// <summary>Izin grubunun Turkce gorunen adi; <see cref="PermissionGroupDisplayNameEn"/> ile ayni kurallara tabidir.</summary>
|
||||
public string PermissionGroupDisplayNameTr { get; set; }
|
||||
|
||||
public string MenuParentModuleId { get; set; }
|
||||
public string MenuParentCode { get; set; }
|
||||
public string MenuParentShortName { get; set; }
|
||||
public string MenuParentIcon { get; set; }
|
||||
public string MenuIcon { get; set; }
|
||||
public string DataSourceCode { get; set; }
|
||||
|
|
|
|||
|
|
@ -170,11 +170,11 @@ public static class LookupQueryValues
|
|||
$"FROM \"AbpPermissionGroups\" " +
|
||||
$"ORDER BY \"Name\";";
|
||||
|
||||
public static string MenuGroupValues =
|
||||
public static string ModuleValues =
|
||||
$"SELECT " +
|
||||
$"\"Id\" AS \"Key\", " +
|
||||
$"\"Name\" AS \"Name\" " +
|
||||
$"FROM \"{TableNameResolver.GetFullTableName(nameof(TableNameEnum.MenuGroup))}\" " +
|
||||
$"FROM \"{TableNameResolver.GetFullTableName(nameof(TableNameEnum.Module))}\" " +
|
||||
$"ORDER BY \"Name\";";
|
||||
|
||||
public static string ProductValues =
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public class MenuDto : FullAuditedEntityDto<Guid>
|
|||
public string ParentCode { get; set; }
|
||||
public string CssClass { get; set; }
|
||||
public string RequiredPermissionName { get; set; }
|
||||
public string ShortName { get; set; }
|
||||
public string ModuleId { get; set; }
|
||||
|
||||
public string Target { get; set; }
|
||||
public bool IsDisabled { get; set; }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public class CustomTenantDto
|
|||
public string FaxNumber { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Website { get; set; }
|
||||
public string MenuGroup { get; set; }
|
||||
public string Modules { get; set; }
|
||||
public string Reference { get; set; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public partial class TenantToCustomTenantDtoMapper : MapperBase<Tenant, CustomTe
|
|||
[MapperIgnoreTarget(nameof(CustomTenantDto.FaxNumber))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Email))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Website))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.MenuGroup))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Modules))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Reference))]
|
||||
public override partial CustomTenantDto Map(Tenant source);
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ public partial class TenantToCustomTenantDtoMapper : MapperBase<Tenant, CustomTe
|
|||
[MapperIgnoreTarget(nameof(CustomTenantDto.FaxNumber))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Email))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Website))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.MenuGroup))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Modules))]
|
||||
[MapperIgnoreTarget(nameof(CustomTenantDto.Reference))]
|
||||
public override partial void Map(Tenant source, CustomTenantDto destination);
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ public partial class TenantToCustomTenantDtoMapper : MapperBase<Tenant, CustomTe
|
|||
destination.FaxNumber = source.GetFaxNumber();
|
||||
destination.Email = source.GetEmail();
|
||||
destination.Website = source.GetWebsite();
|
||||
destination.MenuGroup = source.GetMenuGroup();
|
||||
destination.Modules = source.GetModulesRaw();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ public class ListFormFieldsAppService : CrudAppService<
|
|||
{
|
||||
RepoListForm = _repoListForm;
|
||||
|
||||
CreatePolicyName = $"{AppCodes.Listforms.Listform}.Create";
|
||||
UpdatePolicyName = $"{AppCodes.Listforms.Listform}.Update";
|
||||
DeletePolicyName = $"{AppCodes.Listforms.Listform}.Delete";
|
||||
CreatePolicyName = $"{AppCodes.Listforms.ListformField}.Create";
|
||||
UpdatePolicyName = $"{AppCodes.Listforms.ListformField}.Update";
|
||||
DeletePolicyName = $"{AppCodes.Listforms.ListformField}.Delete";
|
||||
}
|
||||
|
||||
protected override async Task<IQueryable<ListFormField>> CreateFilteredQueryAsync(ListFormFieldRequestDto input)
|
||||
|
|
@ -217,6 +217,7 @@ public class ListFormFieldsAppService : CrudAppService<
|
|||
return await MapToGetOutputDtoAsync(item);
|
||||
}
|
||||
|
||||
[Authorize(AppCodes.Listforms.ListformField + ".Create")]
|
||||
public async Task<CopyListFormFieldColumnDto> CopyField(CopyListFormFieldColumnDto input)
|
||||
{
|
||||
////Izin logic process
|
||||
|
|
|
|||
|
|
@ -250,9 +250,9 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
|||
throw new UserFriendlyException("Tenant name is required.");
|
||||
}
|
||||
|
||||
if (input.Data.MenuGroup.IsNullOrWhiteSpace())
|
||||
if (input.Data.Modules.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new UserFriendlyException("Menu group is required.");
|
||||
throw new UserFriendlyException("Module is required.");
|
||||
}
|
||||
|
||||
var order = await orderRepository.GetAsync(input.Data.OrderId)
|
||||
|
|
@ -283,11 +283,11 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
|||
FaxNumber = order.FaxNumber,
|
||||
Email = order.Email,
|
||||
Website = order.Website,
|
||||
MenuGroup = input.Data.MenuGroup,
|
||||
Modules = input.Data.Modules,
|
||||
});
|
||||
|
||||
order.TenantId = tenant.Id;
|
||||
order.MenuGroup = input.Data.MenuGroup;
|
||||
order.Modules = input.Data.Modules;
|
||||
await orderRepository.UpdateAsync(order, autoSave: true);
|
||||
|
||||
return tenant.Id;
|
||||
|
|
@ -315,7 +315,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
|||
entity.SetFaxNumber(input.FaxNumber);
|
||||
entity.SetEmail(input.Email);
|
||||
entity.SetWebsite(input.Website);
|
||||
entity.SetMenuGroup(input.MenuGroup);
|
||||
entity.SetModules(input.Modules);
|
||||
|
||||
return await tenantRepository.UpdateAsync(entity, autoSave: true);
|
||||
}
|
||||
|
|
@ -350,7 +350,7 @@ public class ListFormDynamicApiAppService : PlatformAppService, IListFormDynamic
|
|||
entity.SetFaxNumber(input.Data.FaxNumber);
|
||||
entity.SetEmail(input.Data.Email);
|
||||
entity.SetWebsite(input.Data.Website);
|
||||
entity.SetMenuGroup(input.Data.MenuGroup);
|
||||
entity.SetModules(input.Data.Modules);
|
||||
|
||||
await tenantRepository.UpdateAsync(entity, autoSave: true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public class ListFormWizardAppService(
|
|||
IRepository<PermissionDefinitionRecord, Guid> repoPerm,
|
||||
IRepository<PermissionGroupDefinitionRecord, Guid> repoPermGroup,
|
||||
IRepository<Menu, Guid> repoMenu,
|
||||
IRepository<Module, string> repoModule,
|
||||
IPermissionGrantRepository permissionGrantRepository,
|
||||
IConfiguration configuration,
|
||||
LanguageTextAppService languageTextAppService,
|
||||
|
|
@ -63,6 +64,7 @@ public class ListFormWizardAppService(
|
|||
private readonly IRepository<PermissionDefinitionRecord, Guid> repoPerm = repoPerm;
|
||||
private readonly IRepository<PermissionGroupDefinitionRecord, Guid> repoPermGroup = repoPermGroup;
|
||||
private readonly IRepository<Menu, Guid> repoMenu = repoMenu;
|
||||
private readonly IRepository<Module, string> repoModule = repoModule;
|
||||
private readonly IPermissionGrantRepository permissionGrantRepository = permissionGrantRepository;
|
||||
private readonly IConfiguration _configuration = configuration;
|
||||
private readonly LanguageTextAppService _languageTextAppService = languageTextAppService;
|
||||
|
|
@ -214,6 +216,8 @@ public class ListFormWizardAppService(
|
|||
if (input.CreateMenu)
|
||||
{
|
||||
//Menu Parent
|
||||
await EnsureModuleAsync(input.MenuParentModuleId);
|
||||
|
||||
var menuQueryable = await repoMenu.GetQueryableAsync();
|
||||
var menuParent = await AsyncExecuter.FirstOrDefaultAsync(menuQueryable.Where(a => a.Code == input.MenuParentCode));
|
||||
if (menuParent == null)
|
||||
|
|
@ -230,16 +234,16 @@ public class ListFormWizardAppService(
|
|||
Code = input.MenuParentCode,
|
||||
DisplayName = input.MenuParentCode,
|
||||
IsDisabled = false,
|
||||
ShortName = input.MenuParentShortName?.Trim(),
|
||||
ModuleId = input.MenuParentModuleId?.Trim(),
|
||||
Icon = menuParentIcon,
|
||||
Order = maxRootOrder + 1,
|
||||
}, autoSave: false);
|
||||
inserted.MenuCodes.Add(input.MenuParentCode);
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(menuParent.ShortName) &&
|
||||
!string.IsNullOrWhiteSpace(input.MenuParentShortName))
|
||||
else if (string.IsNullOrWhiteSpace(menuParent.ModuleId) &&
|
||||
!string.IsNullOrWhiteSpace(input.MenuParentModuleId))
|
||||
{
|
||||
menuParent.ShortName = input.MenuParentShortName.Trim();
|
||||
menuParent.ModuleId = input.MenuParentModuleId.Trim();
|
||||
await repoMenu.UpdateAsync(menuParent, autoSave: false);
|
||||
}
|
||||
|
||||
|
|
@ -264,13 +268,17 @@ public class ListFormWizardAppService(
|
|||
Url = menuUrl,
|
||||
RequiredPermissionName = permRead.Name,
|
||||
Order = menuOrder,
|
||||
ModuleId = menuParent.ModuleId,
|
||||
}, autoSave: false);
|
||||
inserted.MenuCodes.Add(code);
|
||||
}
|
||||
else if (existingMenu.Order != menuOrder || existingMenu.Url != menuUrl)
|
||||
else if (existingMenu.Order != menuOrder ||
|
||||
existingMenu.Url != menuUrl ||
|
||||
string.IsNullOrWhiteSpace(existingMenu.ModuleId))
|
||||
{
|
||||
existingMenu.Order = menuOrder;
|
||||
existingMenu.Url = menuUrl;
|
||||
existingMenu.ModuleId ??= menuParent.ModuleId;
|
||||
await repoMenu.UpdateAsync(existingMenu, autoSave: false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1658,6 +1666,27 @@ public class ListFormWizardAppService(
|
|||
texts.FirstOrDefault(a => a.CultureName == LanguageCodes.Tr)?.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wizard'da secilen modul kaydi yoksa olusturur; menunun ModuleId yabanci anahtari
|
||||
/// tanimsiz bir module bagli kalmasin diye menu yazilmadan once cagrilir.
|
||||
/// </summary>
|
||||
private async Task EnsureModuleAsync(string moduleId)
|
||||
{
|
||||
var cleaned = moduleId?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(cleaned))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (await repoModule.AnyAsync(a => a.Id == cleaned))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await repoModule.InsertAsync(new Module(cleaned) { Name = cleaned }, autoSave: false);
|
||||
logger.LogInformation("Module '{ModuleId}' wizard tarafindan olusturuldu.", cleaned);
|
||||
}
|
||||
|
||||
private async Task<LanguageKey> CreateLangKey(string key, string textEn, string textTr, WizardInsertedRecordsDto inserted = null)
|
||||
{
|
||||
var res = PlatformConsts.AppName;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class MenuAppService : CrudAppService<
|
|||
private readonly ITenantRepository _tenantRepository;
|
||||
private readonly IPermissionDefinitionRecordRepository _permissionRepository;
|
||||
private readonly LanguageTextAppService _languageTextAppService;
|
||||
private readonly IRepository<MenuGroup, string> _menuGroupRepository;
|
||||
private readonly IRepository<Module, string> _moduleRepository;
|
||||
|
||||
public MenuAppService(
|
||||
IRepository<Menu, Guid> menuRepository,
|
||||
|
|
@ -42,7 +42,7 @@ public class MenuAppService : CrudAppService<
|
|||
ITenantRepository tenantRepository,
|
||||
IPermissionDefinitionRecordRepository permissionRepository,
|
||||
LanguageTextAppService languageTextAppService,
|
||||
IRepository<MenuGroup, string> menuGroupRepository
|
||||
IRepository<Module, string> moduleRepository
|
||||
) : base(menuRepository)
|
||||
{
|
||||
_menuRepository = menuRepository;
|
||||
|
|
@ -51,7 +51,7 @@ public class MenuAppService : CrudAppService<
|
|||
_tenantRepository = tenantRepository;
|
||||
_permissionRepository = permissionRepository;
|
||||
_languageTextAppService = languageTextAppService;
|
||||
_menuGroupRepository = menuGroupRepository;
|
||||
_moduleRepository = moduleRepository;
|
||||
|
||||
CreatePolicyName = $"{AppCodes.Menus.Menu}.Create";
|
||||
UpdatePolicyName = $"{AppCodes.Menus.Menu}.Update";
|
||||
|
|
@ -65,18 +65,18 @@ public class MenuAppService : CrudAppService<
|
|||
var query = await CreateFilteredQueryAsync(input);
|
||||
query = query.Where(a => !a.IsDisabled);
|
||||
|
||||
//Tenant üzerinden MenuGrup bilgisi alınıp sadece o menüler listelenecek
|
||||
//Tenant üzerinden modül bilgisi alınıp yalnızca o modüllerin menüleri listelenecek
|
||||
if (CurrentTenant.IsAvailable)
|
||||
{
|
||||
var tenant = await _tenantRepository.FindAsync(CurrentTenant.Id.Value);
|
||||
if (tenant != null)
|
||||
{
|
||||
var tenantMenuGroup = tenant.GetMenuGroup();
|
||||
if (!tenantMenuGroup.IsNullOrWhiteSpace())
|
||||
var tenantModules = tenant.GetModules();
|
||||
if (tenantModules.Length > 0)
|
||||
{
|
||||
var permissionRecords = await _permissionRepository.GetListAsync();
|
||||
var allowedPermissionNames = permissionRecords
|
||||
.Where(p => p.GetMenuGroup().Contains(tenantMenuGroup))
|
||||
.Where(p => p.GetModules().Intersect(tenantModules).Any())
|
||||
.Select(p => p.Name)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
|
@ -168,6 +168,8 @@ public class MenuAppService : CrudAppService<
|
|||
{
|
||||
await CheckCreatePolicyAsync();
|
||||
|
||||
await EnsureModuleAsync(input.ModuleId);
|
||||
|
||||
var keyExists = await _repositoryKey.AnyAsync(
|
||||
a => a.Key == input.DisplayName &&
|
||||
a.ResourceName == PlatformConsts.AppName);
|
||||
|
|
@ -187,6 +189,8 @@ public class MenuAppService : CrudAppService<
|
|||
{
|
||||
await CheckUpdatePolicyAsync();
|
||||
|
||||
await EnsureModuleAsync(input.ModuleId);
|
||||
|
||||
var key = await _repositoryKey.FirstOrDefaultAsync(
|
||||
a => a.Key == input.DisplayName &&
|
||||
a.ResourceName == PlatformConsts.AppName);
|
||||
|
|
@ -273,7 +277,7 @@ public class MenuAppService : CrudAppService<
|
|||
await CheckGetPolicyAsync();
|
||||
|
||||
var query = await _menuRepository.GetQueryableAsync();
|
||||
query = query.Where(a => !a.IsDisabled && a.ShortName != null);
|
||||
query = query.Where(a => !a.IsDisabled && a.ModuleId != null);
|
||||
|
||||
var entities = await AsyncExecuter.ToListAsync(query);
|
||||
var entityDtos = await MapToGetListOutputDtosAsync(entities);
|
||||
|
|
@ -290,6 +294,8 @@ public class MenuAppService : CrudAppService<
|
|||
{
|
||||
await CheckUpdatePolicyAsync();
|
||||
|
||||
await EnsureModuleAsync(input.ModuleId);
|
||||
|
||||
var menu = await _menuRepository.GetAsync(id);
|
||||
|
||||
// Kod değiştirilemez: dil anahtarı, alt menülerin ParentCode'u ve permission
|
||||
|
|
@ -352,6 +358,8 @@ public class MenuAppService : CrudAppService<
|
|||
{
|
||||
await CheckCreatePolicyAsync();
|
||||
|
||||
await EnsureModuleAsync(input.ModuleId);
|
||||
|
||||
//Dil Key oluşturuluyor.
|
||||
var keyExists = await _repositoryKey.AnyAsync(
|
||||
a => a.Key == input.Code &&
|
||||
|
|
@ -415,16 +423,36 @@ public class MenuAppService : CrudAppService<
|
|||
return await base.CreateAsync(input);
|
||||
}
|
||||
|
||||
public async Task<List<LookupDataDto>> GetMenuGroupsAsync()
|
||||
/// <summary>
|
||||
/// Menude secilen modul tanimli degilse olusturur; kok menude girilen kisa kod
|
||||
/// dogrudan yeni bir modul olur ve ModuleId yabanci anahtari bos kalmaz.
|
||||
/// </summary>
|
||||
private async Task EnsureModuleAsync(string moduleId)
|
||||
{
|
||||
var menuGroups = await _menuGroupRepository.GetListAsync();
|
||||
var cleaned = moduleId?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(cleaned))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return menuGroups
|
||||
.OrderBy(menuGroup => menuGroup.Name)
|
||||
.Select(menuGroup => new LookupDataDto
|
||||
if (await _moduleRepository.AnyAsync(a => a.Id == cleaned))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _moduleRepository.InsertAsync(new Module(cleaned) { Name = cleaned }, autoSave: true);
|
||||
}
|
||||
|
||||
public async Task<List<LookupDataDto>> GetModulesAsync()
|
||||
{
|
||||
var modules = await _moduleRepository.GetListAsync();
|
||||
|
||||
return modules
|
||||
.OrderBy(module => module.Name)
|
||||
.Select(module => new LookupDataDto
|
||||
{
|
||||
Key = menuGroup.Id,
|
||||
Name = menuGroup.Name
|
||||
Key = module.Id,
|
||||
Name = module.Name
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class PlatformPermissionGroupDto : PermissionGroupDto
|
|||
|
||||
public class PlatformPermissionGrantInfoDto : PermissionGrantInfoDto
|
||||
{
|
||||
public string MenuGroup { get; set; } = string.Empty;
|
||||
public string Modules { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[Dependency(ReplaceServices = true)]
|
||||
|
|
@ -64,7 +64,7 @@ public class PlatformPermissionAppService : PermissionAppService
|
|||
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 modules = definition?.Properties.GetOrDefault(PlatformConsts.Permissions.Modules)?.ToString();
|
||||
|
||||
var newPermission = new PlatformPermissionGrantInfoDto
|
||||
{
|
||||
|
|
@ -74,7 +74,7 @@ public class PlatformPermissionAppService : PermissionAppService
|
|||
AllowedProviders = permission.AllowedProviders,
|
||||
GrantedProviders = permission.GrantedProviders,
|
||||
IsGranted = permission.IsGranted,
|
||||
MenuGroup = menuGroup ?? string.Empty
|
||||
Modules = modules ?? string.Empty
|
||||
};
|
||||
|
||||
newGroup.Permissions.Add(newPermission);
|
||||
|
|
|
|||
|
|
@ -644,7 +644,7 @@ public class PublicAppService : PlatformAppService
|
|||
FaxNumber = NormalizePhoneNumber(input.Tenant.FaxNumber, input.Tenant.Country),
|
||||
Email = input.Tenant.Email,
|
||||
Website = input.Tenant.Website,
|
||||
MenuGroup = input.Tenant.MenuGroup,
|
||||
Modules = input.Tenant.Modules,
|
||||
|
||||
BillingCycle = input.BillingCycle,
|
||||
Period = input.Period,
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public class PlatformTenantAppService : TenantAppService, IPlatformTenantAppServ
|
|||
dto.FaxNumber = tenant.GetFaxNumber();
|
||||
dto.Email = tenant.GetEmail();
|
||||
dto.Website = tenant.GetWebsite();
|
||||
dto.MenuGroup = tenant.GetMenuGroup();
|
||||
dto.Modules = tenant.GetModulesRaw();
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,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 Modules { get; set; }
|
||||
}
|
||||
|
||||
public class CurrencySeedDto
|
||||
|
|
|
|||
|
|
@ -1436,9 +1436,9 @@
|
|||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Menus.MenuGroup",
|
||||
"en": "Menu Groups",
|
||||
"tr": "Menü Grupları"
|
||||
"key": "App.Menus.Module",
|
||||
"en": "Modules",
|
||||
"tr": "Modüller"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -1461,8 +1461,8 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.LicenceItem",
|
||||
"en": "Licence Items",
|
||||
"tr": "Lisans Kalemleri"
|
||||
"en": "Items",
|
||||
"tr": "Öğeler"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -1509,8 +1509,8 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ListformField",
|
||||
"en": "Listform Fields",
|
||||
"tr": "Listform Alanları"
|
||||
"en": "Fields",
|
||||
"tr": "Alanlar"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -6459,38 +6459,38 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.SocialLike",
|
||||
"tr": "Sosyal Beğeniler",
|
||||
"en": "Social Likes"
|
||||
"tr": "Beğeniler",
|
||||
"en": "Likes"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.SocialComment",
|
||||
"tr": "Sosyal Yorumlar",
|
||||
"en": "Social Comments"
|
||||
"tr": "Yorumlar",
|
||||
"en": "Comments"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.SurveyQuestion",
|
||||
"tr": "Anket Soruları",
|
||||
"en": "Survey Questions"
|
||||
"tr": "Sorular",
|
||||
"en": "Questions"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.SurveyQuestionOption",
|
||||
"tr": "Anket Soruları Seçenekleri",
|
||||
"en": "Survey Question Options"
|
||||
"tr": "Sorular Seçenekleri",
|
||||
"en": "Question Options"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.SurveyResponse",
|
||||
"tr": "Anket Yanıtları",
|
||||
"en": "Survey Responses"
|
||||
"tr": "Yanıtlar",
|
||||
"en": "Responses"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.SurveyAnswer",
|
||||
"tr": "Anket Yanıtları Cevapları",
|
||||
"en": "Survey Response Answers"
|
||||
"tr": "Yanıt Cevapları",
|
||||
"en": "Response Answers"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -6537,14 +6537,14 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.Events.EventLike",
|
||||
"tr": "Etkinlik Beğenileri",
|
||||
"en": "Event Likes"
|
||||
"tr": "Beğeniler",
|
||||
"en": "Likes"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.Events.EventComment",
|
||||
"tr": "Etkinlik Yorumları",
|
||||
"en": "Event Comments"
|
||||
"tr": "Yorumlar",
|
||||
"en": "Comments"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -12339,14 +12339,14 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.Announcement.AnnouncementLike",
|
||||
"en": "Announcements Like",
|
||||
"tr": "Duyuru Beğenileri"
|
||||
"en": "Likes",
|
||||
"tr": "Beğeniler"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Intranet.Announcement.AnnouncementComment",
|
||||
"en": "Announcements Comments",
|
||||
"tr": "Duyuru Yorumları"
|
||||
"en": "Comments",
|
||||
"tr": "Yorumlar"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -14234,9 +14234,9 @@
|
|||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listform.ListformField.MenuGroup",
|
||||
"en": "Menu Group",
|
||||
"tr": "Menü Grubu"
|
||||
"key": "App.Listform.ListformField.Modules",
|
||||
"en": "Modules",
|
||||
"tr": "Modüller"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -15302,9 +15302,9 @@
|
|||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listform.ListformField.ShortName",
|
||||
"en": "Short Name",
|
||||
"tr": "Kısa Adı"
|
||||
"key": "App.Listform.ListformField.ModuleId",
|
||||
"en": "Module",
|
||||
"tr": "Modül"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -16406,9 +16406,9 @@
|
|||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.ShortName",
|
||||
"en": "Short Name",
|
||||
"tr": "Kısa Ad"
|
||||
"key": "App.WizardStep1.ModuleId",
|
||||
"en": "Module",
|
||||
"tr": "Modül"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -27285,8 +27285,8 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "AbpTenantManagement.Tenants.Description",
|
||||
"en": "Tenants — the customer/organization records of the platform. Table: AbpTenants · host scope · list screen (Kanban view is also open).\nUsage: every organization using the platform is one row here. The row carries not only the login identity but the whole commercial identity: title, founder, tax office, address and contact information — invoices, licence cards and order records read these fields.\nFields:\n• Name → the tenant's login name; it is also the Code of the DataSource record that carries the tenant's connection\n• OrganizationName, Founder → legal title and the founder shown on the licence card\n• VknTckn, TaxOffice → tax number and tax office; used on invoices and in the order flow\n• Country, City, District, Township, Address1, Address2, PostalCode → address chain; the lookups come from the Definitions › Country/City/District screens\n• Email, Website, PhoneNumber, MobileNumber, FaxNumber → contact information\n• MenuGroup → which module set the tenant may see; menus are filtered by this value\n• IsActive → a passive tenant cannot log in, but its data is preserved\nConnection and seed: the row command opens the TenantsConnectionString dialog. There the tenant's own database connection is defined and the seed flow that writes the tenant's default data (roles, menus, list definitions, language texts) is started. Without a connection the tenant shares the host database.\nSub-tab: Branches (App.Branches) — the tenant's branches are entered without leaving this screen.\nWriting: insert and update are delegated to the list-form-dynamic-api/tenant-insert and tenant-update services, so the ABP tenant creation flow (schema, admin user, default roles) runs on the server rather than through plain SQL.\nWhy it matters: every screen defined with IsTenant = true resolves its data source over this record — first the DataSource row named after the tenant, otherwise the screen's own DataSourceCode.\nCaution: a connection string is never written into code, JSON or a seed file; it lives only in this dialog. Renaming a tenant breaks the DataSource record bound to the old name.",
|
||||
"tr": "Kiracılar — platformu kullanan müşteri/organizasyon kayıtları. Tablo: AbpTenants · host kapsamlı · liste ekranı (Kanban görünümü de açıktır).\nKullanım: platformu kullanan her organizasyon burada bir satırdır. Satır yalnızca oturum kimliğini değil ticari kimliğin tamamını taşır: unvan, kurucu, vergi dairesi, adres ve iletişim bilgileri — fatura, lisans kartı ve sipariş kayıtları bu alanları okur.\nAlanlar:\n• Name → kiracının oturum adı; aynı zamanda kiracı bağlantısını taşıyan DataSource kaydının Code değeridir\n• OrganizationName, Founder → resmi unvan ve lisans kartında görünen kurucu\n• VknTckn, TaxOffice → vergi numarası ve vergi dairesi; faturada ve sipariş akışında kullanılır\n• Country, City, District, Township, Address1, Address2, PostalCode → adres zinciri; lookup'lar Tanımlar › Ülke/Şehir/İlçe ekranlarından gelir\n• Email, Website, PhoneNumber, MobileNumber, FaxNumber → iletişim bilgileri\n• MenuGroup → kiracının hangi modül kümesini göreceği; menüler bu değere göre süzülür\n• IsActive → pasif kiracı oturum açamaz, verisi korunur\nBağlantı ve seed: satırdaki komut TenantsConnectionString diyaloğunu açar. Kiracının kendi veritabanı bağlantısı burada tanımlanır ve kiracının varsayılan verisini (rol, menü, liste tanımları, dil metinleri) basan seed akışı buradan başlatılır. Bağlantı tanımlanmazsa kiracı host veritabanını paylaşır.\nAlt sekme: Şubeler (App.Branches) — kiracının şubeleri bu ekrandan çıkmadan girilir.\nYazma: ekleme ve güncelleme list-form-dynamic-api/tenant-insert ve tenant-update servislerine devredilir; böylece ABP'nin kiracı oluşturma akışı (şema, admin kullanıcı, varsayılan roller) düz SQL yerine sunucuda çalışır.\nNeden önemli: IsTenant = true ile tanımlanan her ekran veri kaynağını bu kayıt üzerinden çözer — önce kiracı adıyla eşleşen DataSource satırı, yoksa ekranın kendi DataSourceCode değeri.\nDikkat: bağlantı dizesi koda, JSON'a veya seed dosyasına yazılmaz; yalnızca bu diyalogda durur. Kiracının adını değiştirmek, eski ada bağlı DataSource kaydını kopartır."
|
||||
"en": "Tenants — the customer/organization records of the platform. Table: AbpTenants · host scope · list screen (Kanban view is also open).\nUsage: every organization using the platform is one row here. The row carries not only the login identity but the whole commercial identity: title, founder, tax office, address and contact information — invoices, licence cards and order records read these fields.\nFields:\n• Name → the tenant's login name; it is also the Code of the DataSource record that carries the tenant's connection\n• OrganizationName, Founder → legal title and the founder shown on the licence card\n• VknTckn, TaxOffice → tax number and tax office; used on invoices and in the order flow\n• Country, City, District, Township, Address1, Address2, PostalCode → address chain; the lookups come from the Definitions › Country/City/District screens\n• Email, Website, PhoneNumber, MobileNumber, FaxNumber → contact information\n• Modules → which modules the tenant may see (pipe separated, e.g. Sas|Adm); menus are filtered by this value\n• IsActive → a passive tenant cannot log in, but its data is preserved\nConnection and seed: the row command opens the TenantsConnectionString dialog. There the tenant's own database connection is defined and the seed flow that writes the tenant's default data (roles, menus, list definitions, language texts) is started. Without a connection the tenant shares the host database.\nSub-tab: Branches (App.Branches) — the tenant's branches are entered without leaving this screen.\nWriting: insert and update are delegated to the list-form-dynamic-api/tenant-insert and tenant-update services, so the ABP tenant creation flow (schema, admin user, default roles) runs on the server rather than through plain SQL.\nWhy it matters: every screen defined with IsTenant = true resolves its data source over this record — first the DataSource row named after the tenant, otherwise the screen's own DataSourceCode.\nCaution: a connection string is never written into code, JSON or a seed file; it lives only in this dialog. Renaming a tenant breaks the DataSource record bound to the old name.",
|
||||
"tr": "Kiracılar — platformu kullanan müşteri/organizasyon kayıtları. Tablo: AbpTenants · host kapsamlı · liste ekranı (Kanban görünümü de açıktır).\nKullanım: platformu kullanan her organizasyon burada bir satırdır. Satır yalnızca oturum kimliğini değil ticari kimliğin tamamını taşır: unvan, kurucu, vergi dairesi, adres ve iletişim bilgileri — fatura, lisans kartı ve sipariş kayıtları bu alanları okur.\nAlanlar:\n• Name → kiracının oturum adı; aynı zamanda kiracı bağlantısını taşıyan DataSource kaydının Code değeridir\n• OrganizationName, Founder → resmi unvan ve lisans kartında görünen kurucu\n• VknTckn, TaxOffice → vergi numarası ve vergi dairesi; faturada ve sipariş akışında kullanılır\n• Country, City, District, Township, Address1, Address2, PostalCode → adres zinciri; lookup'lar Tanımlar › Ülke/Şehir/İlçe ekranlarından gelir\n• Email, Website, PhoneNumber, MobileNumber, FaxNumber → iletişim bilgileri\n• Modules → kiracının göreceği modüller (pipe ile ayrılır, örn. Sas|Adm); menüler bu değere göre süzülür\n• IsActive → pasif kiracı oturum açamaz, verisi korunur\nBağlantı ve seed: satırdaki komut TenantsConnectionString diyaloğunu açar. Kiracının kendi veritabanı bağlantısı burada tanımlanır ve kiracının varsayılan verisini (rol, menü, liste tanımları, dil metinleri) basan seed akışı buradan başlatılır. Bağlantı tanımlanmazsa kiracı host veritabanını paylaşır.\nAlt sekme: Şubeler (App.Branches) — kiracının şubeleri bu ekrandan çıkmadan girilir.\nYazma: ekleme ve güncelleme list-form-dynamic-api/tenant-insert ve tenant-update servislerine devredilir; böylece ABP'nin kiracı oluşturma akışı (şema, admin kullanıcı, varsayılan roller) düz SQL yerine sunucuda çalışır.\nNeden önemli: IsTenant = true ile tanımlanan her ekran veri kaynağını bu kayıt üzerinden çözer — önce kiracı adıyla eşleşen DataSource satırı, yoksa ekranın kendi DataSourceCode değeri.\nDikkat: bağlantı dizesi koda, JSON'a veya seed dosyasına yazılmaz; yalnızca bu diyalogda durur. Kiracının adını değiştirmek, eski ada bağlı DataSource kaydını kopartır."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -27441,20 +27441,20 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Menus.Routes.Description",
|
||||
"en": "Routes — the route records of custom React screens. Table: Sas_H_Route · host scope · list screen.\nUsage: needed only when a page written in code is added — this is the last step of the decision order. Screens produced with a ListForm do not get a route record; they use the ready dynamic routes /admin/list/{code}, /admin/form/{code}, /admin/form/{code}/{id}, /admin/chart/{code}.\nFields:\n• Key → the unique key of the route; the menu record binds to the page over this value\n• Path → the url; parameters are written in the /admin/foo/:id form\n• ComponentType → how the component is resolved (normal)\n• ComponentPath → the component path, e.g. @/views/admin/foo/Foo. The file must exist in the repository\n• RouteType → who may open it: public (no login), authenticated (any logged in user), protected (permission required)\n• Authority → the permissions that may open it; on a protected route this field is mandatory\nCaution: a route whose ComponentPath does not exist breaks the whole menu load, not just that page. In Migrations/MenusData.json the Routes section is managed by the platform — while adding a menu only the MenuGroups and Menus sections are touched.",
|
||||
"tr": "Route'lar — özel React ekranlarının route kayıtları. Tablo: Sas_H_Route · host kapsamlı · liste ekranı.\nKullanım: yalnızca kod ile yazılmış bir sayfa eklenirken gerekir — karar sırasının son adımıdır. ListForm ile üretilen ekranlara route kaydı açılmaz; hazır dinamik rotalar kullanılır: /admin/list/{kod}, /admin/form/{kod}, /admin/form/{kod}/{id}, /admin/chart/{kod}.\nAlanlar:\n• Key → route'un benzersiz anahtarı; menü kaydı sayfaya bu değerle bağlanır\n• Path → url; parametreler /admin/foo/:id biçiminde yazılır\n• ComponentType → bileşenin nasıl çözüleceği (normal)\n• ComponentPath → bileşen yolu, örn. @/views/admin/foo/Foo. Dosyanın depoda bulunması zorunludur\n• RouteType → kimin açabileceği: public (oturumsuz), authenticated (oturum açmış herkes), protected (yetki gerekir)\n• Authority → açabilecek yetkiler; protected route'ta bu alan zorunludur\nDikkat: ComponentPath karşılığı olmayan route yalnızca o sayfayı değil menünün tamamının yüklenmesini bozar. Migrations/MenusData.json içindeki Routes bölümü platform tarafından yönetilir — menü eklerken yalnızca MenuGroups ve Menus bölümlerine dokunulur."
|
||||
"en": "Routes — the route records of custom React screens. Table: Sas_H_Route · host scope · list screen.\nUsage: needed only when a page written in code is added — this is the last step of the decision order. Screens produced with a ListForm do not get a route record; they use the ready dynamic routes /admin/list/{code}, /admin/form/{code}, /admin/form/{code}/{id}, /admin/chart/{code}.\nFields:\n• Key → the unique key of the route; the menu record binds to the page over this value\n• Path → the url; parameters are written in the /admin/foo/:id form\n• ComponentType → how the component is resolved (normal)\n• ComponentPath → the component path, e.g. @/views/admin/foo/Foo. The file must exist in the repository\n• RouteType → who may open it: public (no login), authenticated (any logged in user), protected (permission required)\n• Authority → the permissions that may open it; on a protected route this field is mandatory\nCaution: a route whose ComponentPath does not exist breaks the whole menu load, not just that page. In Migrations/MenusData.json the Routes section is managed by the platform — while adding a menu only the Modules and Menus sections are touched.",
|
||||
"tr": "Route'lar — özel React ekranlarının route kayıtları. Tablo: Sas_H_Route · host kapsamlı · liste ekranı.\nKullanım: yalnızca kod ile yazılmış bir sayfa eklenirken gerekir — karar sırasının son adımıdır. ListForm ile üretilen ekranlara route kaydı açılmaz; hazır dinamik rotalar kullanılır: /admin/list/{kod}, /admin/form/{kod}, /admin/form/{kod}/{id}, /admin/chart/{kod}.\nAlanlar:\n• Key → route'un benzersiz anahtarı; menü kaydı sayfaya bu değerle bağlanır\n• Path → url; parametreler /admin/foo/:id biçiminde yazılır\n• ComponentType → bileşenin nasıl çözüleceği (normal)\n• ComponentPath → bileşen yolu, örn. @/views/admin/foo/Foo. Dosyanın depoda bulunması zorunludur\n• RouteType → kimin açabileceği: public (oturumsuz), authenticated (oturum açmış herkes), protected (yetki gerekir)\n• Authority → açabilecek yetkiler; protected route'ta bu alan zorunludur\nDikkat: ComponentPath karşılığı olmayan route yalnızca o sayfayı değil menünün tamamının yüklenmesini bozar. Migrations/MenusData.json içindeki Routes bölümü platform tarafından yönetilir — menü eklerken yalnızca Modules ve Menus bölümlerine dokunulur."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Menus.MenuGroup.Description",
|
||||
"en": "Menu Group — the root headings of the left menu. Table: Sas_H_MenuGroup · host scope · list screen.\nUsage: a group is the entry point of a module (Saas, Administration, CRM, Production). Menu items are placed under a group and the tenant's MenuGroup field decides which groups it sees.\nFields:\n• Name → group name; menu records and the tenant's MenuGroup value reference this text\nCaution: a new screen is not pushed under an existing 'Definitions' heading by default — a root menu is created for its own module and Order = max(Order) + 1 is used. A group with no menu item is not rendered.",
|
||||
"tr": "Menü Grubu — sol menünün kök başlıkları. Tablo: Sas_H_MenuGroup · host kapsamlı · liste ekranı.\nKullanım: grup, bir modülün giriş noktasıdır (Saas, Administration, CRM, Üretim). Menü öğeleri bir grubun altına yerleşir ve kiracının MenuGroup alanı hangi grupları göreceğini belirler.\nAlanlar:\n• Name → grup adı; menü kayıtları ve kiracının MenuGroup değeri bu metne referans verir\nDikkat: yeni ekran varsayılan olarak mevcut 'Tanımlar' başlığının altına atılmaz — modülüne ait yeni bir kök menü oluşturulur ve Order = max(Order) + 1 kullanılır. Menü öğesi olmayan grup basılmaz."
|
||||
"key": "App.Menus.Module.Description",
|
||||
"en": "Module — the modules of the platform. Table: Sas_H_Module · host scope · list screen.\nUsage: a module is the entry point of a feature set (Saas, Administration, CRM, Production). A root menu binds to a module through its ModuleId field, and the tenant Modules field decides which modules it sees.\nFields:\n• Id → module code; the menu record references it through ModuleId\n• Name → module name; the tenant Modules value references this text\nCaution: a module referenced by a menu cannot be deleted — the foreign key is restricted.",
|
||||
"tr": "Modül — platformun modülleri. Tablo: Sas_H_Module · host kapsamlı · liste ekranı.\nKullanım: modül, bir yetenek kümesinin giriş noktasıdır (Saas, Administration, CRM, Üretim). Kök menü, ModuleId alanı ile bir modüle bağlanır; kiracının Modules alanı hangi modülleri göreceğini belirler.\nAlanlar:\n• Id → modül kodu; menü kaydı ModuleId ile buna referans verir\n• Name → modül adı; kiracının Modules değeri bu metne referans verir\nDikkat: bir menü tarafından kullanılan modül silinemez — yabancı anahtar kısıtlıdır."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Menus.Menu.Description",
|
||||
"en": "Menu — menu items. Table: Sas_H_Menu · host scope · tree layout. The menu comes from the database, not from code.\nUsage: the tree of the left menu is built here. The produced screen becomes visible to the user only after its menu record is opened.\nFields:\n• Code → the unique code of the menu item; the child items reference it through ParentCode\n• ParentCode → the parent menu; the tree structure is formed over this field\n• DisplayName → the language key of the displayed name; the text is written on Language Text\n• ShortName → the short name used in the collapsed menu\n• Url → the address it opens; for a produced screen /admin/list/{ListFormCode}\n• Icon, CssClass → the icon and additional style\n• Order → the ordering among siblings\n• Target → does it open in the same tab or a new one\n• ElementId → the dom id used for tests and guided tours\n• RequiredPermissionName → a menu whose permission the user does not hold is not rendered at all\n• IsDisabled → a disabled item does not appear in the menu; the record is preserved\nRule: the menu item, the route it opens and the permission must show the same contract. A visible menu leading to a screen the user cannot open is a design error.\nCaution: a menu added only from the interface disappears on a database reset; the same record is also written into Migrations/MenusData.json (MenuGroups and Menus sections only).",
|
||||
"tr": "Menü — menü öğeleri. Tablo: Sas_H_Menu · host kapsamlı · ağaç düzeni. Menü koddan değil veritabanından gelir.\nKullanım: sol menünün ağacı burada kurulur. Üretilen ekran, menü kaydı açılmadan kullanıcıya görünmez.\nAlanlar:\n• Code → menü öğesinin benzersiz kodu; alt öğeler ParentCode ile buna referans verir\n• ParentCode → üst menü; ağaç yapısı bu alan üzerinden kurulur\n• DisplayName → görünen adın dil anahtarı; metin Language Text ekranına yazılır\n• ShortName → daraltılmış menüde kullanılan kısa ad\n• Url → açtığı adres; üretilen ekran için /admin/list/{ListFormCode}\n• Icon, CssClass → ikon ve ek stil\n• Order → kardeşleri arasındaki sıra\n• Target → aynı sekmede mi yeni sekmede mi açılacağı\n• ElementId → test ve rehberli tur için kullanılan dom kimliği\n• RequiredPermissionName → kullanıcının yetkisi olmayan menü hiç basılmaz\n• IsDisabled → pasif öğe menüde görünmez, kaydı korunur\nKural: menü öğesi, açtığı route ve yetki aynı sözleşmeyi göstermelidir. Görünen ama açılamayan ekrana götüren menü tasarım hatasıdır.\nDikkat: yalnızca arayüzden eklenen menü veritabanı sıfırlandığında kaybolur; aynı kayıt Migrations/MenusData.json dosyasına da yazılır (yalnızca MenuGroups ve Menus bölümleri)."
|
||||
"en": "Menu — menu items. Table: Sas_H_Menu · host scope · tree layout. The menu comes from the database, not from code.\nUsage: the tree of the left menu is built here. The produced screen becomes visible to the user only after its menu record is opened.\nFields:\n• Code → the unique code of the menu item; the child items reference it through ParentCode\n• ParentCode → the parent menu; the tree structure is formed over this field\n• DisplayName → the language key of the displayed name; the text is written on Language Text\n• ModuleId → the module the root menu belongs to; it references the Module record and the module cannot be deleted while a menu points at it\n• Url → the address it opens; for a produced screen /admin/list/{ListFormCode}\n• Icon, CssClass → the icon and additional style\n• Order → the ordering among siblings\n• Target → does it open in the same tab or a new one\n• ElementId → the dom id used for tests and guided tours\n• RequiredPermissionName → a menu whose permission the user does not hold is not rendered at all\n• IsDisabled → a disabled item does not appear in the menu; the record is preserved\nRule: the menu item, the route it opens and the permission must show the same contract. A visible menu leading to a screen the user cannot open is a design error.\nCaution: a menu added only from the interface disappears on a database reset; the same record is also written into Migrations/MenusData.json (Modules and Menus sections only).",
|
||||
"tr": "Menü — menü öğeleri. Tablo: Sas_H_Menu · host kapsamlı · ağaç düzeni. Menü koddan değil veritabanından gelir.\nKullanım: sol menünün ağacı burada kurulur. Üretilen ekran, menü kaydı açılmadan kullanıcıya görünmez.\nAlanlar:\n• Code → menü öğesinin benzersiz kodu; alt öğeler ParentCode ile buna referans verir\n• ParentCode → üst menü; ağaç yapısı bu alan üzerinden kurulur\n• DisplayName → görünen adın dil anahtarı; metin Language Text ekranına yazılır\n• ModuleId → kök menünün bağlı olduğu modül; Modül kaydına referans verir, menü bağlıyken modül silinemez\n• Url → açtığı adres; üretilen ekran için /admin/list/{ListFormCode}\n• Icon, CssClass → ikon ve ek stil\n• Order → kardeşleri arasındaki sıra\n• Target → aynı sekmede mi yeni sekmede mi açılacağı\n• ElementId → test ve rehberli tur için kullanılan dom kimliği\n• RequiredPermissionName → kullanıcının yetkisi olmayan menü hiç basılmaz\n• IsDisabled → pasif öğe menüde görünmez, kaydı korunur\nKural: menü öğesi, açtığı route ve yetki aynı sözleşmeyi göstermelidir. Görünen ama açılamayan ekrana götüren menü tasarım hatasıdır.\nDikkat: yalnızca arayüzden eklenen menü veritabanı sıfırlandığında kaybolur; aynı kayıt Migrations/MenusData.json dosyasına da yazılır (yalnızca Modules ve Menus bölümleri)."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
@ -27525,8 +27525,8 @@
|
|||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "Abp.Identity.Permissions.Description",
|
||||
"en": "Permissions — the permission definitions of the application. Table: AbpPermissions · tree layout.\nUsage: the permission contract of every screen is visible here. A list screen normally has a root permission plus the .Create, .Update, .Delete, .Export, .Import and .Note sub-permissions; the ListForm PermissionJson maps these codes onto the buttons.\nFields:\n• Name → the permission code, e.g. App.Definitions.Currency.Create. It is the same value referenced from the code (PlatformConsts.AppCodes) and from the UI\n• ParentName → the parent permission; the tree is formed over this field and granting a parent does not automatically grant the children\n• GroupName → the permission group it belongs to\n• DisplayName → the language key of the displayed name\n• MultiTenancySide → on which side it is valid: host, tenant or both. A permission defined only for host is not offered to a tenant role\n• MenuGroup → which module the permission belongs to; it drives the module based filtering of the permission dialogs\n• IsEnabled → a disabled permission is not offered to anyone; it is the fastest way to close a capability across the system\nCaution: a permission added only from the interface is lost on a database reset. The same record is also written into PlatformConsts.AppCodes, Migrations/PermissionsData.json, LanguagesData.json and, if it is used in the interface, into permission.constant.ts.",
|
||||
"tr": "Yetkiler — uygulamanın yetki tanımları. Tablo: AbpPermissions · ağaç düzeni.\nKullanım: her ekranın yetki sözleşmesi burada görünür. Liste ekranı normalde bir kök yetki ile birlikte .Create, .Update, .Delete, .Export, .Import ve .Note alt yetkilerini taşır; ListForm PermissionJson bu kodları butonlara eşler.\nAlanlar:\n• Name → yetki kodu, örn. App.Definitions.Currency.Create. Koddan (PlatformConsts.AppCodes) ve arayüzden referans verilen değerle aynıdır\n• ParentName → üst yetki; ağaç bu alan üzerinden kurulur ve üst yetkiyi vermek alt yetkileri otomatik vermez\n• GroupName → bağlı olduğu yetki grubu\n• DisplayName → görünen adın dil anahtarı\n• MultiTenancySide → hangi tarafta geçerli olduğu: host, tenant veya ikisi. Yalnızca host için tanımlı yetki kiracı rolüne sunulmaz\n• MenuGroup → yetkinin hangi modüle ait olduğu; yetki diyaloglarının modül bazlı süzülmesini sağlar\n• IsEnabled → pasif yetki kimseye sunulmaz; bir yeteneği sistem genelinde kapatmanın en hızlı yoludur\nDikkat: yalnızca arayüzden eklenen yetki veritabanı sıfırlandığında kaybolur. Aynı kayıt PlatformConsts.AppCodes, Migrations/PermissionsData.json, LanguagesData.json ve arayüzde kullanılacaksa permission.constant.ts dosyalarına da yazılır."
|
||||
"en": "Permissions — the permission definitions of the application. Table: AbpPermissions · tree layout.\nUsage: the permission contract of every screen is visible here. A list screen normally has a root permission plus the .Create, .Update, .Delete, .Export, .Import and .Note sub-permissions; the ListForm PermissionJson maps these codes onto the buttons.\nFields:\n• Name → the permission code, e.g. App.Definitions.Currency.Create. It is the same value referenced from the code (PlatformConsts.AppCodes) and from the UI\n• ParentName → the parent permission; the tree is formed over this field and granting a parent does not automatically grant the children\n• GroupName → the permission group it belongs to\n• DisplayName → the language key of the displayed name\n• MultiTenancySide → on which side it is valid: host, tenant or both. A permission defined only for host is not offered to a tenant role\n• Modules → which modules the permission belongs to; it drives the module based filtering of the permission dialogs\n• IsEnabled → a disabled permission is not offered to anyone; it is the fastest way to close a capability across the system\nCaution: a permission added only from the interface is lost on a database reset. The same record is also written into PlatformConsts.AppCodes, Migrations/PermissionsData.json, LanguagesData.json and, if it is used in the interface, into permission.constant.ts.",
|
||||
"tr": "Yetkiler — uygulamanın yetki tanımları. Tablo: AbpPermissions · ağaç düzeni.\nKullanım: her ekranın yetki sözleşmesi burada görünür. Liste ekranı normalde bir kök yetki ile birlikte .Create, .Update, .Delete, .Export, .Import ve .Note alt yetkilerini taşır; ListForm PermissionJson bu kodları butonlara eşler.\nAlanlar:\n• Name → yetki kodu, örn. App.Definitions.Currency.Create. Koddan (PlatformConsts.AppCodes) ve arayüzden referans verilen değerle aynıdır\n• ParentName → üst yetki; ağaç bu alan üzerinden kurulur ve üst yetkiyi vermek alt yetkileri otomatik vermez\n• GroupName → bağlı olduğu yetki grubu\n• DisplayName → görünen adın dil anahtarı\n• MultiTenancySide → hangi tarafta geçerli olduğu: host, tenant veya ikisi. Yalnızca host için tanımlı yetki kiracı rolüne sunulmaz\n• Modules → yetkinin hangi modüllere ait olduğu; yetki diyaloglarının modül bazlı süzülmesini sağlar\n• IsEnabled → pasif yetki kimseye sunulmaz; bir yeteneği sistem genelinde kapatmanın en hızlı yoludur\nDikkat: yalnızca arayüzden eklenen yetki veritabanı sıfırlandığında kaybolur. Aynı kayıt PlatformConsts.AppCodes, Migrations/PermissionsData.json, LanguagesData.json ve arayüzde kullanılacaksa permission.constant.ts dosyalarına da yazılır."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
|
|
|
|||
|
|
@ -410,12 +410,12 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
|||
ListFormCode = listForm.ListFormCode,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.String,
|
||||
FieldName = "MenuGroup",
|
||||
FieldName = "Modules",
|
||||
EditGroupOrderNo = 1,
|
||||
EditOrderNo = 7,
|
||||
EditorType2 = EditorTypes.dxTagBox,
|
||||
ColSpan = 1,
|
||||
CaptionName = "App.Listform.ListformField.MenuGroup",
|
||||
CaptionName = "App.Listform.ListformField.Modules",
|
||||
Width = 0,
|
||||
ListOrderNo = 8,
|
||||
Visible = true,
|
||||
|
|
@ -426,7 +426,7 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
|||
DataSourceType = UiLookupDataSourceTypeEnum.Query,
|
||||
DisplayExpr = "name",
|
||||
ValueExpr = "key",
|
||||
LookupQuery = LookupQueryValues.MenuGroupValues
|
||||
LookupQuery = LookupQueryValues.ModuleValues
|
||||
}),
|
||||
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||
|
|
|
|||
|
|
@ -572,13 +572,12 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
ListFormCode = listForm.ListFormCode,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.String,
|
||||
FieldName = "MenuGroup",
|
||||
FieldName = "Modules",
|
||||
EditGroupOrderNo = 1,
|
||||
EditOrderNo = 9,
|
||||
EditorType2 = EditorTypes.dxSelectBox,
|
||||
EditorType2 = EditorTypes.dxTagBox,
|
||||
ColSpan = 1,
|
||||
EditorOptions = EditorOptions.ShowClearButton(),
|
||||
CaptionName = "App.Listform.ListformField.MenuGroup",
|
||||
CaptionName = "App.Listform.ListformField.Modules",
|
||||
Width = 0,
|
||||
ListOrderNo = 20,
|
||||
Visible = true,
|
||||
|
|
@ -587,7 +586,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
DataSourceType = UiLookupDataSourceTypeEnum.Query,
|
||||
DisplayExpr = "name",
|
||||
ValueExpr = "key",
|
||||
LookupQuery = LookupQueryValues.MenuGroupValues,
|
||||
LookupQuery = LookupQueryValues.ModuleValues,
|
||||
}),
|
||||
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||
|
|
@ -6391,8 +6390,8 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region MenuGroup
|
||||
listFormName = AppCodes.Menus.MenuGroup;
|
||||
#region Module
|
||||
listFormName = AppCodes.Menus.Module;
|
||||
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
|
||||
{
|
||||
var listForm = await _listFormRepository.InsertAsync(
|
||||
|
|
@ -6414,7 +6413,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
IsOrganizationUnit = false,
|
||||
Description = $"{listFormName}.Description",
|
||||
SelectCommandType = SelectCommandTypeEnum.Table,
|
||||
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.MenuGroup)),
|
||||
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.Module)),
|
||||
KeyFieldName = "Id",
|
||||
KeyFieldDbSourceType = DbType.String,
|
||||
SortMode = GridOptions.SortModeSingle,
|
||||
|
|
@ -6430,11 +6429,10 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>
|
||||
{
|
||||
new() { Order = 1, ColCount = 1, ColSpan = 1, ItemType = "group" },
|
||||
}),
|
||||
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(DbType.String, "Name"),
|
||||
})
|
||||
});
|
||||
|
||||
#region MenuGroup Fields
|
||||
#region Module Fields
|
||||
await _listFormFieldRepository.InsertManyAsync([
|
||||
new() {
|
||||
ListFormCode = listForm.ListFormCode,
|
||||
|
|
@ -6816,17 +6814,25 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency
|
|||
ListFormCode = listForm.ListFormCode,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.String,
|
||||
FieldName = "ShortName",
|
||||
FieldName = "ModuleId",
|
||||
EditGroupOrderNo = 1,
|
||||
EditOrderNo = 12,
|
||||
EditorType2 = EditorTypes.dxTextBox,
|
||||
EditorType2 = EditorTypes.dxSelectBox,
|
||||
ColSpan = 1,
|
||||
CaptionName = "App.Listform.ListformField.ShortName",
|
||||
EditorOptions = EditorOptions.ShowClearButton(),
|
||||
CaptionName = "App.Listform.ListformField.ModuleId",
|
||||
Width = 0,
|
||||
ListOrderNo = 13,
|
||||
Visible = true,
|
||||
IsActive = true,
|
||||
|
||||
LookupJson = JsonSerializer.Serialize(new LookupDto
|
||||
{
|
||||
DataSourceType = UiLookupDataSourceTypeEnum.Query,
|
||||
DisplayExpr = "name",
|
||||
ValueExpr = "key",
|
||||
LookupQuery = LookupQueryValues.ModuleValues,
|
||||
}),
|
||||
AllowSearch = true,
|
||||
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public class RouteSeedDto
|
|||
public string[] Authority { get; set; }
|
||||
}
|
||||
|
||||
public class MenuGroupSeedDto
|
||||
public class ModuleSeedDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
|
@ -36,31 +36,31 @@ public class MenuSeedDto
|
|||
public string Icon { get; set; }
|
||||
public string RequiredPermissionName { get; set; }
|
||||
public bool IsDisabled { get; set; }
|
||||
public string ShortName { get; set; }
|
||||
public string ModuleId { get; set; }
|
||||
}
|
||||
|
||||
public class MenuSeederDto
|
||||
{
|
||||
public List<RouteSeedDto> Routes { get; set; }
|
||||
public List<ModuleSeedDto> Modules { 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;
|
||||
private readonly IRepository<Module, string> _moduleRepository;
|
||||
|
||||
public MenuDataSeeder(
|
||||
IRepository<Route, Guid> routeRepository,
|
||||
IRepository<Menu, Guid> menuRepository,
|
||||
IRepository<MenuGroup, string> menuGroupRepository
|
||||
IRepository<Module, string> moduleRepository
|
||||
)
|
||||
{
|
||||
_routeRepository = routeRepository;
|
||||
_menuRepository = menuRepository;
|
||||
_menuGroupRepository = menuGroupRepository;
|
||||
_moduleRepository = moduleRepository;
|
||||
}
|
||||
|
||||
public async Task SeedAsync(DataSeedContext context)
|
||||
|
|
@ -89,13 +89,13 @@ public class MenuDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var item in items.MenuGroups)
|
||||
foreach (var item in items.Modules)
|
||||
{
|
||||
var exists = await _menuGroupRepository.AnyAsync(x => x.Name == item.Name);
|
||||
var exists = await _moduleRepository.AnyAsync(x => x.Name == item.Name);
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
await _menuGroupRepository.InsertAsync(new MenuGroup(item.Name)
|
||||
await _moduleRepository.InsertAsync(new Module(item.Name)
|
||||
{
|
||||
Name = item.Name
|
||||
}, autoSave: true);
|
||||
|
|
@ -108,6 +108,10 @@ public class MenuDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
|
||||
if (!exists)
|
||||
{
|
||||
// Menunun bagli oldugu modul Modules bolumunde tanimli degilse burada olusturulur;
|
||||
// aksi halde ModuleId yabanci anahtari seed sirasinda hata verir.
|
||||
await EnsureModuleAsync(item.ModuleId);
|
||||
|
||||
await _menuRepository.InsertAsync(new Menu
|
||||
{
|
||||
ParentCode = string.IsNullOrWhiteSpace(item.ParentCode) ? null : item.ParentCode,
|
||||
|
|
@ -118,9 +122,25 @@ public class MenuDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
Icon = item.Icon,
|
||||
RequiredPermissionName = item.RequiredPermissionName,
|
||||
IsDisabled = item.IsDisabled,
|
||||
ShortName = item.ShortName
|
||||
ModuleId = item.ModuleId
|
||||
}, autoSave: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task EnsureModuleAsync(string moduleId)
|
||||
{
|
||||
var cleaned = moduleId?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(cleaned))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (await _moduleRepository.AnyAsync(x => x.Id == cleaned))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _moduleRepository.InsertAsync(new Module(cleaned) { Name = cleaned }, autoSave: true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -457,12 +457,12 @@
|
|||
"authority": ["App.Videoroom.Detail"]
|
||||
}
|
||||
],
|
||||
"MenuGroups": [
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "Erp"
|
||||
"Name": "Sas"
|
||||
},
|
||||
{
|
||||
"Name": "Kurs"
|
||||
"Name": "Adm"
|
||||
}
|
||||
],
|
||||
"Menus": [
|
||||
|
|
@ -475,7 +475,7 @@
|
|||
"Icon": "FcPodiumWithAudience",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false,
|
||||
"ShortName": "Sas"
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -485,7 +485,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcFilingCabinet",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -495,7 +496,8 @@
|
|||
"Url": "/admin/list/App.Definitions.AiBot",
|
||||
"Icon": "FcMindMap",
|
||||
"RequiredPermissionName": "App.Definitions.AiBot",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -505,7 +507,8 @@
|
|||
"Url": "/admin/list/App.Definitions.GlobalSearch",
|
||||
"Icon": "FcSearch",
|
||||
"RequiredPermissionName": "App.Definitions.GlobalSearch",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -515,7 +518,8 @@
|
|||
"Url": "/admin/list/App.Definitions.ContactTitle",
|
||||
"Icon": "FcNeutralDecision",
|
||||
"RequiredPermissionName": "App.Definitions.ContactTitle",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -525,7 +529,8 @@
|
|||
"Url": "/admin/list/App.Definitions.Currency",
|
||||
"Icon": "FcCurrencyExchange",
|
||||
"RequiredPermissionName": "App.Definitions.Currency",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -535,7 +540,8 @@
|
|||
"Url": "/admin/list/App.Definitions.CountryGroup",
|
||||
"Icon": "FaFlag",
|
||||
"RequiredPermissionName": "App.Definitions.CountryGroup",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -545,7 +551,8 @@
|
|||
"Url": "/admin/list/App.Definitions.Country",
|
||||
"Icon": "FaFlagCheckered",
|
||||
"RequiredPermissionName": "App.Definitions.Country",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -555,7 +562,8 @@
|
|||
"Url": "/admin/list/App.Definitions.City",
|
||||
"Icon": "FaFontAwesomeFlag",
|
||||
"RequiredPermissionName": "App.Definitions.City",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -565,7 +573,8 @@
|
|||
"Url": "/admin/list/App.Definitions.District",
|
||||
"Icon": "FaFontAwesome",
|
||||
"RequiredPermissionName": "App.Definitions.District",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -575,7 +584,8 @@
|
|||
"Url": "/admin/list/App.Definitions.SkillType",
|
||||
"Icon": "FcMindMap",
|
||||
"RequiredPermissionName": "App.Definitions.SkillType",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -585,7 +595,8 @@
|
|||
"Url": "/admin/list/App.Definitions.UomCategory",
|
||||
"Icon": "FcWorkflow",
|
||||
"RequiredPermissionName": "App.Definitions.UomCategory",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas.Definitions",
|
||||
|
|
@ -595,7 +606,8 @@
|
|||
"Url": "/admin/list/App.Definitions.Sequence",
|
||||
"Icon": "FcNumericalSorting12",
|
||||
"RequiredPermissionName": "App.Definitions.Sequence",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -605,7 +617,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcTemplate",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -615,7 +628,8 @@
|
|||
"Url": "/admin/public/home/designer",
|
||||
"Icon": "FcHome",
|
||||
"RequiredPermissionName": "App.Home",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -625,7 +639,8 @@
|
|||
"Url": "/admin/public/about/designer",
|
||||
"Icon": "FcAbout",
|
||||
"RequiredPermissionName": "App.About",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -635,7 +650,8 @@
|
|||
"Url": "/admin/public/services/designer",
|
||||
"Icon": "FcServices",
|
||||
"RequiredPermissionName": "App.Services",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -645,7 +661,8 @@
|
|||
"Url": "/admin/list/App.Orders.Products",
|
||||
"Icon": "FcDiploma1",
|
||||
"RequiredPermissionName": "App.Orders.Products",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -655,7 +672,8 @@
|
|||
"Url": "/admin/list/App.Orders.PaymentMethods",
|
||||
"Icon": "FcFeedIn",
|
||||
"RequiredPermissionName": "App.Orders.PaymentMethods",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -665,7 +683,8 @@
|
|||
"Url": "/admin/list/App.Orders.InstallmentOptions",
|
||||
"Icon": "FcProcess",
|
||||
"RequiredPermissionName": "App.Orders.InstallmentOptions",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -675,7 +694,8 @@
|
|||
"Url": "/admin/list/App.Orders.SalesOrders",
|
||||
"Icon": "FcCollect",
|
||||
"RequiredPermissionName": "App.Orders.SalesOrders",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -685,7 +705,8 @@
|
|||
"Url": "/admin/list/App.BlogManagement.Category",
|
||||
"Icon": "FaCertificate",
|
||||
"RequiredPermissionName": "App.BlogManagement.Category",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -695,7 +716,8 @@
|
|||
"Url": "/admin/list/App.BlogManagement.Posts",
|
||||
"Icon": "FaWeixin",
|
||||
"RequiredPermissionName": "App.BlogManagement.Posts",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -705,7 +727,8 @@
|
|||
"Url": "/admin/list/App.Demos",
|
||||
"Icon": "FcMissedCall",
|
||||
"RequiredPermissionName": "App.Demos",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Public",
|
||||
|
|
@ -715,7 +738,8 @@
|
|||
"Url": "/admin/public/contact/designer",
|
||||
"Icon": "FcContacts",
|
||||
"RequiredPermissionName": "App.Contact",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -725,7 +749,8 @@
|
|||
"Url": "/admin/list/App.DevRequests",
|
||||
"Icon": "FcIdea",
|
||||
"RequiredPermissionName": "App.DevRequests",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -735,7 +760,8 @@
|
|||
"Url": "/admin/list/AbpTenantManagement.Tenants",
|
||||
"Icon": "FcDepartment",
|
||||
"RequiredPermissionName": "AbpTenantManagement.Tenants",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -745,7 +771,8 @@
|
|||
"Url": "/admin/list/App.Branches",
|
||||
"Icon": "FcTreeStructure",
|
||||
"RequiredPermissionName": "App.Branches",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -755,7 +782,8 @@
|
|||
"Url": "/admin/list/App.SettingDefinitions",
|
||||
"Icon": "FcSupport",
|
||||
"RequiredPermissionName": "App.SettingDefinitions",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -765,7 +793,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcGlobe",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Languages",
|
||||
|
|
@ -775,7 +804,8 @@
|
|||
"Url": "/admin/list/App.Languages.Language",
|
||||
"Icon": "FcGraduationCap",
|
||||
"RequiredPermissionName": "App.Languages.Language",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Languages",
|
||||
|
|
@ -785,7 +815,8 @@
|
|||
"Url": "/admin/list/App.Languages.LanguageText",
|
||||
"Icon": "FcMindMap",
|
||||
"RequiredPermissionName": "App.Languages.LanguageText",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -795,7 +826,8 @@
|
|||
"Url": "/admin/list/App.DataSource",
|
||||
"Icon": "FcAcceptDatabase",
|
||||
"RequiredPermissionName": "App.DataSource",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -805,7 +837,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcWorkflow",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Notifications",
|
||||
|
|
@ -815,7 +848,8 @@
|
|||
"Url": "/admin/list/App.Notifications.NotificationTypes",
|
||||
"Icon": "FcComboChart",
|
||||
"RequiredPermissionName": "App.Notifications.NotificationTypes",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Notifications",
|
||||
|
|
@ -825,7 +859,8 @@
|
|||
"Url": "/admin/list/App.Notifications.NotificationRules",
|
||||
"Icon": "FcLibrary",
|
||||
"RequiredPermissionName": "App.Notifications.NotificationRules",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Notifications",
|
||||
|
|
@ -835,7 +870,8 @@
|
|||
"Url": "/admin/list/App.Notifications.Notification",
|
||||
"Icon": "FcBrokenLink",
|
||||
"RequiredPermissionName": "App.Notifications.Notification",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -846,7 +882,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcSynchronize",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.BackgroundWorkers",
|
||||
|
|
@ -856,7 +893,8 @@
|
|||
"Url": "/admin/list/App.BackgroundWorkers.RecurringJobs",
|
||||
"Icon": "FcDataConfiguration",
|
||||
"RequiredPermissionName": "App.BackgroundWorkers.RecurringJobs",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.BackgroundWorkers",
|
||||
|
|
@ -866,7 +904,8 @@
|
|||
"Url": "/admin/list/App.BackgroundWorkers.Jobs",
|
||||
"Icon": "FcFlowChart",
|
||||
"RequiredPermissionName": "App.BackgroundWorkers.Jobs",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -876,27 +915,30 @@
|
|||
"Url": null,
|
||||
"Icon": "FcParallelTasks",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Menus",
|
||||
"Code": "App.Menus.Module",
|
||||
"DisplayName": "App.Menus.Module",
|
||||
"Order": 1,
|
||||
"Url": "/admin/list/App.Menus.Module",
|
||||
"Icon": "FcGrid",
|
||||
"RequiredPermissionName": "App.Menus.Module",
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Menus",
|
||||
"Code": "App.Menus.Routes",
|
||||
"DisplayName": "App.Menus.Routes",
|
||||
"Order": 1,
|
||||
"Order": 2,
|
||||
"Url": "/admin/list/App.Menus.Routes",
|
||||
"Icon": "FcMultipleInputs",
|
||||
"RequiredPermissionName": "App.Menus.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
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Menus",
|
||||
|
|
@ -906,7 +948,8 @@
|
|||
"Url": "/admin/list/App.Menus.Menu",
|
||||
"Icon": "FcMenu",
|
||||
"RequiredPermissionName": "App.Menus.Menu",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Menus",
|
||||
|
|
@ -916,7 +959,8 @@
|
|||
"Url": "/admin/menuManager",
|
||||
"Icon": "FaRegListAlt",
|
||||
"RequiredPermissionName": "App.Menus.Manager",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -926,7 +970,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcAndroidOs",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.DeveloperKit",
|
||||
|
|
@ -936,7 +981,8 @@
|
|||
"Url": "/admin/sqlQueryManager",
|
||||
"Icon": "FaDatabase",
|
||||
"RequiredPermissionName": "App.SqlQueryManager",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.DeveloperKit",
|
||||
|
|
@ -946,7 +992,8 @@
|
|||
"Url": "/admin/list/App.DeveloperKit.CustomEndpoints",
|
||||
"Icon": "FcMindMap",
|
||||
"RequiredPermissionName": "App.DeveloperKit.CustomEndpoints",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.DeveloperKit",
|
||||
|
|
@ -956,7 +1003,8 @@
|
|||
"Url": "/admin/developerkit/dynamic-services",
|
||||
"Icon": "FcCommandLine",
|
||||
"RequiredPermissionName": "App.DeveloperKit.DynamicServices",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.DeveloperKit",
|
||||
|
|
@ -966,7 +1014,8 @@
|
|||
"Url": "/admin/developerkit/components",
|
||||
"Icon": "FcBiohazard",
|
||||
"RequiredPermissionName": "App.DeveloperKit.Components",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.DeveloperKit",
|
||||
|
|
@ -976,7 +1025,8 @@
|
|||
"Url": "/admin/list/App.Listforms.Listform",
|
||||
"Icon": "FcDataSheet",
|
||||
"RequiredPermissionName": "App.Listforms.Listform",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.DeveloperKit",
|
||||
|
|
@ -986,7 +1036,8 @@
|
|||
"Url": "/admin/listform/wizardManager",
|
||||
"Icon": "FcFlashAuto",
|
||||
"RequiredPermissionName": "App.Listforms.Wizard",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Saas",
|
||||
|
|
@ -996,7 +1047,8 @@
|
|||
"Url": "/admin/forumManagement",
|
||||
"Icon": "FcReading",
|
||||
"RequiredPermissionName": "App.ForumManagement",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Sas"
|
||||
},
|
||||
{
|
||||
"ParentCode": null,
|
||||
|
|
@ -1007,7 +1059,7 @@
|
|||
"Icon": "FcOrganization",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false,
|
||||
"ShortName": "Adm"
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1017,7 +1069,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcFilingCabinet",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Definitions",
|
||||
|
|
@ -1027,7 +1080,8 @@
|
|||
"Url": "/admin/list/App.Definitions.Sector",
|
||||
"Icon": "FcBiomass",
|
||||
"RequiredPermissionName": "App.Definitions.Sector",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Definitions",
|
||||
|
|
@ -1037,7 +1091,8 @@
|
|||
"Url": "/admin/list/App.Definitions.Department",
|
||||
"Icon": "FcDepartment",
|
||||
"RequiredPermissionName": "App.Definitions.Department",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Definitions",
|
||||
|
|
@ -1047,7 +1102,8 @@
|
|||
"Url": "/admin/list/App.Definitions.JobPosition",
|
||||
"Icon": "FcDebt",
|
||||
"RequiredPermissionName": "App.Definitions.JobPosition",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Definitions",
|
||||
|
|
@ -1057,7 +1113,8 @@
|
|||
"Url": "/admin/organization",
|
||||
"Icon": "FaSitemap",
|
||||
"RequiredPermissionName": "App.Definitions.OrgChart",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1067,7 +1124,8 @@
|
|||
"Url": "/admin/form/App.Licence",
|
||||
"Icon": "FcRules",
|
||||
"RequiredPermissionName": "App.Licence",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1077,7 +1135,8 @@
|
|||
"Url": "/admin/list/App.DevRequest",
|
||||
"Icon": "FcIdea",
|
||||
"RequiredPermissionName": "App.DevRequest",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1087,7 +1146,8 @@
|
|||
"Url": "/admin/list/App.Agenda",
|
||||
"Icon": "FcPlanner",
|
||||
"RequiredPermissionName": "App.Agenda",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1097,7 +1157,8 @@
|
|||
"Url": "/admin/settings",
|
||||
"Icon": "FcSettings",
|
||||
"RequiredPermissionName": "App.Setting",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1107,7 +1168,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcConferenceCall",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Intranet",
|
||||
|
|
@ -1117,7 +1179,8 @@
|
|||
"Url": "/admin/list/App.Intranet.Announcement",
|
||||
"Icon": "FcAdvertising",
|
||||
"RequiredPermissionName": "App.Intranet.Announcement",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Intranet",
|
||||
|
|
@ -1127,7 +1190,8 @@
|
|||
"Url": "/admin/list/App.Intranet.Survey",
|
||||
"Icon": "FcTodoList",
|
||||
"RequiredPermissionName": "App.Intranet.Survey",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Intranet",
|
||||
|
|
@ -1137,7 +1201,8 @@
|
|||
"Url": "/admin/list/App.Intranet.SocialPost",
|
||||
"Icon": "FcComments",
|
||||
"RequiredPermissionName": "App.Intranet.SocialPost",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Intranet",
|
||||
|
|
@ -1147,7 +1212,8 @@
|
|||
"Url": "/admin/list/App.Intranet.Events.EventType",
|
||||
"Icon": "FcPlanner",
|
||||
"RequiredPermissionName": "App.Intranet.Events.EventType",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Intranet",
|
||||
|
|
@ -1157,7 +1223,8 @@
|
|||
"Url": "/admin/list/App.Intranet.Events.EventCategory",
|
||||
"Icon": "FcTreeStructure",
|
||||
"RequiredPermissionName": "App.Intranet.Events.EventCategory",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Intranet",
|
||||
|
|
@ -1167,7 +1234,8 @@
|
|||
"Url": "/admin/list/App.Intranet.Events.Event",
|
||||
"Icon": "FcCalendar",
|
||||
"RequiredPermissionName": "App.Intranet.Events.Event",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1177,7 +1245,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FaLock",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Restrictions",
|
||||
|
|
@ -1187,7 +1256,8 @@
|
|||
"Url": "/admin/list/App.Restrictions.WorkHour",
|
||||
"Icon": "FcClock",
|
||||
"RequiredPermissionName": "App.Restrictions.WorkHour",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration.Restrictions",
|
||||
|
|
@ -1197,7 +1267,8 @@
|
|||
"Url": "/admin/list/App.Restrictions.IpRestrictions",
|
||||
"Icon": "FcNfcSign",
|
||||
"RequiredPermissionName": "App.Restrictions.IpRestrictions",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1207,7 +1278,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcConferenceCall",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1217,7 +1289,8 @@
|
|||
"Url": "/admin/list/Abp.Identity.PermissionGroups",
|
||||
"Icon": "FcEngineering",
|
||||
"RequiredPermissionName": "Abp.Identity.PermissionGroups",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1227,7 +1300,8 @@
|
|||
"Url": "/admin/list/Abp.Identity.Permissions",
|
||||
"Icon": "FcSupport",
|
||||
"RequiredPermissionName": "Abp.Identity.Permissions",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1237,7 +1311,8 @@
|
|||
"Url": "/admin/list/App.IdentityManagement.ClaimType",
|
||||
"Icon": "FcOrganization",
|
||||
"RequiredPermissionName": "App.IdentityManagement.ClaimType",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1247,7 +1322,8 @@
|
|||
"Url": "/admin/list/AbpIdentity.Roles",
|
||||
"Icon": "FcFlowChart",
|
||||
"RequiredPermissionName": "AbpIdentity.Roles",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1257,7 +1333,8 @@
|
|||
"Url": "/admin/list/AbpIdentity.Users",
|
||||
"Icon": "FcBusinessman",
|
||||
"RequiredPermissionName": "AbpIdentity.Users",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1267,7 +1344,8 @@
|
|||
"Url": "/admin/ous",
|
||||
"Icon": "FcOrganization",
|
||||
"RequiredPermissionName": "Abp.Identity.OrganizationUnits",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1277,7 +1355,8 @@
|
|||
"Url": "/admin/list/App.IdentityManagement.AuditLogs",
|
||||
"Icon": "FcMultipleInputs",
|
||||
"RequiredPermissionName": "App.IdentityManagement.AuditLogs",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "Abp.Identity",
|
||||
|
|
@ -1287,7 +1366,8 @@
|
|||
"Url": "/admin/list/App.IdentityManagement.Sessions",
|
||||
"Icon": "FcPrivacy",
|
||||
"RequiredPermissionName": "App.IdentityManagement.Sessions",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1297,7 +1377,8 @@
|
|||
"Url": null,
|
||||
"Icon": "FcDocument",
|
||||
"RequiredPermissionName": null,
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Reports.Management",
|
||||
|
|
@ -1307,7 +1388,8 @@
|
|||
"Url": "/admin/list/App.Reports.Categories",
|
||||
"Icon": "FcProcess",
|
||||
"RequiredPermissionName": "App.Reports.Categories",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Reports.Management",
|
||||
|
|
@ -1317,7 +1399,8 @@
|
|||
"Url": "/admin/list/App.Reports.ReportTemplates",
|
||||
"Icon": "FcSimCardChip",
|
||||
"RequiredPermissionName": "App.Reports.ReportTemplates",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1327,7 +1410,8 @@
|
|||
"Url": "/admin/videoroom/dashboard",
|
||||
"Icon": "FcVideoCall",
|
||||
"RequiredPermissionName": "App.Videoroom",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1337,7 +1421,8 @@
|
|||
"Url": "/admin/files",
|
||||
"Icon": "FcFolder",
|
||||
"RequiredPermissionName": "App.Files",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
},
|
||||
{
|
||||
"ParentCode": "App.Administration",
|
||||
|
|
@ -1347,7 +1432,8 @@
|
|||
"Url": "/admin/forum",
|
||||
"Icon": "FcLink",
|
||||
"RequiredPermissionName": "App.ForumManagement.Publish",
|
||||
"IsDisabled": false
|
||||
"IsDisabled": false,
|
||||
"ModuleId": "Adm"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class PermissionDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
MultiTenancySide = (MultiTenancySides)item.MultiTenancySide,
|
||||
};
|
||||
|
||||
perm.SetMenuGroup(item.MenuGroup);
|
||||
perm.SetModules(item.Modules);
|
||||
|
||||
await _permissionRepository.InsertAsync(perm, autoSave: true);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -187,6 +187,7 @@ public class PlatformIdentityDataSeeder : IdentityDataSeeder
|
|||
new(Guid.NewGuid(), IdentityPermissions.Roles.Delete, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Roles.Update, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Roles.Default + ".Export", "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Roles.Default + ".Import", "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Roles.ManagePermissions, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Users.Default, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Users.Create, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
|
|
@ -194,6 +195,7 @@ public class PlatformIdentityDataSeeder : IdentityDataSeeder
|
|||
new(Guid.NewGuid(), IdentityPermissions.Users.Update, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Users.ManagePermissions, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Users.Default + ".Export", "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Users.Default + ".Import", "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.Users.ManageRoles, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
new(Guid.NewGuid(), IdentityPermissions.UserLookup.Default, "R", PlatformConsts.AbpIdentity.User.AdminRoleName, tenantId),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
private readonly IRepository<PermissionGroupDefinitionRecord, Guid> _repoPermGroup;
|
||||
private readonly IRepository<PermissionDefinitionRecord, Guid> _repoPerm;
|
||||
private readonly IRepository<Menu, Guid> _repoMenu;
|
||||
private readonly IRepository<Module, string> _repoModule;
|
||||
private readonly IRepository<DataSource, Guid> _repoDataSource;
|
||||
private readonly IRepository<ListForm, Guid> _repoListForm;
|
||||
private readonly IRepository<ListFormField, Guid> _repoListFormField;
|
||||
|
|
@ -50,6 +51,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
IRepository<PermissionGroupDefinitionRecord, Guid> repoPermGroup,
|
||||
IRepository<PermissionDefinitionRecord, Guid> repoPerm,
|
||||
IRepository<Menu, Guid> repoMenu,
|
||||
IRepository<Module, string> repoModule,
|
||||
IRepository<DataSource, Guid> repoDataSource,
|
||||
IRepository<ListForm, Guid> repoListForm,
|
||||
IRepository<ListFormField, Guid> repoListFormField,
|
||||
|
|
@ -62,6 +64,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
_repoPermGroup = repoPermGroup;
|
||||
_repoPerm = repoPerm;
|
||||
_repoMenu = repoMenu;
|
||||
_repoModule = repoModule;
|
||||
_repoDataSource = repoDataSource;
|
||||
_repoListForm = repoListForm;
|
||||
_repoListFormField = repoListFormField;
|
||||
|
|
@ -113,7 +116,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
|
||||
await BackfillMenuParentShortNameAsync(seedFile.Wizard);
|
||||
await BackfillMenuParentModuleIdAsync(seedFile.Wizard);
|
||||
|
||||
// Zaten seeded mi kontrol et. Custom yolunda ListForm üretilmediği için
|
||||
// idempotency menü kaydı üzerinden değerlendirilir.
|
||||
|
|
@ -269,6 +272,8 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
if (input.CreateMenu)
|
||||
{
|
||||
// Menu Parent
|
||||
await EnsureModuleAsync(input.MenuParentModuleId);
|
||||
|
||||
var menuQueryable = await _repoMenu.GetQueryableAsync();
|
||||
var menuParent = await _repoMenu.FirstOrDefaultAsync(a => a.Code == input.MenuParentCode);
|
||||
if (menuParent == null)
|
||||
|
|
@ -285,7 +290,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
Code = input.MenuParentCode,
|
||||
DisplayName = input.MenuParentCode,
|
||||
IsDisabled = false,
|
||||
ShortName = input.MenuParentShortName,
|
||||
ModuleId = input.MenuParentModuleId,
|
||||
Icon = menuParentIcon,
|
||||
Order = maxRootOrder + 1,
|
||||
}, autoSave: true);
|
||||
|
|
@ -312,6 +317,7 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
Url = menuUrl,
|
||||
RequiredPermissionName = permRead.Name,
|
||||
Order = menuOrder,
|
||||
ModuleId = menuParent.ModuleId,
|
||||
}, autoSave: true);
|
||||
}
|
||||
else if (existingMenu.Order != menuOrder || existingMenu.Url != menuUrl)
|
||||
|
|
@ -593,22 +599,41 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
return routePath.StartsWith('/') ? routePath : "/" + routePath;
|
||||
}
|
||||
|
||||
private async Task BackfillMenuParentShortNameAsync(ListFormWizardDto input)
|
||||
/// <summary>
|
||||
/// Seed dosyasindaki modul kaydi yoksa olusturur; menunun ModuleId yabanci anahtari
|
||||
/// tanimsiz bir module bagli kalmasin diye menu yazilmadan once cagrilir.
|
||||
/// </summary>
|
||||
private async Task EnsureModuleAsync(string moduleId)
|
||||
{
|
||||
var cleaned = moduleId?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(cleaned))
|
||||
return;
|
||||
|
||||
if (await _repoModule.AnyAsync(a => a.Id == cleaned))
|
||||
return;
|
||||
|
||||
await _repoModule.InsertAsync(new Module(cleaned) { Name = cleaned }, autoSave: true);
|
||||
_logger.LogInformation("Module '{ModuleId}' seed sirasinda olusturuldu.", cleaned);
|
||||
}
|
||||
|
||||
private async Task BackfillMenuParentModuleIdAsync(ListFormWizardDto input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input.MenuParentCode) ||
|
||||
string.IsNullOrWhiteSpace(input.MenuParentShortName))
|
||||
string.IsNullOrWhiteSpace(input.MenuParentModuleId))
|
||||
return;
|
||||
|
||||
await EnsureModuleAsync(input.MenuParentModuleId);
|
||||
|
||||
var menuParent = await _repoMenu.FirstOrDefaultAsync(a => a.Code == input.MenuParentCode);
|
||||
if (menuParent == null || !string.IsNullOrWhiteSpace(menuParent.ShortName))
|
||||
if (menuParent == null || !string.IsNullOrWhiteSpace(menuParent.ModuleId))
|
||||
return;
|
||||
|
||||
menuParent.ShortName = input.MenuParentShortName.Trim();
|
||||
menuParent.ModuleId = input.MenuParentModuleId.Trim();
|
||||
await _repoMenu.UpdateAsync(menuParent, autoSave: true);
|
||||
_logger.LogInformation(
|
||||
"Menu parent '{MenuParentCode}' ShortName backfilled as '{ShortName}'.",
|
||||
"Menu parent '{MenuParentCode}' ModuleId backfilled as '{ModuleId}'.",
|
||||
input.MenuParentCode,
|
||||
menuParent.ShortName);
|
||||
menuParent.ModuleId);
|
||||
}
|
||||
|
||||
private static bool HasWorkflow(WorkflowDto workflow)
|
||||
|
|
|
|||
|
|
@ -4,17 +4,8 @@ namespace Sozsoft.Platform.Enums;
|
|||
|
||||
public enum MenuPrefix
|
||||
{
|
||||
Saas,
|
||||
Sas,
|
||||
Administration,
|
||||
Crm,
|
||||
Coordinator,
|
||||
SupplyChain,
|
||||
Maintenance,
|
||||
Store,
|
||||
Project,
|
||||
Hr,
|
||||
Mrp,
|
||||
Accounting
|
||||
}
|
||||
|
||||
public static class MenuPrefixExtensions
|
||||
|
|
@ -23,17 +14,8 @@ public static class MenuPrefixExtensions
|
|||
{
|
||||
return menu switch
|
||||
{
|
||||
MenuPrefix.Saas => "Sas",
|
||||
MenuPrefix.Sas => "Sas",
|
||||
MenuPrefix.Administration => "Adm",
|
||||
MenuPrefix.Crm => "Crm",
|
||||
MenuPrefix.Coordinator => "Crd",
|
||||
MenuPrefix.SupplyChain => "Scp",
|
||||
MenuPrefix.Maintenance => "Mnt",
|
||||
MenuPrefix.Store => "Str",
|
||||
MenuPrefix.Project => "Prj",
|
||||
MenuPrefix.Hr => "Hr",
|
||||
MenuPrefix.Mrp => "Mrp",
|
||||
MenuPrefix.Accounting => "Acc",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(menu), menu, null)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public enum TableNameEnum
|
|||
BranchUsers,
|
||||
GlobalSearch,
|
||||
Route,
|
||||
MenuGroup,
|
||||
Module,
|
||||
Menu,
|
||||
DataSource,
|
||||
ListForm,
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@ public static class TablePrefix
|
|||
public const string TenantPrefix = "T";
|
||||
public const string BranchPrefix = "B";
|
||||
|
||||
public static string PlatformByName(MenuPrefix MenuGroup, TableNameEnum tableName)
|
||||
public static string PlatformByName(MenuPrefix menuPrefix, TableNameEnum tableName)
|
||||
{
|
||||
return $"{MenuPrefixExtensions.ToPrefix(MenuGroup)}_{HostPrefix}_{tableName}";
|
||||
return $"{MenuPrefixExtensions.ToPrefix(menuPrefix)}_{HostPrefix}_{tableName}";
|
||||
}
|
||||
|
||||
public static string TenantByName(MenuPrefix MenuGroup, TableNameEnum tableName)
|
||||
public static string TenantByName(MenuPrefix menuPrefix, TableNameEnum tableName)
|
||||
{
|
||||
return $"{MenuPrefixExtensions.ToPrefix(MenuGroup)}_{TenantPrefix}_{tableName}";
|
||||
return $"{MenuPrefixExtensions.ToPrefix(menuPrefix)}_{TenantPrefix}_{tableName}";
|
||||
}
|
||||
|
||||
public static string BranchByName(MenuPrefix MenuGroup, TableNameEnum tableName)
|
||||
public static string BranchByName(MenuPrefix menuPrefix, TableNameEnum tableName)
|
||||
{
|
||||
return $"{MenuPrefixExtensions.ToPrefix(MenuGroup)}_{BranchPrefix}_{tableName}";
|
||||
return $"{MenuPrefixExtensions.ToPrefix(menuPrefix)}_{BranchPrefix}_{tableName}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public static class PlatformConsts
|
|||
|
||||
public static class Permissions
|
||||
{
|
||||
public const string MenuGroup = "MenuGroup";
|
||||
public const string Modules = "Modules";
|
||||
}
|
||||
|
||||
public static class Tenants
|
||||
|
|
@ -52,7 +52,7 @@ public static class PlatformConsts
|
|||
public const string FaxNumber = "FaxNumber";
|
||||
public const string Email = "Email";
|
||||
public const string Website = "Website";
|
||||
public const string MenuGroup = "MenuGroup";
|
||||
public const string Modules = "Modules";
|
||||
}
|
||||
|
||||
public static class Branches
|
||||
|
|
@ -465,7 +465,7 @@ public static class PlatformConsts
|
|||
public const string Default = Prefix.App + ".Menus";
|
||||
|
||||
public const string Routes = Default + ".Routes";
|
||||
public const string MenuGroup = Default + ".MenuGroup";
|
||||
public const string Module = Default + ".Module";
|
||||
public const string Menu = Default + ".Menu";
|
||||
public const string Manager = Default + ".Manager";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,67 +12,67 @@ public static class TableNameResolver
|
|||
_map = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
// 🔹 SAAS TABLOLARI
|
||||
{ nameof(TableNameEnum.DbTableColumn), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.LogEntry), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.AiBot), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ChangeLog), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.GlobalSearch), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ContactTitle), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Currency), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.CountryGroup), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Country), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.City), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.District), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.SkillType), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Skill), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.SkillLevel), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.UomCategory), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Uom), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Branch), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BranchUsers), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.SettingDefinition), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Language), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.LanguageKey), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.LanguageText), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.DataSource), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ListForm), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ListFormField), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ListFormCustomization), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ListFormImport), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ListFormImportLog), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ListFormWorkflow), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Notification), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.NotificationRule), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.NotificationType), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_JobFlow), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_MailQueue), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_MailQueueEvents), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_MailQueueTableFormat), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ForumCategory), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ForumTopic), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.ForumPost), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Home), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.About), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Service), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Product), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.PaymentMethod), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.InstallmentOption), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.Order), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.OrderItem), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.OrderItem_ByTenantId), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BlogCategory), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.BlogPost), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ 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) },
|
||||
{ nameof(TableNameEnum.CustomComponent), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.DynamicService), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.DevRequest), (TablePrefix.PlatformByName, MenuPrefix.Saas) },
|
||||
{ nameof(TableNameEnum.DbTableColumn), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.LogEntry), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.AiBot), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ChangeLog), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.GlobalSearch), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ContactTitle), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Currency), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.CountryGroup), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Country), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.City), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.District), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.SkillType), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Skill), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.SkillLevel), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.UomCategory), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Uom), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Branch), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BranchUsers), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.SettingDefinition), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Language), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.LanguageKey), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.LanguageText), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.DataSource), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ListForm), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ListFormField), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ListFormCustomization), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ListFormImport), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ListFormImportLog), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ListFormWorkflow), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Notification), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.NotificationRule), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.NotificationType), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_JobFlow), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_MailQueue), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_MailQueueEvents), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BackgroundWorker_MailQueueTableFormat), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ForumCategory), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ForumTopic), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.ForumPost), (TablePrefix.TenantByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Home), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.About), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Service), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Product), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.PaymentMethod), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.InstallmentOption), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Order), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.OrderItem), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.OrderItem_ByTenantId), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BlogCategory), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.BlogPost), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Demo), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Contact), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Route), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Module), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.Menu), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.CrudEndpoint), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.CustomEndpoint), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.CustomComponent), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.DynamicService), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
{ nameof(TableNameEnum.DevRequest), (TablePrefix.PlatformByName, MenuPrefix.Sas) },
|
||||
|
||||
// 🔹 ADMINISTRATION TABLOLARI
|
||||
{ nameof(TableNameEnum.Sector), (TablePrefix.TenantByName, MenuPrefix.Administration) },
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ public static class SeedConsts
|
|||
public const string Default = Prefix.App + ".Menus";
|
||||
|
||||
public const string Routes = Default + ".Routes";
|
||||
public const string MenuGroup = Default + ".MenuGroup";
|
||||
public const string Module = Default + ".Module";
|
||||
public const string Menu = Default + ".Menu";
|
||||
public const string Manager = Default + ".Manager";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public class Menu : Entity<Guid>
|
|||
public string ParentCode { get; set; }
|
||||
public string CssClass { get; set; }
|
||||
public string RequiredPermissionName { get; set; }
|
||||
public string ShortName { get; set; } // Örn: "HR", "INV", "CRM"
|
||||
public string ModuleId { get; set; } // Modul referansi (Module.Id)
|
||||
|
||||
public string Target { get; set; }
|
||||
public bool IsDisabled { get; set; }
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
namespace Sozsoft.Platform.Entities;
|
||||
|
||||
public class MenuGroup : Entity<string>
|
||||
public class Module : Entity<string>
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public MenuGroup(string id)
|
||||
public Module(string id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ public class Order : FullAuditedEntity<Guid>
|
|||
public string FaxNumber { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Website { get; set; }
|
||||
public string MenuGroup { get; set; }
|
||||
public string Modules { get; set; }
|
||||
|
||||
public bool IsExisting { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
|
|
|
|||
|
|
@ -8,41 +8,41 @@ namespace Sozsoft.Platform.Extensions;
|
|||
public static class AbpPermissionsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Menü gruplarını pipe karakteriyle ayrılmış string olarak kaydeder. (örnek: "Erp|Kurs")
|
||||
/// Yetkinin ait olduğu modülleri pipe karakteriyle ayrılmış string olarak kaydeder. (örnek: "Sas|Adm")
|
||||
/// </summary>
|
||||
public static void SetMenuGroup(this PermissionDefinitionRecord permission, string menuGroup)
|
||||
public static void SetModules(this PermissionDefinitionRecord permission, string modules)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(menuGroup))
|
||||
if (string.IsNullOrWhiteSpace(modules))
|
||||
{
|
||||
permission.SetProperty(PlatformConsts.Permissions.MenuGroup, null);
|
||||
permission.SetProperty(PlatformConsts.Permissions.Modules, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔹 Gereksiz boşlukları temizle
|
||||
var cleaned = string.Join(
|
||||
"|",
|
||||
menuGroup
|
||||
modules
|
||||
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Distinct()
|
||||
);
|
||||
|
||||
// 🔹 Veritabanına "Erp|Kurs" formatında kaydet
|
||||
permission.SetProperty(PlatformConsts.Permissions.MenuGroup, cleaned);
|
||||
// 🔹 Veritabanına "Sas|Adm" formatında kaydet
|
||||
permission.SetProperty(PlatformConsts.Permissions.Modules, cleaned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Menü gruplarını veritabanındaki pipe formatından string[] olarak döndürür. (örnek: "Erp|Kurs" → ["Erp", "Kurs"])
|
||||
/// Modülleri veritabanındaki pipe formatından string[] olarak döndürür. (örnek: "Sas|Adm" → ["Sas", "Adm"])
|
||||
/// </summary>
|
||||
public static string[] GetMenuGroup(this PermissionDefinitionRecord permission)
|
||||
public static string[] GetModules(this PermissionDefinitionRecord permission)
|
||||
{
|
||||
var value = permission.GetProperty<string>(PlatformConsts.Permissions.MenuGroup);
|
||||
var value = permission.GetProperty<string>(PlatformConsts.Permissions.Modules);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
// 🔹 "Erp|Kurs" -> ["Erp", "Kurs"]
|
||||
// 🔹 "Sas|Adm" -> ["Sas", "Adm"]
|
||||
return value
|
||||
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Distinct()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using Volo.Abp.Data;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.TenantManagement;
|
||||
|
||||
namespace Sozsoft.Platform.Extensions;
|
||||
|
|
@ -156,13 +158,51 @@ public static class AbpTenantExtensions
|
|||
return tenant.GetProperty<string>(PlatformConsts.Tenants.Website);
|
||||
}
|
||||
|
||||
public static void SetMenuGroup(this Tenant tenant, string menuGroup)
|
||||
/// <summary>
|
||||
/// Kiracinin gorebilecegi modulleri pipe ile ayrilmis tek string olarak kaydeder. (ornek: "Saas|Adm")
|
||||
/// </summary>
|
||||
public static void SetModules(this Tenant tenant, string modules)
|
||||
{
|
||||
tenant.SetProperty(PlatformConsts.Tenants.MenuGroup, menuGroup);
|
||||
if (string.IsNullOrWhiteSpace(modules))
|
||||
{
|
||||
tenant.SetProperty(PlatformConsts.Tenants.Modules, null);
|
||||
return;
|
||||
}
|
||||
|
||||
var cleaned = string.Join(
|
||||
PlatformConsts.MultiValueDelimiter,
|
||||
modules
|
||||
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Distinct()
|
||||
);
|
||||
|
||||
tenant.SetProperty(PlatformConsts.Tenants.Modules, cleaned);
|
||||
}
|
||||
public static string GetMenuGroup(this Tenant tenant)
|
||||
|
||||
/// <summary>
|
||||
/// Kiracinin modullerini pipe formatindan dizi olarak dondurur. ("Sas|Adm" -> ["Sas", "Adm"])
|
||||
/// </summary>
|
||||
public static string[] GetModules(this Tenant tenant)
|
||||
{
|
||||
return tenant.GetProperty<string>(PlatformConsts.Tenants.MenuGroup);
|
||||
var value = tenant.GetModulesRaw();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return value
|
||||
.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modul listesini veritabanindaki ham haliyle dondurur. (ornek: "Saas|Adm")
|
||||
/// </summary>
|
||||
public static string GetModulesRaw(this Tenant tenant)
|
||||
{
|
||||
return tenant.GetProperty<string>(PlatformConsts.Tenants.Modules);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,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<Module> Modules { get; set; }
|
||||
public DbSet<DataSource> DataSources { get; set; }
|
||||
public DbSet<ListForm> ListForms { get; set; }
|
||||
public DbSet<ListFormField> ListFormFields { get; set; }
|
||||
|
|
@ -294,11 +294,12 @@ public class PlatformDbContext :
|
|||
b.HasIndex(x => new { x.Path }).IsUnique().HasFilter("[IsDeleted] = 0");
|
||||
});
|
||||
|
||||
builder.Entity<MenuGroup>(b =>
|
||||
builder.Entity<Module>(b =>
|
||||
{
|
||||
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.MenuGroup)), Prefix.DbSchema);
|
||||
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.Module)), Prefix.DbSchema);
|
||||
b.ConfigureByConvention();
|
||||
|
||||
b.Property(a => a.Id).HasMaxLength(128);
|
||||
b.Property(a => a.Name).IsRequired().HasMaxLength(128);
|
||||
|
||||
b.HasIndex(x => new { x.Name }).IsUnique().HasFilter(null);
|
||||
|
|
@ -321,8 +322,16 @@ public class PlatformDbContext :
|
|||
b.Property(a => a.UserId).HasMaxLength(256);
|
||||
b.Property(a => a.RoleId).HasMaxLength(256);
|
||||
b.Property(a => a.CultureName).HasMaxLength(64);
|
||||
b.Property(a => a.ModuleId).HasMaxLength(128);
|
||||
|
||||
b.HasOne<Module>()
|
||||
.WithMany()
|
||||
.HasPrincipalKey(x => x.Id)
|
||||
.HasForeignKey(x => x.ModuleId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasIndex(x => new { x.Code }).IsUnique().HasFilter(null);
|
||||
b.HasIndex(x => new { x.ModuleId });
|
||||
});
|
||||
|
||||
builder.Entity<DataSource>(b =>
|
||||
|
|
@ -1066,7 +1075,7 @@ public class PlatformDbContext :
|
|||
b.Property(o => o.FaxNumber).HasMaxLength(20);
|
||||
b.Property(o => o.Email).HasMaxLength(128);
|
||||
b.Property(o => o.Website).HasMaxLength(128);
|
||||
b.Property(o => o.MenuGroup).HasMaxLength(64);
|
||||
b.Property(o => o.Modules).HasMaxLength(256);
|
||||
b.Property(o => o.BillingCycle).HasMaxLength(32);
|
||||
b.Property(o => o.Period).IsRequired().HasDefaultValue(1);
|
||||
|
||||
|
|
|
|||
|
|
@ -472,19 +472,19 @@ public static class PlatformEfCoreEntityExtensionMappings
|
|||
|
||||
ObjectExtensionManager.Instance
|
||||
.MapEfCoreProperty<Tenant, string>(
|
||||
PlatformConsts.Tenants.MenuGroup,
|
||||
PlatformConsts.Tenants.Modules,
|
||||
(entityBuilder, propertyBuilder) =>
|
||||
{
|
||||
propertyBuilder.HasMaxLength(64).HasDefaultValue(null);
|
||||
propertyBuilder.HasMaxLength(256).HasDefaultValue(null);
|
||||
}
|
||||
);
|
||||
|
||||
ObjectExtensionManager.Instance
|
||||
.MapEfCoreProperty<PermissionDefinitionRecord, string>(
|
||||
PlatformConsts.Permissions.MenuGroup,
|
||||
PlatformConsts.Permissions.Modules,
|
||||
(entityBuilder, propertyBuilder) =>
|
||||
{
|
||||
propertyBuilder.HasMaxLength(64).HasDefaultValue(null);
|
||||
propertyBuilder.HasMaxLength(256).HasDefaultValue(null);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
|||
namespace Sozsoft.Platform.Migrations
|
||||
{
|
||||
[DbContext(typeof(PlatformDbContext))]
|
||||
[Migration("20260828094327_Initial")]
|
||||
[Migration("20260831095952_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
|
@ -4056,6 +4056,10 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.Property<bool>("IsDisabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("ModuleId")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
|
|
@ -4071,9 +4075,6 @@ namespace Sozsoft.Platform.Migrations
|
|||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("ShortName")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Target")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
|
|
@ -4091,27 +4092,11 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.HasIndex("Code")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ModuleId");
|
||||
|
||||
b.ToTable("Sas_H_Menu", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.MenuGroup", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Sas_H_MenuGroup", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.MessengerConversation", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
|
@ -4266,6 +4251,25 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.ToTable("Adm_T_MessengerConversationMessage", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Module", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Sas_H_Module", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Note", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
|
@ -4447,14 +4451,14 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.Property<DateTime?>("LicenseStartTime")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("MenuGroup")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
|
||||
b.Property<string>("MobileNumber")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<string>("Modules")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("OrganizationName")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
|
@ -8490,9 +8494,9 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("MenuGroup")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
b.Property<string>("Modules")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<byte>("MultiTenancySide")
|
||||
.HasColumnType("tinyint");
|
||||
|
|
@ -8754,14 +8758,14 @@ namespace Sozsoft.Platform.Migrations
|
|||
.HasColumnType("uniqueidentifier")
|
||||
.HasColumnName("LastModifierId");
|
||||
|
||||
b.Property<string>("MenuGroup")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
|
||||
b.Property<string>("MobileNumber")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<string>("Modules")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
|
|
@ -9055,6 +9059,14 @@ namespace Sozsoft.Platform.Migrations
|
|||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Menu", b =>
|
||||
{
|
||||
b.HasOne("Sozsoft.Platform.Entities.Module", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ModuleId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.MessengerConversationMessage", b =>
|
||||
{
|
||||
b.HasOne("Sozsoft.Platform.Entities.MessengerConversation", "Conversation")
|
||||
|
|
@ -242,7 +242,7 @@ namespace Sozsoft.Platform.Migrations
|
|||
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
StateCheckers = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true)
|
||||
Modules = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
|
|
@ -368,8 +368,8 @@ namespace Sozsoft.Platform.Migrations
|
|||
FaxNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Founder = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
||||
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
MobileNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Modules = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||
OrganizationName = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
PhoneNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
PostalCode = table.Column<string>(type: "nvarchar(10)", maxLength: 10, nullable: true),
|
||||
|
|
@ -1570,41 +1570,15 @@ namespace Sozsoft.Platform.Migrations
|
|||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Sas_H_Menu",
|
||||
name: "Sas_H_Module",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Code = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||
DisplayName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||
Order = table.Column<int>(type: "int", nullable: false),
|
||||
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||
Icon = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
ParentCode = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
CssClass = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
RequiredPermissionName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
ShortName = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
Target = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
IsDisabled = table.Column<bool>(type: "bit", nullable: false),
|
||||
ElementId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
UserId = 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(64)", maxLength: 64, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
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),
|
||||
Id = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Sas_H_MenuGroup", x => x.Id);
|
||||
table.PrimaryKey("PK_Sas_H_Module", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
|
|
@ -1648,7 +1622,7 @@ namespace Sozsoft.Platform.Migrations
|
|||
FaxNumber = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||
Email = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
Website = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
MenuGroup = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
Modules = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||
IsExisting = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||
IsActive = table.Column<bool>(type: "bit", nullable: false, computedColumnSql: "CONVERT(bit, CASE WHEN [LicenseEndTime] IS NOT NULL AND CONVERT(date, GETDATE()) > CONVERT(date, [LicenseEndTime]) THEN 0 ELSE 1 END)", stored: false),
|
||||
BillingCycle = table.Column<string>(type: "nvarchar(32)", maxLength: 32, nullable: true),
|
||||
|
|
@ -2954,6 +2928,38 @@ namespace Sozsoft.Platform.Migrations
|
|||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Sas_H_Menu",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Code = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||
DisplayName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
||||
Order = table.Column<int>(type: "int", nullable: false),
|
||||
Url = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
||||
Icon = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
ParentCode = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
CssClass = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
RequiredPermissionName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
ModuleId = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||
Target = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
IsDisabled = table.Column<bool>(type: "bit", nullable: false),
|
||||
ElementId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
|
||||
UserId = 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(64)", maxLength: 64, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Sas_H_Menu", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Sas_H_Menu_Sas_H_Module_ModuleId",
|
||||
column: x => x.ModuleId,
|
||||
principalTable: "Sas_H_Module",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Sas_H_NotificationRule",
|
||||
columns: table => new
|
||||
|
|
@ -4229,8 +4235,13 @@ namespace Sozsoft.Platform.Migrations
|
|||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Sas_H_MenuGroup_Name",
|
||||
table: "Sas_H_MenuGroup",
|
||||
name: "IX_Sas_H_Menu_ModuleId",
|
||||
table: "Sas_H_Menu",
|
||||
column: "ModuleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Sas_H_Module_Name",
|
||||
table: "Sas_H_Module",
|
||||
column: "Name",
|
||||
unique: true);
|
||||
|
||||
|
|
@ -4596,9 +4607,6 @@ namespace Sozsoft.Platform.Migrations
|
|||
migrationBuilder.DropTable(
|
||||
name: "Sas_H_Menu");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Sas_H_MenuGroup");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Sas_H_Notification");
|
||||
|
||||
|
|
@ -4704,6 +4712,9 @@ namespace Sozsoft.Platform.Migrations
|
|||
migrationBuilder.DropTable(
|
||||
name: "Sas_H_ListFormImport");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Sas_H_Module");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Sas_H_NotificationRule");
|
||||
|
||||
|
|
@ -4053,6 +4053,10 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.Property<bool>("IsDisabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("ModuleId")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.Property<int>("Order")
|
||||
.HasColumnType("int");
|
||||
|
||||
|
|
@ -4068,9 +4072,6 @@ namespace Sozsoft.Platform.Migrations
|
|||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("ShortName")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Target")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
|
|
@ -4088,27 +4089,11 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.HasIndex("Code")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ModuleId");
|
||||
|
||||
b.ToTable("Sas_H_Menu", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.MenuGroup", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("nvarchar(450)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Sas_H_MenuGroup", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.MessengerConversation", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
|
@ -4263,6 +4248,25 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.ToTable("Adm_T_MessengerConversationMessage", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Module", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Name")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Sas_H_Module", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Note", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
|
@ -4444,14 +4448,14 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.Property<DateTime?>("LicenseStartTime")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("MenuGroup")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
|
||||
b.Property<string>("MobileNumber")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<string>("Modules")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("OrganizationName")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("nvarchar(128)");
|
||||
|
|
@ -8487,9 +8491,9 @@ namespace Sozsoft.Platform.Migrations
|
|||
b.Property<bool>("IsEnabled")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("MenuGroup")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
b.Property<string>("Modules")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<byte>("MultiTenancySide")
|
||||
.HasColumnType("tinyint");
|
||||
|
|
@ -8751,14 +8755,14 @@ namespace Sozsoft.Platform.Migrations
|
|||
.HasColumnType("uniqueidentifier")
|
||||
.HasColumnName("LastModifierId");
|
||||
|
||||
b.Property<string>("MenuGroup")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("nvarchar(64)");
|
||||
|
||||
b.Property<string>("MobileNumber")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<string>("Modules")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("nvarchar(256)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
|
|
@ -9052,6 +9056,14 @@ namespace Sozsoft.Platform.Migrations
|
|||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.Menu", b =>
|
||||
{
|
||||
b.HasOne("Sozsoft.Platform.Entities.Module", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ModuleId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Sozsoft.Platform.Entities.MessengerConversationMessage", b =>
|
||||
{
|
||||
b.HasOne("Sozsoft.Platform.Entities.MessengerConversation", "Conversation")
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
`crud/{Entity}.json`.
|
||||
- **Wizard dosyası** → tek başına taşınmaz; export zip'i `wizard/`, `custom/`, `crud/` ve
|
||||
`{sql|postgres}/{object|execute}/` bağımlılıklarını da içerir.
|
||||
- **`MenusData.json`** → `Routes` bölümüne dokunma; yalnızca `MenuGroups` ve `Menus`.
|
||||
- **`MenusData.json`** → `Routes` bölümüne dokunma; yalnızca `Modules` ve `Menus`.
|
||||
|
||||
### Definition of done
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@
|
|||
"PermissionGroupName": "App.Wizard.Sample",
|
||||
"PermissionGroupDisplayNameEn": "Sample",
|
||||
"PermissionGroupDisplayNameTr": "Sample",
|
||||
"MenuParentModuleId": "Sam",
|
||||
"MenuParentCode": "App.Wizard.Sample",
|
||||
"MenuParentShortName": "Sam",
|
||||
"MenuParentIcon": "FcBookmark",
|
||||
"MenuIcon": "FcBiohazard",
|
||||
"DataSourceCode": "Default",
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
address2: tenant.data.address2,
|
||||
email: tenant.data.email,
|
||||
website: tenant.data.website,
|
||||
menuGroup: tenant.data.menuGroup,
|
||||
modules: tenant.data.modules,
|
||||
}))
|
||||
|
||||
if (tenant.data.name) setFoundTenantName(tenant.data.name)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ const TenantSelector = () => {
|
|||
setTenant({
|
||||
tenantId: response.data.id,
|
||||
tenantName: response.data.name,
|
||||
menuGroup: response.data.menuGroup,
|
||||
modules: response.data.modules,
|
||||
})
|
||||
} else {
|
||||
setTenant(undefined)
|
||||
|
|
|
|||
|
|
@ -43,3 +43,16 @@ export const COMPONENT_PERMISSION = {
|
|||
UPDATE: 'App.DeveloperKit.Components.Update',
|
||||
DELETE: 'App.DeveloperKit.Components.Delete',
|
||||
} as const
|
||||
|
||||
/**
|
||||
* ListForm alan (Fields) yoneticisi yetkileri. `PermissionsData.json` icinde tanimlidir ve
|
||||
* seeder ile yonetilir; buradaki kontroller yalnizca butonlari kapatir, asil kontrol
|
||||
* `ListFormFieldsAppService` uzerindeki ABP policy adlarindadir.
|
||||
*/
|
||||
export const LISTFORM_FIELD_PERMISSION = {
|
||||
/** Alan listesini gorme (okuma) yetkisi; alt yetkilerin tamaminin ustudur. */
|
||||
DEFAULT: 'App.Listforms.ListformField',
|
||||
CREATE: 'App.Listforms.ListformField.Create',
|
||||
UPDATE: 'App.Listforms.ListformField.Update',
|
||||
DELETE: 'App.Listforms.ListformField.Delete',
|
||||
} as const
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export interface ListFormWizardDto {
|
|||
/** Izin grubunun Turkce gorunen adi. */
|
||||
permissionGroupDisplayNameTr: string
|
||||
menuParentCode: string
|
||||
menuParentShortName?: string
|
||||
menuParentModuleId?: string
|
||||
menuParentIcon?: string
|
||||
menuIcon: string
|
||||
dataSourceCode: string
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export interface CustomTenantDto extends TenantDto {
|
|||
faxNumber: string
|
||||
email: string
|
||||
website: string
|
||||
menuGroup?: string
|
||||
modules?: string
|
||||
reference?: string
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export interface MenuDto extends FullAuditedEntityDto<string> {
|
|||
userId?: string
|
||||
roleId?: string
|
||||
cultureName?: string
|
||||
shortName?: string
|
||||
moduleId?: string
|
||||
menuTextTr?: string
|
||||
menuTextEn?: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ export interface NavigationTree {
|
|||
type: 'title' | 'collapse' | 'item'
|
||||
authority: string[]
|
||||
subMenu: NavigationTree[]
|
||||
shortName?: string
|
||||
moduleId?: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { PagedAndSortedResultRequestDto, PagedResultDto } from '@/proxy/abp'
|
|||
import { MenuDto } from '@/proxy/menus/models'
|
||||
import apiService from '@/services/api.service'
|
||||
|
||||
export type MenuGroupLookupDto = {
|
||||
export type ModuleLookupDto = {
|
||||
key: string
|
||||
name: string
|
||||
group?: string
|
||||
|
|
@ -103,11 +103,11 @@ export class MenuService {
|
|||
{ apiName: this.apiName },
|
||||
)
|
||||
|
||||
getMenuGroups = () =>
|
||||
apiService.fetchData<MenuGroupLookupDto[]>(
|
||||
getModules = () =>
|
||||
apiService.fetchData<ModuleLookupDto[]>(
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/app/menu/menu-groups',
|
||||
url: '/api/app/menu/modules',
|
||||
},
|
||||
{ apiName: this.apiName },
|
||||
)
|
||||
|
|
@ -123,8 +123,8 @@ export const getMenus = async (skipCount = 0, maxResultCount = 1000, sorting = '
|
|||
})
|
||||
}
|
||||
|
||||
export const getMenuGroups = async () => {
|
||||
export const getModules = async () => {
|
||||
const menuService = new MenuService()
|
||||
|
||||
return await menuService.getMenuGroups()
|
||||
return await menuService.getModules()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import apiService from './api.service'
|
|||
export type CreateTenantFromOrderInput = {
|
||||
orderId: string
|
||||
name: string
|
||||
menuGroup: string
|
||||
modules: string
|
||||
}
|
||||
|
||||
export const getTenants = (skipCount = 0, maxResultCount = 10) =>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export interface AuthStoreModel {
|
|||
tenant?: {
|
||||
tenantId?: string
|
||||
tenantName?: string
|
||||
menuGroup?: string
|
||||
modules?: string
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ export const initialState: AuthStoreModel = {
|
|||
tenant: {
|
||||
tenantId: '',
|
||||
tenantName: '',
|
||||
menuGroup: '',
|
||||
modules: '',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ export const authModel: AuthModel = {
|
|||
setTenant: action((state, payload) => {
|
||||
state.tenantId = payload?.tenantId
|
||||
state.tenantName = payload?.tenantName
|
||||
state.menuGroup = payload?.menuGroup
|
||||
state.modules = payload?.modules
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
export default function acronym(name = '') {
|
||||
const shortName = name.match(/\b(\w)/g)
|
||||
const moduleId = name.match(/\b(\w)/g)
|
||||
|
||||
if (shortName) {
|
||||
return shortName.join('')
|
||||
if (moduleId) {
|
||||
return moduleId.join('')
|
||||
}
|
||||
|
||||
return name
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export default function getChildren(menu: MenuDto[], parentCode: string | null):
|
|||
translateKey: child.displayName ?? '',
|
||||
authority: [child.requiredPermissionName ?? ''],
|
||||
subMenu: [],
|
||||
shortName: child.shortName ?? '',
|
||||
moduleId: child.moduleId ?? '',
|
||||
}
|
||||
|
||||
if (child.code) {
|
||||
|
|
|
|||
|
|
@ -45,13 +45,9 @@ function FormFieldEdit({
|
|||
<TabNav value="options">{translate('::App.Listform.ListformField.Options')}</TabNav>
|
||||
<TabNav value="permissions">{translate('::Abp.Identity.Permissions')}</TabNav>
|
||||
<TabNav value="lookup">{translate('::App.ListFormFieldEdit.TabLookup')}</TabNav>
|
||||
<TabNav value="customization">
|
||||
{translate('::App.ListFormEdit.TabCustomization')}
|
||||
</TabNav>
|
||||
<TabNav value="customization">{translate('::App.ListFormEdit.TabCustomization')}</TabNav>
|
||||
<TabNav value="filtering">{translate('::App.ListFormEdit.TabFiltering')}</TabNav>
|
||||
<TabNav value="headering">
|
||||
{translate('::App.ListFormFieldEdit.TabHeadering')}
|
||||
</TabNav>
|
||||
<TabNav value="headering">{translate('::App.ListFormFieldEdit.TabHeadering')}</TabNav>
|
||||
<TabNav value="grouping">{translate('::App.ListFormEdit.TabGrouping')}</TabNav>
|
||||
<TabNav value="groupSummary">
|
||||
{translate('::App.ListFormFieldEdit.TabGroupSummary')}
|
||||
|
|
@ -59,9 +55,7 @@ function FormFieldEdit({
|
|||
<TabNav value="totalSummary">
|
||||
{translate('::App.ListFormFieldEdit.TabTotalSummary')}
|
||||
</TabNav>
|
||||
<TabNav value="joinOptions">
|
||||
{translate('::App.ListFormFieldEdit.TabJoinOptions')}
|
||||
</TabNav>
|
||||
<TabNav value="joinOptions">{translate('::App.ListFormFieldEdit.TabJoinOptions')}</TabNav>
|
||||
<TabNav value="cssOptions">
|
||||
{translate('::App.ListFormField.CopyFieldsCssOptions')}
|
||||
</TabNav>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import {
|
|||
ColumnValidationComparisonTypeEnum,
|
||||
} from '@/proxy/form/models'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const NewItem: ColumnStylingDto = {
|
||||
rowType: ColumnRowTypeListOptions.Data,
|
||||
|
|
@ -52,6 +53,7 @@ function FormFieldTabConditionalFormatting({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [itemIndex, setItemIndex] = useState(-2)
|
||||
|
|
@ -87,6 +89,7 @@ function FormFieldTabConditionalFormatting({
|
|||
type="button"
|
||||
size="sm"
|
||||
title="Add"
|
||||
disabled={!canUpdate}
|
||||
icon={<FaPlusSquare />}
|
||||
onClick={() => setItemIndex(-1)}
|
||||
/>
|
||||
|
|
@ -121,6 +124,7 @@ function FormFieldTabConditionalFormatting({
|
|||
type="button"
|
||||
size="sm"
|
||||
title="Delete"
|
||||
disabled={!canUpdate}
|
||||
icon={<FaTrashAlt />}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
|
|
@ -298,8 +302,17 @@ function FormFieldTabConditionalFormatting({
|
|||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" variant="solid" loading={isLoading} type="submit">
|
||||
{isLoading ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
variant="solid"
|
||||
loading={isLoading}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isLoading
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
|||
import { Field, Form, Formik } from 'formik'
|
||||
import { object, string } from 'yup'
|
||||
import { FormFieldEditProps } from './FormFields'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
columnCssClass: string(),
|
||||
|
|
@ -18,6 +19,7 @@ function FormFieldTabCssOptions({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
|
|
@ -61,8 +63,18 @@ function FormFieldTabCssOptions({
|
|||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { fixedPositionOptions } from '../options'
|
|||
import { FormFieldEditProps } from './FormFields'
|
||||
import { FixedPositionEnum } from '@/proxy/form/models'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
columnCustomizationDto: object()
|
||||
|
|
@ -26,6 +27,7 @@ function FormFieldTabCustomization({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
|
|
@ -43,22 +45,28 @@ function FormFieldTabCustomization({
|
|||
<FormItem label={translate('::App.Listform.ListformField.IsFixed')}>
|
||||
<Field name="columnCustomizationDto.fixed" component={Checkbox} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={translate('::App.ListFormFieldEdit.CustomizationAllowReordering')}
|
||||
>
|
||||
<FormItem label={translate('::App.ListFormFieldEdit.CustomizationAllowReordering')}>
|
||||
<Field name="columnCustomizationDto.allowReordering" component={Checkbox} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={translate('::App.ListFormFieldEdit.CustomizationFixedPosition')}
|
||||
>
|
||||
<FormItem label={translate('::App.ListFormFieldEdit.CustomizationFixedPosition')}>
|
||||
<SelectField
|
||||
name="columnCustomizationDto.fixedPosition"
|
||||
options={fixedPositionOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { isValidJsonText } from '../json-row-operations/editor-options/jsonUtils
|
|||
import { FormFieldEditProps } from './FormFields'
|
||||
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
fieldName: string().required().max(100),
|
||||
|
|
@ -42,6 +43,7 @@ function FormFieldTabDetails({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
const [isEditorOptionsDialogOpen, setIsEditorOptionsDialogOpen] = useState(false)
|
||||
|
||||
return (
|
||||
|
|
@ -171,6 +173,7 @@ function FormFieldTabDetails({
|
|||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
|||
import { Field, Form, Formik } from 'formik'
|
||||
import { bool, object, string } from 'yup'
|
||||
import { FormFieldEditProps } from './FormFields'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
columnFilterDto: object()
|
||||
|
|
@ -23,6 +24,7 @@ function FormFieldTabFiltering({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
|
|
@ -82,8 +84,18 @@ function FormFieldTabFiltering({
|
|||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
|||
import { Field, Form, Formik } from 'formik'
|
||||
import { bool, number, object } from 'yup'
|
||||
import { FormFieldEditProps } from './FormFields'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
columnGroupingDto: object()
|
||||
|
|
@ -23,6 +24,7 @@ function FormFieldTabGrouping({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
|
|
@ -59,8 +61,18 @@ function FormFieldTabGrouping({
|
|||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
|
|||
import { Field, Form, Formik } from 'formik'
|
||||
import { bool, object, string } from 'yup'
|
||||
import { FormFieldEditProps } from './FormFields'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
columnHeaderDto: object()
|
||||
|
|
@ -23,6 +24,7 @@ function FormFieldTabHeadering({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Container className="grid xl:grid-cols-2">
|
||||
|
|
@ -37,9 +39,7 @@ function FormFieldTabHeadering({
|
|||
{({ touched, errors, isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem
|
||||
label={translate('::App.ListFormFieldEdit.HeaderingAllowHeaderFiltering')}
|
||||
>
|
||||
<FormItem label={translate('::App.ListFormFieldEdit.HeaderingAllowHeaderFiltering')}>
|
||||
<Field name="columnHeaderDto.allowHeaderFiltering" component={Checkbox} />
|
||||
</FormItem>
|
||||
|
||||
|
|
@ -63,8 +63,18 @@ function FormFieldTabHeadering({
|
|||
/>
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { object, string } from 'yup'
|
|||
import { gridColumnJoinConditionOptions, gridColumnJoinTypeListOptions } from '../options'
|
||||
import { FormFieldEditProps } from './FormFields'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
columnJoinTableDto: object()
|
||||
|
|
@ -35,6 +36,7 @@ function FormFieldTabJoinOptions({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Formik
|
||||
|
|
@ -124,9 +126,7 @@ function FormFieldTabJoinOptions({
|
|||
type="text"
|
||||
autoComplete="off"
|
||||
name="columnJoinTableDto.selectFieldName"
|
||||
placeholder={translate(
|
||||
'::App.ListFormFieldEdit.JoinOptionsSelectFieldName',
|
||||
)}
|
||||
placeholder={translate('::App.ListFormFieldEdit.JoinOptionsSelectFieldName')}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
|
@ -202,7 +202,15 @@ function FormFieldTabJoinOptions({
|
|||
</FormItem>
|
||||
</Card>
|
||||
</div>
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { FormFieldEditProps } from './FormFields'
|
|||
import { ColumnCascadeFilterOperatorEnum, UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
|
||||
import { buildLookupQuery } from '../../lookupQuery'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
lookupDto: object()
|
||||
|
|
@ -254,6 +255,7 @@ function FormFieldTabLookup({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
const listFormValues = useStoreState((s) => s.admin.lists.values)
|
||||
const dsCode = listFormValues?.dataSourceCode ?? ''
|
||||
const [dbObjects, setDbObjects] = useState<SqlObjectExplorerDto | null>(null)
|
||||
|
|
@ -377,9 +379,7 @@ function FormFieldTabLookup({
|
|||
type="text"
|
||||
autoComplete="off"
|
||||
name="lookupDto.cascadeRelationField"
|
||||
placeholder={translate(
|
||||
'::App.ListFormFieldEdit.LookupCascadeRelationField',
|
||||
)}
|
||||
placeholder={translate('::App.ListFormFieldEdit.LookupCascadeRelationField')}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
|
@ -438,6 +438,7 @@ function FormFieldTabLookup({
|
|||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { FaCode } from 'react-icons/fa'
|
|||
import { useState } from 'react'
|
||||
import EditorScriptBuilderDialog from '../json-row-operations/EditorScriptBuilderDialog'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
listOrderNo: number(),
|
||||
|
|
@ -36,6 +37,7 @@ function FormFieldTabOptions({
|
|||
fields: ColumnFormatEditDto[]
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
const [isEditorScriptDialogOpen, setIsEditorScriptDialogOpen] = useState(false)
|
||||
const editingFormGroupOptions: SelectBoxOption[] = [...editingFormGroups]
|
||||
.sort((left, right) => left.order - right.order)
|
||||
|
|
@ -82,10 +84,7 @@ function FormFieldTabOptions({
|
|||
invalid={errors.sortDirection && touched.sortDirection}
|
||||
errorMessage={errors.sortDirection}
|
||||
>
|
||||
<SelectField
|
||||
name="sortDirection"
|
||||
options={sortDirectionOptions}
|
||||
/>
|
||||
<SelectField name="sortDirection" options={sortDirectionOptions} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={translate('::App.ListFormFieldEdit.OptionsSortIndex')}
|
||||
|
|
@ -195,6 +194,7 @@ function FormFieldTabOptions({
|
|||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { bool, object, string } from 'yup'
|
|||
import { FormFieldEditProps } from './FormFields'
|
||||
import { getPermissions } from '@/services/identity.service'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
permissionDto: object().shape({
|
||||
|
|
@ -28,6 +29,7 @@ function FormFieldTabPermissions({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
const [permissionOptions, setPermissionOptions] = useState<SelectBoxOption[]>([])
|
||||
|
||||
const fetchPermissions = async () => {
|
||||
|
|
@ -73,10 +75,7 @@ function FormFieldTabPermissions({
|
|||
invalid={errors.permissionDto?.r && touched.permissionDto?.r}
|
||||
errorMessage={errors.permissionDto?.r}
|
||||
>
|
||||
<SelectField
|
||||
name="permissionDto.r"
|
||||
options={permissionOptions}
|
||||
/>
|
||||
<SelectField name="permissionDto.r" options={permissionOptions} />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={translate('::App.Platform.Create')}
|
||||
|
|
@ -143,8 +142,18 @@ function FormFieldTabPermissions({
|
|||
<Field name="permissionDto.i" component={Checkbox} />
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from '../options'
|
||||
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const schema = object().shape({
|
||||
pivotSettingsDto: object().shape({
|
||||
|
|
@ -35,6 +36,7 @@ function FormFieldTabPivotSetting({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
return (
|
||||
<Formik
|
||||
|
|
@ -62,10 +64,7 @@ function FormFieldTabPivotSetting({
|
|||
invalid={errors.pivotSettingsDto?.area && touched.pivotSettingsDto?.area}
|
||||
errorMessage={errors.pivotSettingsDto?.area}
|
||||
>
|
||||
<SelectField
|
||||
name="pivotSettingsDto.area"
|
||||
options={pivotSettingsAreaOptions}
|
||||
/>
|
||||
<SelectField name="pivotSettingsDto.area" options={pivotSettingsAreaOptions} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
|
|
@ -73,10 +72,7 @@ function FormFieldTabPivotSetting({
|
|||
invalid={errors.pivotSettingsDto?.format && touched.pivotSettingsDto?.format}
|
||||
errorMessage={errors.pivotSettingsDto?.format}
|
||||
>
|
||||
<SelectField
|
||||
name="pivotSettingsDto.format"
|
||||
options={tooltipFormatListOptions}
|
||||
/>
|
||||
<SelectField name="pivotSettingsDto.format" options={tooltipFormatListOptions} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem
|
||||
|
|
@ -138,7 +134,15 @@ function FormFieldTabPivotSetting({
|
|||
</FormItem>
|
||||
</Card>
|
||||
</div>
|
||||
<Button block size="sm" className="mt-1" variant="solid" loading={isSubmitting} type="submit">
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
className="mt-1"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { FormFieldEditProps } from './FormFields'
|
|||
import { tooltipFormatListOptions } from '@/proxy/admin/list-form/options'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
/**
|
||||
* Grup özeti ve genel toplam sekmelerinin ortak gövdesi.
|
||||
|
|
@ -44,6 +45,7 @@ function FormFieldTabSummary({
|
|||
editTab: string
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
const fieldList: SelectBoxOption[] = fields.map((field) => ({
|
||||
value: field.fieldName,
|
||||
|
|
@ -64,51 +66,54 @@ function FormFieldTabSummary({
|
|||
}}
|
||||
>
|
||||
{({ isSubmitting }) => (
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem label={label('SummaryType')}>
|
||||
<SelectField
|
||||
name={`${dtoKey}.summaryType`}
|
||||
options={columnSummaryTypeListOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
<Form>
|
||||
<FormContainer size="sm">
|
||||
<FormItem label={label('SummaryType')}>
|
||||
<SelectField
|
||||
name={`${dtoKey}.summaryType`}
|
||||
options={columnSummaryTypeListOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label={label('GroupingSummaryValueFormat')}>
|
||||
<SelectField
|
||||
name={`${dtoKey}.valueFormat`}
|
||||
options={tooltipFormatListOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label={label('GroupingSummaryValueFormat')}>
|
||||
<SelectField name={`${dtoKey}.valueFormat`} options={tooltipFormatListOptions} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem label={label('GroupingSummaryDisplayFormat')}>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name={`${dtoKey}.displayFormat`}
|
||||
placeholder={label('GroupingSummaryDisplayFormat')}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label={label('GroupingSummaryDisplayFormat')}>
|
||||
<Field
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
name={`${dtoKey}.displayFormat`}
|
||||
placeholder={label('GroupingSummaryDisplayFormat')}
|
||||
component={Input}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem label={label('GroupingSummaryShowInColumn')}>
|
||||
<SelectField
|
||||
name={`${dtoKey}.showInColumn`}
|
||||
options={fieldList}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label={label('GroupingSummaryShowInColumn')}>
|
||||
<SelectField name={`${dtoKey}.showInColumn`} options={fieldList} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem label={label('GroupingSummaryShowInGroupFooter')}>
|
||||
<Field name={`${dtoKey}.showInGroupFooter`} component={Checkbox} />
|
||||
</FormItem>
|
||||
<FormItem label={label('GroupingSummaryShowInGroupFooter')}>
|
||||
<Field name={`${dtoKey}.showInGroupFooter`} component={Checkbox} />
|
||||
</FormItem>
|
||||
|
||||
<FormItem label={label('GroupingSummaryAlignByColumn')}>
|
||||
<Field name={`${dtoKey}.alignByColumn`} component={Checkbox} />
|
||||
</FormItem>
|
||||
<FormItem label={label('GroupingSummaryAlignByColumn')}>
|
||||
<Field name={`${dtoKey}.alignByColumn`} component={Checkbox} />
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import {
|
|||
ValidationRuleDto,
|
||||
} from '@/proxy/form/models'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
const NewItem: ValidationRuleDto = {
|
||||
type: ColumnValidationTypeListEnum.None,
|
||||
|
|
@ -66,6 +67,7 @@ function FormFieldTabValidationRules({
|
|||
initialValues: ColumnFormatEditDto
|
||||
} & FormFieldEditProps) {
|
||||
const { translate } = useLocalization()
|
||||
const { canUpdate } = useFieldPermission()
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [itemIndex, setItemIndex] = useState(-2)
|
||||
|
|
@ -101,6 +103,7 @@ function FormFieldTabValidationRules({
|
|||
type="button"
|
||||
size="sm"
|
||||
title="Add"
|
||||
disabled={!canUpdate}
|
||||
icon={<FaPlusSquare />}
|
||||
onClick={() => setItemIndex(-1)}
|
||||
/>
|
||||
|
|
@ -137,6 +140,7 @@ function FormFieldTabValidationRules({
|
|||
type="button"
|
||||
size="sm"
|
||||
title="Delete"
|
||||
disabled={!canUpdate}
|
||||
icon={<FaTrashAlt />}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
|
|
@ -332,8 +336,11 @@ function FormFieldTabValidationRules({
|
|||
variant="solid"
|
||||
loading={isLoading}
|
||||
type="submit"
|
||||
disabled={!canUpdate}
|
||||
>
|
||||
{isLoading ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
{isLoading
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
|||
import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models'
|
||||
import type { EditingFormDto } from '@/proxy/form/models'
|
||||
import SelectField from '../shared/SelectField'
|
||||
import { useFieldPermission } from './useFieldPermission'
|
||||
|
||||
export interface FormFieldEditProps {
|
||||
onSubmit: (
|
||||
|
|
@ -86,6 +87,7 @@ function FormFields({
|
|||
columns: DatabaseColumnDto[]
|
||||
}) {
|
||||
const { translate } = useLocalization()
|
||||
const { canCreate, canDelete } = useFieldPermission()
|
||||
const [fields, setFields] = useState<ColumnFormatEditDto[]>()
|
||||
const [deleteRowId, setDeleteRowId] = useState<string | null>(null)
|
||||
const [row, setRow] = useState<ColumnFormatEditDto | null>(null)
|
||||
|
|
@ -389,31 +391,35 @@ function FormFields({
|
|||
<Tr>
|
||||
<Th className="w-3/12">
|
||||
<div>
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Add"
|
||||
icon={<FaFileMedical />}
|
||||
onClick={() => {
|
||||
setIsNewField(true)
|
||||
setRow({} as ColumnFormatEditDto)
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Copy"
|
||||
icon={<FaCopy />}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
setIsCopyField(true)
|
||||
}}
|
||||
/>
|
||||
{allDbColumns.length > 0 && (
|
||||
{canCreate && (
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Add"
|
||||
icon={<FaFileMedical />}
|
||||
onClick={() => {
|
||||
setIsNewField(true)
|
||||
setRow({} as ColumnFormatEditDto)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{canCreate && (
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Copy"
|
||||
icon={<FaCopy />}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
setIsCopyField(true)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{canCreate && allDbColumns.length > 0 && (
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
|
|
@ -445,21 +451,23 @@ function FormFields({
|
|||
setRow(field)
|
||||
}}
|
||||
>
|
||||
<Td className="flex items-center !p-0">
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Delete"
|
||||
icon={<FaMinus />}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
if (field.id) {
|
||||
setDeleteRowId(field.id)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Td className="flex items-center !py-1 !px-1">
|
||||
{canDelete && (
|
||||
<Button
|
||||
shape="circle"
|
||||
variant="plain"
|
||||
type="button"
|
||||
size="sm"
|
||||
title="Delete"
|
||||
icon={<FaMinus />}
|
||||
onClick={async (e) => {
|
||||
e.preventDefault()
|
||||
if (field.id) {
|
||||
setDeleteRowId(field.id)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<span style={{ visibility: !field?.visible ? 'visible' : 'hidden' }}>
|
||||
<FaEyeSlash />
|
||||
</span>
|
||||
|
|
@ -471,8 +479,8 @@ function FormFields({
|
|||
{field.editOrderNo ? ` (${field.editOrderNo})` : ''}
|
||||
</span>
|
||||
</Td>
|
||||
<Td className="!p-0">{field.fieldName}</Td>
|
||||
<Td className="align-middle text-center !p-0">
|
||||
<Td className="!py-1 !px-1">{field.fieldName}</Td>
|
||||
<Td className="align-middle text-center !py-1 !px-1">
|
||||
<Avatar
|
||||
size={18}
|
||||
shape="circle"
|
||||
|
|
@ -480,11 +488,11 @@ function FormFields({
|
|||
title={field.cultureName}
|
||||
/>
|
||||
</Td>
|
||||
<Td className="hidden sm:table-cell !p-0">
|
||||
<Td className="hidden sm:table-cell !py-1 !px-1">
|
||||
{field.roleId &&
|
||||
(roleList.find((a) => a.value === field.roleId)?.label ?? 'X')}
|
||||
</Td>
|
||||
<Td className="hidden sm:table-cell !p-0">
|
||||
<Td className="hidden sm:table-cell !py-1 !px-1">
|
||||
{field.userId &&
|
||||
(userList.find((a) => a.value === field.userId)?.label ?? 'X')}
|
||||
</Td>
|
||||
|
|
@ -610,8 +618,17 @@ function FormFields({
|
|||
<SelectField name="userId" options={userList} />
|
||||
</FormItem>
|
||||
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canCreate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
@ -638,6 +655,7 @@ function FormFields({
|
|||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!canDelete}
|
||||
variant="solid"
|
||||
onClick={async () => {
|
||||
if (!deleteRowId) {
|
||||
|
|
@ -784,10 +802,7 @@ function FormFields({
|
|||
<FormItem label={translate('::App.Platform.Search3')} labelClass="justify-center">
|
||||
<Field name="copiedFields.all" component={Checkbox} className="mr-1" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
label={translate('::App.Platform.Detail')}
|
||||
labelClass="justify-center"
|
||||
>
|
||||
<FormItem label={translate('::App.Platform.Detail')} labelClass="justify-center">
|
||||
<Field name="copiedFields.details" component={Checkbox} className="mr-1" />
|
||||
</FormItem>
|
||||
<FormItem
|
||||
|
|
@ -883,8 +898,17 @@ function FormFields({
|
|||
<Field name="copiedFields.pivotSetting" component={Checkbox} className="mr-1" />
|
||||
</FormItem>
|
||||
</div>
|
||||
<Button block size="sm" variant="solid" loading={isSubmitting} type="submit">
|
||||
{isSubmitting ? translate('::App.Platform.Saving') : translate('::App.Platform.Save')}
|
||||
<Button
|
||||
block
|
||||
size="sm"
|
||||
variant="solid"
|
||||
loading={isSubmitting}
|
||||
type="submit"
|
||||
disabled={!canCreate}
|
||||
>
|
||||
{isSubmitting
|
||||
? translate('::App.Platform.Saving')
|
||||
: translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</FormContainer>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
import { LISTFORM_FIELD_PERMISSION } from '@/constants/permission.constant'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
|
||||
/**
|
||||
* Fields ekranindaki butonlarin yetki sozlesmesi. Sunucu tarafinda ayni kodlar
|
||||
* `ListFormFieldsAppService` policy adlari olarak zorunlu tutulur; burasi yalnizca
|
||||
* kullaniciya calismayacak bir buton gostermemek icindir.
|
||||
*/
|
||||
export const useFieldPermission = () => {
|
||||
const { checkPermission } = usePermission()
|
||||
|
||||
return {
|
||||
canCreate: checkPermission(LISTFORM_FIELD_PERMISSION.CREATE),
|
||||
canUpdate: checkPermission(LISTFORM_FIELD_PERMISSION.UPDATE),
|
||||
canDelete: checkPermission(LISTFORM_FIELD_PERMISSION.DELETE),
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ const initialValues: ListFormWizardDto = {
|
|||
permissionGroupDisplayNameEn: '',
|
||||
permissionGroupDisplayNameTr: '',
|
||||
menuParentCode: '',
|
||||
menuParentShortName: '',
|
||||
menuParentModuleId: '',
|
||||
menuParentIcon: '',
|
||||
menuIcon: '',
|
||||
dataSourceCode: '',
|
||||
|
|
@ -735,7 +735,7 @@ const Wizard = () => {
|
|||
permissionGroupDisplayNameEn: w.permissionGroupDisplayNameEn ?? '',
|
||||
permissionGroupDisplayNameTr: w.permissionGroupDisplayNameTr ?? '',
|
||||
menuParentCode: w.menuParentCode ?? '',
|
||||
menuParentShortName: w.menuParentShortName ?? '',
|
||||
menuParentModuleId: w.menuParentModuleId ?? '',
|
||||
menuParentIcon: w.menuParentIcon ?? '',
|
||||
menuIcon: w.menuIcon ?? '',
|
||||
dataSourceCode: w.dataSourceCode ?? '',
|
||||
|
|
@ -941,7 +941,7 @@ const Wizard = () => {
|
|||
group === findRootCode(rawMenuItems, parentCode).toLowerCase())
|
||||
|
||||
formik?.setFieldValue('menuParentCode', '')
|
||||
formik?.setFieldValue('menuParentShortName', '')
|
||||
formik?.setFieldValue('menuParentModuleId', '')
|
||||
formik?.setFieldValue('menuParentIcon', '')
|
||||
formik?.setFieldValue('languageTextMenuParentEn', '')
|
||||
formik?.setFieldValue('languageTextMenuParentTr', '')
|
||||
|
|
@ -959,7 +959,7 @@ const Wizard = () => {
|
|||
handlePermissionGroupChange('')
|
||||
if ((formik?.values.menuParentCode ?? '').toLowerCase() === deleted) {
|
||||
formik?.setFieldValue('menuParentCode', '')
|
||||
formik?.setFieldValue('menuParentShortName', '')
|
||||
formik?.setFieldValue('menuParentModuleId', '')
|
||||
formik?.setFieldValue('menuParentIcon', '')
|
||||
formik?.setFieldValue('languageTextMenuParentEn', '')
|
||||
formik?.setFieldValue('languageTextMenuParentTr', '')
|
||||
|
|
@ -975,7 +975,7 @@ const Wizard = () => {
|
|||
formik?.setFieldValue('createMenu', createMenu)
|
||||
if (createMenu) return
|
||||
formik?.setFieldValue('menuParentCode', '')
|
||||
formik?.setFieldValue('menuParentShortName', '')
|
||||
formik?.setFieldValue('menuParentModuleId', '')
|
||||
formik?.setFieldValue('menuParentIcon', '')
|
||||
formik?.setFieldValue('languageTextMenuParentEn', '')
|
||||
formik?.setFieldValue('languageTextMenuParentTr', '')
|
||||
|
|
@ -999,12 +999,12 @@ const Wizard = () => {
|
|||
formikRef.current?.setFieldValue('languageTextMenuParentEn', selectedMenu?.menuTextEn ?? '')
|
||||
formikRef.current?.setFieldValue('languageTextMenuParentTr', selectedMenu?.menuTextTr ?? '')
|
||||
if (!code) {
|
||||
formikRef.current?.setFieldValue('menuParentShortName', '')
|
||||
formikRef.current?.setFieldValue('menuParentModuleId', '')
|
||||
return
|
||||
}
|
||||
const rootCode = findRootCode(rawMenuItems, code)
|
||||
const rootMenu = rawMenuItems.find((item) => item.code === rootCode)
|
||||
formikRef.current?.setFieldValue('menuParentShortName', rootMenu?.shortName ?? '')
|
||||
formikRef.current?.setFieldValue('menuParentModuleId', rootMenu?.moduleId ?? '')
|
||||
applyPermissionGroupFromRoot(rootCode)
|
||||
}
|
||||
|
||||
|
|
@ -1014,7 +1014,7 @@ const Wizard = () => {
|
|||
menuTextEn: string
|
||||
menuTextTr: string
|
||||
icon?: string
|
||||
shortName?: string
|
||||
moduleId?: string
|
||||
}) => {
|
||||
formikRef.current?.setFieldValue('menuParentCode', menu.code)
|
||||
const nextMenuOrder =
|
||||
|
|
@ -1029,8 +1029,8 @@ const Wizard = () => {
|
|||
const rootCode = menu.parentCode ? findRootCode(rawMenuItems, menu.parentCode) : menu.code
|
||||
const existingRoot = rawMenuItems.find((item) => item.code === rootCode)
|
||||
formikRef.current?.setFieldValue(
|
||||
'menuParentShortName',
|
||||
menu.parentCode ? (existingRoot?.shortName ?? '') : (menu.shortName ?? ''),
|
||||
'menuParentModuleId',
|
||||
menu.parentCode ? (existingRoot?.moduleId ?? '') : (menu.moduleId ?? ''),
|
||||
)
|
||||
// Yeni menu kok seviyedeyse izin grubu ondan turetilir; gorunen adlar da menunun
|
||||
// dialogda girilen TR/EN metinleridir (menu heniz listede olmadigi icin buradan gecilir).
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ export interface WizardStepMenuProps {
|
|||
menuTextEn: string
|
||||
menuTextTr: string
|
||||
icon?: string
|
||||
shortName?: string
|
||||
moduleId?: string
|
||||
}) => void | Promise<void>
|
||||
onReloadMenu: () => void
|
||||
permissionGroupList: SelectBoxOption[]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { MenuItem } from '@/proxy/menus/menu'
|
|||
export interface MenuTreeNode {
|
||||
code: string
|
||||
displayName: string
|
||||
shortName?: string
|
||||
moduleId?: string
|
||||
icon?: string
|
||||
url?: string
|
||||
order?: number
|
||||
|
|
@ -22,7 +22,7 @@ export function buildMenuTree(items: MenuItem[]): MenuTreeNode[] {
|
|||
map.set(item.code!, {
|
||||
code: item.code!,
|
||||
displayName: item.displayName ?? item.code!,
|
||||
shortName: item.shortName ?? undefined,
|
||||
moduleId: item.moduleId ?? undefined,
|
||||
icon: item.icon ?? undefined,
|
||||
url: item.url ?? undefined,
|
||||
order: item.order ?? undefined,
|
||||
|
|
|
|||
|
|
@ -232,8 +232,13 @@ function RolesPermission({
|
|||
const response = await getPermissions(providerName, name)
|
||||
const data = response.data
|
||||
|
||||
const tenantGroup = tenant?.menuGroup?.trim()
|
||||
if (!tenantGroup) {
|
||||
// Kiracı birden fazla modüle sahip olabilir: "Sas|Adm"
|
||||
const tenantModules = (tenant?.modules ?? '')
|
||||
.split(MULTIVALUE_DELIMITER)
|
||||
.map((module: string) => module.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
if (!tenantModules.length) {
|
||||
setPermissionList(data)
|
||||
return
|
||||
}
|
||||
|
|
@ -241,12 +246,12 @@ function RolesPermission({
|
|||
const filteredGroups = data.groups
|
||||
.map((group: any) => {
|
||||
const filteredPermissions = group.permissions.filter((perm: any) => {
|
||||
if (!perm.menuGroup) return false
|
||||
const groups =
|
||||
typeof perm.menuGroup === 'string'
|
||||
? perm.menuGroup.split(MULTIVALUE_DELIMITER).map((g: string) => g.trim())
|
||||
: perm.menuGroup
|
||||
return groups.includes(tenantGroup)
|
||||
if (!perm.modules) return false
|
||||
const permissionModules =
|
||||
typeof perm.modules === 'string'
|
||||
? perm.modules.split(MULTIVALUE_DELIMITER).map((m: string) => m.trim())
|
||||
: perm.modules
|
||||
return permissionModules.some((module: string) => tenantModules.includes(module))
|
||||
})
|
||||
|
||||
return { ...group, permissions: filteredPermissions }
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import {
|
|||
Select,
|
||||
toast,
|
||||
} from '@/components/ui'
|
||||
import { getMenuGroups } from '@/services/menu.service'
|
||||
import { MULTIVALUE_DELIMITER } from '@/constants/app.constant'
|
||||
import { getModules } from '@/services/menu.service'
|
||||
import { createTenantFromOrder } from '@/services/tenant.service'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
|
|
@ -18,7 +19,7 @@ import * as Yup from 'yup'
|
|||
|
||||
type CreateTenantFromOrderValues = {
|
||||
name: string
|
||||
menuGroup: string
|
||||
modules: string[]
|
||||
}
|
||||
|
||||
type CreateTenantFromOrderDialogProps = {
|
||||
|
|
@ -29,7 +30,7 @@ type CreateTenantFromOrderDialogProps = {
|
|||
|
||||
const schema = Yup.object().shape({
|
||||
name: Yup.string().trim().required(),
|
||||
menuGroup: Yup.string().trim().required(),
|
||||
modules: Yup.array().of(Yup.string().trim()).min(1).required(),
|
||||
})
|
||||
|
||||
const CreateTenantFromOrderDialog = ({
|
||||
|
|
@ -38,35 +39,35 @@ const CreateTenantFromOrderDialog = ({
|
|||
orderId,
|
||||
}: CreateTenantFromOrderDialogProps) => {
|
||||
const { translate } = useLocalization()
|
||||
const [menuGroupOptions, setMenuGroupOptions] = useState<SelectBoxOption[]>([])
|
||||
const [isMenuGroupsLoading, setIsMenuGroupsLoading] = useState(false)
|
||||
const [moduleOptions, setModuleOptions] = useState<SelectBoxOption[]>([])
|
||||
const [isModulesLoading, setIsModulesLoading] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
return
|
||||
}
|
||||
|
||||
const fetchMenuGroups = async () => {
|
||||
setIsMenuGroupsLoading(true)
|
||||
const fetchModules = async () => {
|
||||
setIsModulesLoading(true)
|
||||
|
||||
try {
|
||||
const response = await getMenuGroups()
|
||||
const response = await getModules()
|
||||
const items = response?.data ?? []
|
||||
|
||||
setMenuGroupOptions(
|
||||
setModuleOptions(
|
||||
items.map((item: any) => ({
|
||||
value: String(item.key ?? item.Key ?? ''),
|
||||
label: String(item.name ?? item.Name ?? ''),
|
||||
})),
|
||||
)
|
||||
} catch {
|
||||
setMenuGroupOptions([])
|
||||
setModuleOptions([])
|
||||
} finally {
|
||||
setIsMenuGroupsLoading(false)
|
||||
setIsModulesLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
fetchMenuGroups()
|
||||
fetchModules()
|
||||
}, [open])
|
||||
|
||||
const handleSubmit = async (
|
||||
|
|
@ -79,7 +80,7 @@ const CreateTenantFromOrderDialog = ({
|
|||
await createTenantFromOrder({
|
||||
orderId,
|
||||
name: values.name.trim(),
|
||||
menuGroup: values.menuGroup.trim(),
|
||||
modules: values.modules.join(MULTIVALUE_DELIMITER),
|
||||
})
|
||||
|
||||
toast.push(
|
||||
|
|
@ -115,7 +116,7 @@ const CreateTenantFromOrderDialog = ({
|
|||
<Formik<CreateTenantFromOrderValues>
|
||||
initialValues={{
|
||||
name: '',
|
||||
menuGroup: 'Erp',
|
||||
modules: [],
|
||||
}}
|
||||
validationSchema={schema}
|
||||
onSubmit={handleSubmit}
|
||||
|
|
@ -124,20 +125,28 @@ const CreateTenantFromOrderDialog = ({
|
|||
<Form>
|
||||
<FormContainer>
|
||||
<FormItem
|
||||
label="Menu Group"
|
||||
invalid={Boolean(errors.menuGroup && touched.menuGroup)}
|
||||
errorMessage={errors.menuGroup}
|
||||
label={translate('::App.Listform.ListformField.Modules')}
|
||||
invalid={Boolean(errors.modules && touched.modules)}
|
||||
errorMessage={typeof errors.modules === 'string' ? errors.modules : undefined}
|
||||
>
|
||||
<Field name="menuGroup">
|
||||
{({ field, form }: FieldProps<string>) => (
|
||||
<Field name="modules">
|
||||
{({ field, form }: FieldProps<string[]>) => (
|
||||
<Select
|
||||
isMulti
|
||||
field={field}
|
||||
form={form}
|
||||
isClearable={true}
|
||||
isLoading={isMenuGroupsLoading}
|
||||
options={menuGroupOptions}
|
||||
value={menuGroupOptions.filter((option) => option.value === field.value)}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value ?? '')}
|
||||
isLoading={isModulesLoading}
|
||||
options={moduleOptions}
|
||||
value={moduleOptions.filter((option) =>
|
||||
(field.value ?? []).includes(option.value ?? ''),
|
||||
)}
|
||||
onChange={(options) =>
|
||||
form.setFieldValue(
|
||||
field.name,
|
||||
((options ?? []) as SelectBoxOption[]).map((option) => option.value),
|
||||
)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
|
|
|||
|
|
@ -1138,7 +1138,7 @@ function StepContentWrapper({ children }: { children: React.ReactNode }) {
|
|||
// ─── Simple Menu Tree (read-only selection) ───────────────────────────────────
|
||||
|
||||
interface SimpleMenuTreeNodeProps {
|
||||
node: MenuTreeNode & { shortName?: string }
|
||||
node: MenuTreeNode & { moduleId?: string }
|
||||
depth: number
|
||||
selectedCode: string
|
||||
onSelect: (code: string) => void
|
||||
|
|
@ -1187,7 +1187,7 @@ function SimpleMenuTreeNode({
|
|||
/>
|
||||
)}
|
||||
<span className="flex-1 text-sm truncate">{translate('::' + node.code)}</span>
|
||||
{node.shortName && (
|
||||
{node.moduleId && (
|
||||
<span
|
||||
className={`text-xs shrink-0 font-mono px-1.5 py-0.5 rounded ${
|
||||
isSelected
|
||||
|
|
@ -1195,7 +1195,7 @@ function SimpleMenuTreeNode({
|
|||
: 'bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400'
|
||||
}`}
|
||||
>
|
||||
{node.shortName}
|
||||
{node.moduleId}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -1203,7 +1203,7 @@ function SimpleMenuTreeNode({
|
|||
node.children.map((child: MenuTreeNode) => (
|
||||
<SimpleMenuTreeNode
|
||||
key={child.code}
|
||||
node={child as MenuTreeNode & { shortName?: string }}
|
||||
node={child as MenuTreeNode & { moduleId?: string }}
|
||||
depth={depth + 1}
|
||||
selectedCode={selectedCode}
|
||||
onSelect={onSelect}
|
||||
|
|
@ -1258,7 +1258,7 @@ function SimpleMenuTreeSelect({
|
|||
nodes.map((node) => (
|
||||
<SimpleMenuTreeNode
|
||||
key={node.code}
|
||||
node={node as MenuTreeNode & { shortName?: string }}
|
||||
node={node as MenuTreeNode & { moduleId?: string }}
|
||||
depth={0}
|
||||
selectedCode={selectedCode}
|
||||
onSelect={onSelect}
|
||||
|
|
@ -1389,7 +1389,7 @@ const SqlTableDesignerDialog = ({
|
|||
getMenus(0, 1000)
|
||||
.then((res) => {
|
||||
const items = (res.data?.items ?? []) as MenuItem[]
|
||||
const filtered = items.filter((m) => !!m.shortName?.trim())
|
||||
const filtered = items.filter((m) => !!m.moduleId?.trim())
|
||||
setRawMenuItems(filtered)
|
||||
const tree = filterNonLinkNodes(buildMenuTree(filtered))
|
||||
setMenuTree(tree)
|
||||
|
|
@ -1402,11 +1402,11 @@ const SqlTableDesignerDialog = ({
|
|||
useEffect(() => {
|
||||
if (!isOpen) return
|
||||
reloadMenus((items) => {
|
||||
// In edit mode, auto-select the matching menu code by shortName
|
||||
// In edit mode, auto-select the matching menu code by moduleId
|
||||
if (initialTableData) {
|
||||
const parts = initialTableData.tableName.split('_')
|
||||
const derivedShortName = parts[0] ?? ''
|
||||
const match = items.find((m) => m.shortName === derivedShortName)
|
||||
const derivedModuleId = parts[0] ?? ''
|
||||
const match = items.find((m) => m.moduleId === derivedModuleId)
|
||||
if (match?.code) setSelectedMenuCode(match.code)
|
||||
}
|
||||
})
|
||||
|
|
@ -1803,7 +1803,7 @@ const SqlTableDesignerDialog = ({
|
|||
const onMenuCodeSelect = (code: string) => {
|
||||
if (isEditMode) return
|
||||
const item = rawMenuItems.find((m) => m.code === code)
|
||||
const prefix = item?.shortName ?? ''
|
||||
const prefix = item?.moduleId ?? ''
|
||||
setSelectedMenuCode(code)
|
||||
const newTableName = buildTableName(prefix, settings.entityName)
|
||||
setSettings((s) => ({
|
||||
|
|
@ -2581,7 +2581,7 @@ const SqlTableDesignerDialog = ({
|
|||
onSaved={(menu) =>
|
||||
reloadMenus((items) => {
|
||||
const savedMenu = items.find((item) => item.code === menu.code)
|
||||
if (savedMenu?.code && savedMenu.shortName) {
|
||||
if (savedMenu?.code && savedMenu.moduleId) {
|
||||
onMenuCodeSelect(savedMenu.code)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Button, Dialog, Notification, toast } from '@/components/ui'
|
||||
import { MenuDto } from '@/proxy/menus/models'
|
||||
import { MenuItem } from '@/proxy/menus/menu'
|
||||
import { MenuService } from '@/services/menu.service'
|
||||
import { MenuService, ModuleLookupDto, getModules } from '@/services/menu.service'
|
||||
import { useNavigationIcons } from '@/proxy/menus/navigation-icon.config'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { FaChevronDown, FaEdit, FaPlus } from 'react-icons/fa'
|
||||
|
|
@ -10,6 +10,7 @@ import { useConfig } from '@/components/ui/ConfigProvider'
|
|||
import { useForm } from '@/components/ui/Form/context'
|
||||
import Input from '@/components/ui/Input'
|
||||
import Select from '@/components/ui/Select'
|
||||
import CreatableSelect from 'react-select/creatable'
|
||||
|
||||
const menuService = new MenuService()
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ export function IconPickerField({ value, onChange, invalid }: IconPickerFieldPro
|
|||
variant="plain"
|
||||
shape="round"
|
||||
size={controlSize}
|
||||
className={`input flex items-center gap-2 !justify-start !px-3 text-left text-sm !text-gray-700 dark:!text-gray-100
|
||||
className={`input flex items-center gap-2 !justify-start !px-2 text-left text-sm !text-gray-700 dark:!text-gray-100
|
||||
!bg-white dark:!bg-transparent !border !border-gray-300 dark:!border-gray-600 hover:!border-indigo-400
|
||||
${invalid ? 'input-invalid !border-red-500' : ''}`}
|
||||
>
|
||||
|
|
@ -170,10 +171,26 @@ export interface MenuAddDialogProps {
|
|||
menuTextEn: string
|
||||
menuTextTr: string
|
||||
icon?: string
|
||||
shortName?: string
|
||||
moduleId?: string
|
||||
}) => void | Promise<void>
|
||||
}
|
||||
|
||||
/** Menünün bağlı olduğu kök menüyü bulur; modül bilgisi kök menüde tutulur. */
|
||||
function findRootMenu(
|
||||
items: (MenuItem & { id?: string })[],
|
||||
code: string,
|
||||
): (MenuItem & { id?: string }) | undefined {
|
||||
let current = items.find((item) => item.code === code)
|
||||
const visited = new Set<string>()
|
||||
while (current?.parentCode && !visited.has(current.code ?? '')) {
|
||||
visited.add(current.code ?? '')
|
||||
const parent = items.find((item) => item.code === current!.parentCode)
|
||||
if (!parent) break
|
||||
current = parent
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
/** Düzenleme modunda menü kendi alt ağacına taşınamaz; aksi halde döngü oluşur. */
|
||||
function collectDescendantCodes(
|
||||
items: (MenuItem & { id?: string })[],
|
||||
|
|
@ -201,7 +218,7 @@ const emptyForm = (parentCode: string, order: number) => ({
|
|||
menuTextTr: '',
|
||||
parentCode,
|
||||
icon: '',
|
||||
shortName: '',
|
||||
moduleId: '',
|
||||
order,
|
||||
url: '',
|
||||
isDisabled: false,
|
||||
|
|
@ -231,7 +248,7 @@ export function MenuAddDialog({
|
|||
menuTextTr: editMenu.menuTextTr ?? '',
|
||||
parentCode: editMenu.parentCode ?? '',
|
||||
icon: editMenu.icon ?? '',
|
||||
shortName: editMenu.shortName ?? '',
|
||||
moduleId: editMenu.moduleId ?? '',
|
||||
order: editMenu.order ?? 0,
|
||||
url: editMenu.url ?? '',
|
||||
isDisabled: editMenu.isDisabled ?? false,
|
||||
|
|
@ -241,8 +258,34 @@ export function MenuAddDialog({
|
|||
setForm(emptyForm(initialParentCode, initialOrder))
|
||||
}, [isOpen, initialParentCode, initialOrder, editMenu])
|
||||
|
||||
// Kök menülerde kısa ad zorunlu; alt menülerde isteğe bağlıdır.
|
||||
const shortNameRequired = !form.parentCode.trim()
|
||||
// Modül kök menüde tanımlanır; alt menü bağlandığı kök menünün modülünü devralır.
|
||||
const isRootMenu = !form.parentCode.trim()
|
||||
const inheritedModuleId = useMemo(
|
||||
() => (isRootMenu ? '' : (findRootMenu(rawItems, form.parentCode.trim())?.moduleId ?? '')),
|
||||
[isRootMenu, rawItems, form.parentCode],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isRootMenu) return
|
||||
setForm((p) => (p.moduleId === inheritedModuleId ? p : { ...p, moduleId: inheritedModuleId }))
|
||||
}, [isRootMenu, inheritedModuleId])
|
||||
|
||||
const [modules, setModules] = useState<ModuleLookupDto[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) return
|
||||
getModules()
|
||||
.then((response) => setModules(response?.data ?? []))
|
||||
.catch(() => setModules([]))
|
||||
}, [isOpen])
|
||||
|
||||
const moduleSelectOptions = useMemo(
|
||||
() => modules.map((module) => ({ value: module.key, label: module.name })),
|
||||
[modules],
|
||||
)
|
||||
|
||||
const moduleLabel = (moduleId: string) =>
|
||||
modules.find((module) => module.key === moduleId)?.name ?? moduleId
|
||||
|
||||
// Düzenlenen menü, kendisi veya alt ağacındaki bir menünün altına taşınamaz.
|
||||
const parentOptions = useMemo(() => {
|
||||
|
|
@ -261,7 +304,7 @@ export function MenuAddDialog({
|
|||
|
||||
const handleSave = async () => {
|
||||
if (!form.code.trim() || !form.menuTextEn.trim()) return
|
||||
if (shortNameRequired && !form.shortName.trim()) return
|
||||
if (isRootMenu && !form.moduleId.trim()) return
|
||||
setSaving(true)
|
||||
try {
|
||||
const savedMenu = {
|
||||
|
|
@ -270,7 +313,7 @@ export function MenuAddDialog({
|
|||
displayName: form.code.trim(),
|
||||
parentCode: form.parentCode.trim() || undefined,
|
||||
icon: form.icon || undefined,
|
||||
shortName: form.shortName.trim() || undefined,
|
||||
moduleId: form.moduleId.trim() || undefined,
|
||||
order: form.order,
|
||||
isDisabled: form.isDisabled,
|
||||
url: form.url.trim() || undefined,
|
||||
|
|
@ -294,7 +337,7 @@ export function MenuAddDialog({
|
|||
menuTextEn: savedMenu.menuTextEn!,
|
||||
menuTextTr: savedMenu.menuTextTr!,
|
||||
icon: savedMenu.icon,
|
||||
shortName: savedMenu.shortName,
|
||||
moduleId: savedMenu.moduleId,
|
||||
})
|
||||
onClose()
|
||||
} catch (e: any) {
|
||||
|
|
@ -359,7 +402,8 @@ export function MenuAddDialog({
|
|||
code: `App.Wizard.${codeToken}`,
|
||||
menuTextEn: spacedLabel,
|
||||
menuTextTr: spacedLabel,
|
||||
shortName: codeToken.substring(0, 3),
|
||||
// Kök menüde girilen kısa kod modül olarak tanımlanır; öneri addan türer.
|
||||
moduleId: p.parentCode.trim() ? p.moduleId : codeToken.substring(0, 3),
|
||||
}))
|
||||
}}
|
||||
placeholder="MyMenu"
|
||||
|
|
@ -455,27 +499,32 @@ export function MenuAddDialog({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Row 5 — Short Name (full width) */}
|
||||
{/* Row 5 — Modül (full width) */}
|
||||
<div className="flex flex-col">
|
||||
<label className={labelCls}>
|
||||
{translate('::App.WizardStep1.ShortName')}
|
||||
{shortNameRequired ? (
|
||||
<span className="text-red-500 ml-0.5">*</span>
|
||||
) : (
|
||||
<span className="ml-1 text-gray-400 font-normal">
|
||||
({translate('::App.WizardStep1.Optional')})
|
||||
</span>
|
||||
)}
|
||||
{translate('::App.WizardStep1.ModuleId')}
|
||||
{isRootMenu && <span className="text-red-500 ml-0.5">*</span>}
|
||||
</label>
|
||||
<Input
|
||||
unstyle
|
||||
value={form.shortName}
|
||||
onChange={(e) => setForm((p) => ({ ...p, shortName: e.target.value }))}
|
||||
placeholder="Sas, Finance, Hr…"
|
||||
className={`${fieldCls}`}
|
||||
/>
|
||||
{shortNameRequired && (
|
||||
<p className="text-xs text-gray-400 mt-1">{translate('::App.Platform.MenuCodeHint')}</p>
|
||||
{isRootMenu ? (
|
||||
// Listede olmayan bir kod yazılabilir; kaydedildiğinde yeni modül olarak tanımlanır.
|
||||
<Select
|
||||
size="sm"
|
||||
isClearable
|
||||
componentAs={CreatableSelect}
|
||||
placeholder={translate('::App.Listform.ListformField.ModuleId')}
|
||||
menuPortalTarget={document.body}
|
||||
options={moduleSelectOptions}
|
||||
value={
|
||||
form.moduleId
|
||||
? { value: form.moduleId, label: moduleLabel(form.moduleId) }
|
||||
: null
|
||||
}
|
||||
onChange={(option) =>
|
||||
setForm((p) => ({ ...p, moduleId: (option as { value?: string } | null)?.value ?? '' }))
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Input unstyle disabled value={form.moduleId} className={disabledCls} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
@ -529,7 +578,7 @@ export function MenuAddDialog({
|
|||
!form.menuTextEn.trim() ||
|
||||
!form.menuTextTr.trim() ||
|
||||
!form.icon.trim() ||
|
||||
(shortNameRequired && !form.shortName.trim())
|
||||
(isRootMenu && !form.moduleId.trim())
|
||||
}
|
||||
onClick={handleSave}
|
||||
>
|
||||
|
|
|
|||
Loading…
Reference in a new issue