Wizard problemleri giderildi.

This commit is contained in:
Sedat Öztürk 2026-06-06 18:22:14 +03:00
parent 1c472a7d9a
commit 2f1b9d4e77
9 changed files with 184 additions and 54 deletions

View file

@ -39,6 +39,7 @@ public class ListFormWizardDto
public string PermissionGroupName { get; set; } public string PermissionGroupName { get; set; }
public string MenuParentCode { get; set; } public string MenuParentCode { get; set; }
public string MenuParentIcon { get; set; }
public string MenuIcon { get; set; } public string MenuIcon { get; set; }
public string DataSourceCode { get; set; } public string DataSourceCode { get; set; }
public string DataSourceConnectionString { get; set; } public string DataSourceConnectionString { get; set; }

View file

@ -60,10 +60,21 @@ public class ListFormWizardAppService(
public async Task Create(ListFormWizardDto input) public async Task Create(ListFormWizardDto input)
{ {
var wizardName = input.WizardName.Trim(); var wizardName = input.WizardName.Trim();
var titleLangKey = WizardConsts.WizardKeyTitle(wizardName); var code = string.IsNullOrWhiteSpace(input.MenuCode)
var nameLangKey = WizardConsts.WizardKey(wizardName); ? WizardConsts.WizardKey(wizardName)
var descLangKey = WizardConsts.WizardKeyDesc(wizardName); : input.MenuCode.Trim();
var code = WizardConsts.WizardKey(wizardName); var listFormCode = string.IsNullOrWhiteSpace(input.ListFormCode)
? code
: input.ListFormCode.Trim();
var titleLangKey = $"{listFormCode}.Title";
var nameLangKey = code;
var descLangKey = $"{listFormCode}.Desc";
var permCreateName = $"{code}.Create";
var permUpdateName = $"{code}.Update";
var permDeleteName = $"{code}.Delete";
var permExportName = $"{code}.Export";
var permImportName = $"{code}.Import";
var permNoteName = $"{code}.Note";
// Eklenen kayıtları takip et (silme işleminde kullanılır) // Eklenen kayıtları takip et (silme işleminde kullanılır)
var inserted = new WizardInsertedRecordsDto(); var inserted = new WizardInsertedRecordsDto();
@ -78,6 +89,9 @@ public class ListFormWizardAppService(
if (!await repoPermGroup.AnyAsync(a => a.Name == groupName)) if (!await repoPermGroup.AnyAsync(a => a.Name == groupName))
{ {
await repoPermGroup.InsertAsync(new PermissionGroupDefinitionRecord(GuidGenerator.Create(), groupName, groupName), autoSave: false); await repoPermGroup.InsertAsync(new PermissionGroupDefinitionRecord(GuidGenerator.Create(), groupName, groupName), autoSave: false);
if (string.Equals(groupName, input.MenuParentCode, StringComparison.OrdinalIgnoreCase))
await EnsureLangKey(groupName, inserted);
else
await CreateLangKey(groupName, groupName, groupName, inserted); await CreateLangKey(groupName, groupName, groupName, inserted);
inserted.PermissionGroupNames.Add(groupName); inserted.PermissionGroupNames.Add(groupName);
} }
@ -95,45 +109,45 @@ public class ListFormWizardAppService(
inserted.PermissionNames.Add(permRead.Name); inserted.PermissionNames.Add(permRead.Name);
} }
var permCreate = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermCreate(wizardName)); var permCreate = existingPerms.FirstOrDefault(a => a.Name == permCreateName);
if (permCreate == null) if (permCreate == null)
{ {
permCreate = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermCreate(wizardName), permRead.Name, WizardConsts.LangKeyCreate, true, MultiTenancySides.Both), autoSave: false); permCreate = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, permCreateName, permRead.Name, WizardConsts.LangKeyCreate, true, MultiTenancySides.Both), autoSave: false);
inserted.PermissionNames.Add(permCreate.Name); inserted.PermissionNames.Add(permCreate.Name);
} }
var permUpdate = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermUpdate(wizardName)); var permUpdate = existingPerms.FirstOrDefault(a => a.Name == permUpdateName);
if (permUpdate == null) if (permUpdate == null)
{ {
permUpdate = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermUpdate(wizardName), permRead.Name, WizardConsts.LangKeyUpdate, true, MultiTenancySides.Both), autoSave: false); permUpdate = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, permUpdateName, permRead.Name, WizardConsts.LangKeyUpdate, true, MultiTenancySides.Both), autoSave: false);
inserted.PermissionNames.Add(permUpdate.Name); inserted.PermissionNames.Add(permUpdate.Name);
} }
var permDelete = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermDelete(wizardName)); var permDelete = existingPerms.FirstOrDefault(a => a.Name == permDeleteName);
if (permDelete == null) if (permDelete == null)
{ {
permDelete = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermDelete(wizardName), permRead.Name, WizardConsts.LangKeyDelete, true, MultiTenancySides.Both), autoSave: false); permDelete = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, permDeleteName, permRead.Name, WizardConsts.LangKeyDelete, true, MultiTenancySides.Both), autoSave: false);
inserted.PermissionNames.Add(permDelete.Name); inserted.PermissionNames.Add(permDelete.Name);
} }
var permExport = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermExport(wizardName)); var permExport = existingPerms.FirstOrDefault(a => a.Name == permExportName);
if (permExport == null) if (permExport == null)
{ {
permExport = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermExport(wizardName), permRead.Name, WizardConsts.LangKeyExport, true, MultiTenancySides.Both), autoSave: false); permExport = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, permExportName, permRead.Name, WizardConsts.LangKeyExport, true, MultiTenancySides.Both), autoSave: false);
inserted.PermissionNames.Add(permExport.Name); inserted.PermissionNames.Add(permExport.Name);
} }
var permImport = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermImport(wizardName)); var permImport = existingPerms.FirstOrDefault(a => a.Name == permImportName);
if (permImport == null) if (permImport == null)
{ {
permImport = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermImport(wizardName), permRead.Name, WizardConsts.LangKeyImport, true, MultiTenancySides.Both), autoSave: false); permImport = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, permImportName, permRead.Name, WizardConsts.LangKeyImport, true, MultiTenancySides.Both), autoSave: false);
inserted.PermissionNames.Add(permImport.Name); inserted.PermissionNames.Add(permImport.Name);
} }
var permNote = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermNote(wizardName)); var permNote = existingPerms.FirstOrDefault(a => a.Name == permNoteName);
if (permNote == null) if (permNote == null)
{ {
permNote = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermNote(wizardName), permRead.Name, WizardConsts.LangKeyNote, true, MultiTenancySides.Both), autoSave: false); permNote = await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, permNoteName, permRead.Name, WizardConsts.LangKeyNote, true, MultiTenancySides.Both), autoSave: false);
inserted.PermissionNames.Add(permNote.Name); inserted.PermissionNames.Add(permNote.Name);
} }
@ -161,12 +175,18 @@ public class ListFormWizardAppService(
if (menuParent == null) if (menuParent == null)
{ {
var maxRootOrder = menuQueryable.Where(a => a.ParentCode == null || a.ParentCode == "").Select(a => (int?)a.Order).Max() ?? 0; var maxRootOrder = menuQueryable.Where(a => a.ParentCode == null || a.ParentCode == "").Select(a => (int?)a.Order).Max() ?? 0;
await CreateLangKey(WizardConsts.WizardKeyParent(wizardName), input.LanguageTextMenuParentEn, input.LanguageTextMenuParentTr, inserted); var menuParentIcon = !string.IsNullOrWhiteSpace(input.MenuParentIcon)
? input.MenuParentIcon
: !string.IsNullOrWhiteSpace(input.MenuIcon)
? input.MenuIcon
: WizardConsts.MenuIcon;
await CreateLangKey(input.MenuParentCode, input.LanguageTextMenuParentEn, input.LanguageTextMenuParentTr, inserted);
menuParent = await repoMenu.InsertAsync(new Menu menuParent = await repoMenu.InsertAsync(new Menu
{ {
Code = input.MenuParentCode, Code = input.MenuParentCode,
DisplayName = WizardConsts.WizardKeyParent(wizardName), DisplayName = input.MenuParentCode,
IsDisabled = false, IsDisabled = false,
Icon = menuParentIcon,
Order = maxRootOrder + 1, Order = maxRootOrder + 1,
}, autoSave: false); }, autoSave: false);
inserted.MenuCodes.Add(input.MenuParentCode); inserted.MenuCodes.Add(input.MenuParentCode);
@ -677,4 +697,16 @@ public class ListFormWizardAppService(
return existing; return existing;
} }
private async Task<LanguageKey> EnsureLangKey(string key, WizardInsertedRecordsDto inserted = null)
{
var res = PlatformConsts.AppName;
var existing = await repoLangKey.FirstOrDefaultAsync(a => a.ResourceName == res && a.Key == key);
if (existing != null) return existing;
existing = await repoLangKey.InsertAsync(new LanguageKey { ResourceName = res, Key = key }, autoSave: true);
inserted?.LanguageKeys.Add(key);
return existing;
}
} }

View file

@ -30,13 +30,15 @@ public class MenuAppService : CrudAppService<
private readonly IRepository<LanguageText, Guid> _repositoryText; private readonly IRepository<LanguageText, Guid> _repositoryText;
private readonly ITenantRepository _tenantRepository; private readonly ITenantRepository _tenantRepository;
private readonly IPermissionDefinitionRecordRepository _permissionRepository; private readonly IPermissionDefinitionRecordRepository _permissionRepository;
private readonly LanguageTextAppService _languageTextAppService;
public MenuAppService( public MenuAppService(
IRepository<Menu, Guid> menuRepository, IRepository<Menu, Guid> menuRepository,
IRepository<LanguageKey, Guid> languageKeyRepository, IRepository<LanguageKey, Guid> languageKeyRepository,
IRepository<LanguageText, Guid> languageTextRepository, IRepository<LanguageText, Guid> languageTextRepository,
ITenantRepository tenantRepository, ITenantRepository tenantRepository,
IPermissionDefinitionRecordRepository permissionRepository IPermissionDefinitionRecordRepository permissionRepository,
LanguageTextAppService languageTextAppService
) : base(menuRepository) ) : base(menuRepository)
{ {
_menuRepository = menuRepository; _menuRepository = menuRepository;
@ -44,6 +46,7 @@ public class MenuAppService : CrudAppService<
_repositoryText = languageTextRepository; _repositoryText = languageTextRepository;
_tenantRepository = tenantRepository; _tenantRepository = tenantRepository;
_permissionRepository = permissionRepository; _permissionRepository = permissionRepository;
_languageTextAppService = languageTextAppService;
CreatePolicyName = $"{AppCodes.Menus.Menu}.Create"; CreatePolicyName = $"{AppCodes.Menus.Menu}.Create";
UpdatePolicyName = $"{AppCodes.Menus.Menu}.Update"; UpdatePolicyName = $"{AppCodes.Menus.Menu}.Update";
@ -275,7 +278,7 @@ public class MenuAppService : CrudAppService<
if (existingEnText != null) if (existingEnText != null)
{ {
existingEnText.Value = input.MenuTextEn; existingEnText.Value = input.MenuTextEn;
await _repositoryText.UpdateAsync(existingEnText); await _repositoryText.UpdateAsync(existingEnText, autoSave: true);
} }
else else
{ {
@ -285,7 +288,7 @@ public class MenuAppService : CrudAppService<
CultureName = "en", CultureName = "en",
Value = input.MenuTextEn, Value = input.MenuTextEn,
ResourceName = PlatformConsts.AppName ResourceName = PlatformConsts.AppName
}); }, autoSave: true);
} }
// Türkçe text oluşturuluyor veya güncelleniyor. // Türkçe text oluşturuluyor veya güncelleniyor.
@ -297,7 +300,7 @@ public class MenuAppService : CrudAppService<
if (existingTrText != null) if (existingTrText != null)
{ {
existingTrText.Value = input.MenuTextTr; existingTrText.Value = input.MenuTextTr;
await _repositoryText.UpdateAsync(existingTrText); await _repositoryText.UpdateAsync(existingTrText, autoSave: true);
} }
else else
{ {
@ -307,9 +310,12 @@ public class MenuAppService : CrudAppService<
CultureName = "tr", CultureName = "tr",
Value = input.MenuTextTr, Value = input.MenuTextTr,
ResourceName = PlatformConsts.AppName ResourceName = PlatformConsts.AppName
}); }, autoSave: true);
} }
// Clear Redis Cache
await _languageTextAppService.ClearRedisCacheAsync();
return await base.CreateAsync(input); return await base.CreateAsync(input);
} }
} }

View file

@ -1071,6 +1071,22 @@
"dataType": "Number", "dataType": "Number",
"selectOptions": {}, "selectOptions": {},
"order": 80 "order": 80
},
{
"code": "Abp.Identity.OrganizationUnit.MaxUserMembershipCount",
"nameKey": "Abp.Identity.OrganizationUnit.MaxUserMembershipCount",
"descriptionKey": "Abp.Identity.OrganizationUnit.MaxUserMembershipCount.Description",
"defaultValue": "2147483647",
"isVisibleToClients": true,
"providers": "T|G|D",
"isInherited": true,
"isEncrypted": false,
"mainGroupKey": "Abp.Identity",
"subGroupKey": "Abp.Identity.OrganizationUnits",
"requiredPermissionName": "Abp.Identity.OrganizationUnits",
"dataType": "Number",
"selectOptions": {},
"order": 90
} }
], ],
"NotificationTypes": [], "NotificationTypes": [],

View file

@ -137,10 +137,21 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
input.Workflow.Criteria = input.WorkflowCriteria; input.Workflow.Criteria = input.WorkflowCriteria;
var wizardName = input.WizardName.Trim(); var wizardName = input.WizardName.Trim();
var titleLangKey = WizardConsts.WizardKeyTitle(wizardName); var code = string.IsNullOrWhiteSpace(input.MenuCode)
var nameLangKey = WizardConsts.WizardKey(wizardName); ? WizardConsts.WizardKey(wizardName)
var descLangKey = WizardConsts.WizardKeyDesc(wizardName); : input.MenuCode.Trim();
var code = WizardConsts.WizardKey(wizardName); var listFormCode = string.IsNullOrWhiteSpace(input.ListFormCode)
? code
: input.ListFormCode.Trim();
var titleLangKey = $"{listFormCode}.Title";
var nameLangKey = code;
var descLangKey = $"{listFormCode}.Desc";
var permCreateName = $"{code}.Create";
var permUpdateName = $"{code}.Update";
var permDeleteName = $"{code}.Delete";
var permExportName = $"{code}.Export";
var permImportName = $"{code}.Import";
var permNoteName = $"{code}.Note";
// Dil - Language Keys // Dil - Language Keys
await CreateLangKeyAsync(nameLangKey, input.LanguageTextMenuEn, input.LanguageTextMenuTr); await CreateLangKeyAsync(nameLangKey, input.LanguageTextMenuEn, input.LanguageTextMenuTr);
@ -153,6 +164,9 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
{ {
await _repoPermGroup.InsertAsync( await _repoPermGroup.InsertAsync(
new PermissionGroupDefinitionRecord(Guid.NewGuid(), groupName, groupName), autoSave: true); new PermissionGroupDefinitionRecord(Guid.NewGuid(), groupName, groupName), autoSave: true);
if (string.Equals(groupName, input.MenuParentCode, StringComparison.OrdinalIgnoreCase))
await EnsureLangKeyAsync(groupName);
else
await CreateLangKeyAsync(groupName, groupName, groupName); await CreateLangKeyAsync(groupName, groupName, groupName);
} }
@ -165,35 +179,35 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
permRead = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permRead = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, code, null, nameLangKey, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, code, null, nameLangKey, true, MultiTenancySides.Both), autoSave: true);
var permCreate = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermCreate(wizardName)); var permCreate = existingPerms.FirstOrDefault(a => a.Name == permCreateName);
if (permCreate == null) if (permCreate == null)
permCreate = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permCreate = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, WizardConsts.PermCreate(wizardName), permRead.Name, WizardConsts.LangKeyCreate, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, permCreateName, permRead.Name, WizardConsts.LangKeyCreate, true, MultiTenancySides.Both), autoSave: true);
var permUpdate = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermUpdate(wizardName)); var permUpdate = existingPerms.FirstOrDefault(a => a.Name == permUpdateName);
if (permUpdate == null) if (permUpdate == null)
permUpdate = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permUpdate = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, WizardConsts.PermUpdate(wizardName), permRead.Name, WizardConsts.LangKeyUpdate, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, permUpdateName, permRead.Name, WizardConsts.LangKeyUpdate, true, MultiTenancySides.Both), autoSave: true);
var permDelete = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermDelete(wizardName)); var permDelete = existingPerms.FirstOrDefault(a => a.Name == permDeleteName);
if (permDelete == null) if (permDelete == null)
permDelete = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permDelete = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, WizardConsts.PermDelete(wizardName), permRead.Name, WizardConsts.LangKeyDelete, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, permDeleteName, permRead.Name, WizardConsts.LangKeyDelete, true, MultiTenancySides.Both), autoSave: true);
var permExport = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermExport(wizardName)); var permExport = existingPerms.FirstOrDefault(a => a.Name == permExportName);
if (permExport == null) if (permExport == null)
permExport = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permExport = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, WizardConsts.PermExport(wizardName), permRead.Name, WizardConsts.LangKeyExport, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, permExportName, permRead.Name, WizardConsts.LangKeyExport, true, MultiTenancySides.Both), autoSave: true);
var permImport = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermImport(wizardName)); var permImport = existingPerms.FirstOrDefault(a => a.Name == permImportName);
if (permImport == null) if (permImport == null)
permImport = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permImport = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, WizardConsts.PermImport(wizardName), permRead.Name, WizardConsts.LangKeyImport, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, permImportName, permRead.Name, WizardConsts.LangKeyImport, true, MultiTenancySides.Both), autoSave: true);
var permNote = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermNote(wizardName)); var permNote = existingPerms.FirstOrDefault(a => a.Name == permNoteName);
if (permNote == null) if (permNote == null)
permNote = await _repoPerm.InsertAsync(new PermissionDefinitionRecord( permNote = await _repoPerm.InsertAsync(new PermissionDefinitionRecord(
Guid.NewGuid(), groupName, WizardConsts.PermNote(wizardName), permRead.Name, WizardConsts.LangKeyNote, true, MultiTenancySides.Both), autoSave: true); Guid.NewGuid(), groupName, permNoteName, permRead.Name, WizardConsts.LangKeyNote, true, MultiTenancySides.Both), autoSave: true);
// // Permission Grants - Admin role için, sadece eksik olanları ekle // // Permission Grants - Admin role için, sadece eksik olanları ekle
// var existingGrants = await _permissionGrantRepository.GetListAsync("R", PlatformConsts.AbpIdentity.User.AdminRoleName); // var existingGrants = await _permissionGrantRepository.GetListAsync("R", PlatformConsts.AbpIdentity.User.AdminRoleName);
@ -219,12 +233,18 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
if (menuParent == null) if (menuParent == null)
{ {
var maxRootOrder = menuQueryable.Where(a => a.ParentCode == null || a.ParentCode == "").Select(a => (int?)a.Order).Max() ?? 0; var maxRootOrder = menuQueryable.Where(a => a.ParentCode == null || a.ParentCode == "").Select(a => (int?)a.Order).Max() ?? 0;
await CreateLangKeyAsync(WizardConsts.WizardKeyParent(wizardName), input.LanguageTextMenuParentEn, input.LanguageTextMenuParentTr); var menuParentIcon = !string.IsNullOrWhiteSpace(input.MenuParentIcon)
? input.MenuParentIcon
: !string.IsNullOrWhiteSpace(input.MenuIcon)
? input.MenuIcon
: WizardConsts.MenuIcon;
await CreateLangKeyAsync(input.MenuParentCode, input.LanguageTextMenuParentEn, input.LanguageTextMenuParentTr);
menuParent = await _repoMenu.InsertAsync(new Menu menuParent = await _repoMenu.InsertAsync(new Menu
{ {
Code = input.MenuParentCode, Code = input.MenuParentCode,
DisplayName = WizardConsts.WizardKeyParent(wizardName), DisplayName = input.MenuParentCode,
IsDisabled = false, IsDisabled = false,
Icon = menuParentIcon,
Order = maxRootOrder + 1, Order = maxRootOrder + 1,
}, autoSave: true); }, autoSave: true);
} }
@ -427,6 +447,16 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
}, autoSave: true); }, autoSave: true);
} }
} }
private async Task EnsureLangKeyAsync(string key)
{
if (string.IsNullOrWhiteSpace(key)) return;
if (!await _repoLangKey.AnyAsync(a => a.ResourceName == _appName && a.Key == key))
{
await _repoLangKey.InsertAsync(new LanguageKey { ResourceName = _appName, Key = key }, autoSave: true);
}
}
} }

View file

@ -54,6 +54,7 @@ export interface ListFormWizardDto {
languageTextMenuParentTr: string languageTextMenuParentTr: string
permissionGroupName: string permissionGroupName: string
menuParentCode: string menuParentCode: string
menuParentIcon?: string
menuIcon: string menuIcon: string
dataSourceCode: string dataSourceCode: string
dataSourceConnectionString: string dataSourceConnectionString: string

View file

@ -71,6 +71,7 @@ const initialValues: ListFormWizardDto = {
languageTextMenuParentTr: '', languageTextMenuParentTr: '',
permissionGroupName: '', permissionGroupName: '',
menuParentCode: '', menuParentCode: '',
menuParentIcon: '',
menuIcon: '', menuIcon: '',
dataSourceCode: '', dataSourceCode: '',
dataSourceConnectionString: '', dataSourceConnectionString: '',
@ -241,6 +242,18 @@ const Wizard = () => {
]) ])
const isAuditColumn = (columnName: string) => AUDIT_COLUMNS.has(columnName.toLowerCase()) const isAuditColumn = (columnName: string) => AUDIT_COLUMNS.has(columnName.toLowerCase())
const isTenantColumn = (columnName: string) => columnName.toLowerCase() === 'tenantid'
const isAutoSelectedColumn = (columnName: string, isTenant = false) =>
!isAuditColumn(columnName) && !(isTenant && isTenantColumn(columnName))
const removeTenantColumn = (columns: Set<string>) =>
new Set([...columns].filter((columnName) => !isTenantColumn(columnName)))
const removeTenantGroupItems = (groups: WizardGroup[]) =>
groups.map((group) => ({
...group,
items: group.items.filter((item) => !isTenantColumn(item.dataField)),
}))
const loadColumns = async (dsCode: string, schema: string, name: string) => { const loadColumns = async (dsCode: string, schema: string, name: string) => {
if (!dsCode || !name) { if (!dsCode || !name) {
@ -254,12 +267,13 @@ const Wizard = () => {
const res = await sqlObjectManagerService.getTableColumns(dsCode, schema, name) const res = await sqlObjectManagerService.getTableColumns(dsCode, schema, name)
const cols = res.data ?? [] const cols = res.data ?? []
setSelectCommandColumns(cols) setSelectCommandColumns(cols)
const selectableColumns = cols.filter((c) => !isAuditColumn(c.columnName)) const colNames = new Set(cols.map((c) => c.columnName.toLowerCase()))
const hasTenantColumn = colNames.has('tenantid')
const selectableColumns = cols.filter((c) => isAutoSelectedColumn(c.columnName, hasTenantColumn))
setSelectedColumns(new Set(selectableColumns.map((c) => c.columnName))) setSelectedColumns(new Set(selectableColumns.map((c) => c.columnName)))
setEditingGroups([]) setEditingGroups([])
// Auto-check isTenant / isBranch based on column presence // Auto-check isTenant / isBranch based on column presence
const colNames = new Set(cols.map((c) => c.columnName.toLowerCase())) formikRef.current?.setFieldValue('isTenant', hasTenantColumn)
formikRef.current?.setFieldValue('isTenant', colNames.has('tenantid'))
formikRef.current?.setFieldValue('isBranch', colNames.has('branchid')) formikRef.current?.setFieldValue('isBranch', colNames.has('branchid'))
// Auto-select first column as key field // Auto-select first column as key field
if (cols.length > 0) { if (cols.length > 0) {
@ -285,17 +299,23 @@ const Wizard = () => {
return next return next
}) })
const toggleAllColumns = (all: boolean) => const toggleAllColumns = (all: boolean, isTenant = formikRef.current?.values.isTenant ?? false) =>
setSelectedColumns( setSelectedColumns(
all all
? new Set( ? new Set(
selectCommandColumns selectCommandColumns
.filter((c) => !isAuditColumn(c.columnName)) .filter((c) => isAutoSelectedColumn(c.columnName, isTenant))
.map((c) => c.columnName), .map((c) => c.columnName),
) )
: new Set(), : new Set(),
) )
const handleTenantChange = (isTenant: boolean) => {
if (!isTenant) return
setSelectedColumns((prev) => removeTenantColumn(prev))
setEditingGroups((prev) => removeTenantGroupItems(prev))
}
const getDataSourceList = async () => { const getDataSourceList = async () => {
setIsLoadingDataSource(true) setIsLoadingDataSource(true)
const response = await getDataSources() const response = await getDataSources()
@ -392,6 +412,7 @@ const Wizard = () => {
languageTextMenuParentTr: w.languageTextMenuParentTr ?? '', languageTextMenuParentTr: w.languageTextMenuParentTr ?? '',
permissionGroupName: w.permissionGroupName ?? '', permissionGroupName: w.permissionGroupName ?? '',
menuParentCode: w.menuParentCode ?? '', menuParentCode: w.menuParentCode ?? '',
menuParentIcon: w.menuParentIcon ?? '',
menuIcon: w.menuIcon ?? '', menuIcon: w.menuIcon ?? '',
dataSourceCode: w.dataSourceCode ?? '', dataSourceCode: w.dataSourceCode ?? '',
dataSourceConnectionString: w.dataSourceConnectionString ?? '', dataSourceConnectionString: w.dataSourceConnectionString ?? '',
@ -582,6 +603,8 @@ const Wizard = () => {
const handleMenuParentChange = (code: string) => { const handleMenuParentChange = (code: string) => {
formikRef.current?.setFieldValue('menuParentCode', code) formikRef.current?.setFieldValue('menuParentCode', code)
const selectedMenu = rawMenuItems.find((item) => item.code === code)
formikRef.current?.setFieldValue('menuParentIcon', selectedMenu?.icon ?? '')
if (!code) return if (!code) return
applyPermissionGroupFromRoot(findRootCode(rawMenuItems, code)) applyPermissionGroupFromRoot(findRootCode(rawMenuItems, code))
} }
@ -591,8 +614,10 @@ const Wizard = () => {
parentCode?: string parentCode?: string
menuTextEn: string menuTextEn: string
menuTextTr: string menuTextTr: string
icon?: string
}) => { }) => {
formikRef.current?.setFieldValue('menuParentCode', menu.code) formikRef.current?.setFieldValue('menuParentCode', menu.code)
formikRef.current?.setFieldValue('menuParentIcon', menu.icon ?? '')
formikRef.current?.setFieldValue('languageTextMenuParentEn', menu.menuTextEn) formikRef.current?.setFieldValue('languageTextMenuParentEn', menu.menuTextEn)
formikRef.current?.setFieldValue('languageTextMenuParentTr', menu.menuTextTr) formikRef.current?.setFieldValue('languageTextMenuParentTr', menu.menuTextTr)
@ -773,7 +798,10 @@ const Wizard = () => {
menuTree={menuTree} menuTree={menuTree}
isLoadingMenu={isLoadingMenu} isLoadingMenu={isLoadingMenu}
onMenuParentChange={handleMenuParentChange} onMenuParentChange={handleMenuParentChange}
onClearMenuParent={() => formikRef.current?.setFieldValue('menuParentCode', '')} onClearMenuParent={() => {
formikRef.current?.setFieldValue('menuParentCode', '')
formikRef.current?.setFieldValue('menuParentIcon', '')
}}
onMenuCreated={handleMenuCreated} onMenuCreated={handleMenuCreated}
onReloadMenu={getMenuList} onReloadMenu={getMenuList}
permissionGroupList={permissionGroupList} permissionGroupList={permissionGroupList}
@ -806,7 +834,8 @@ const Wizard = () => {
setSelectedColumns(new Set()) setSelectedColumns(new Set())
}} }}
onToggleColumn={toggleColumn} onToggleColumn={toggleColumn}
onToggleAllColumns={toggleAllColumns} onToggleAllColumns={(all) => toggleAllColumns(all, values.isTenant)}
onTenantChange={handleTenantChange}
translate={translate} translate={translate}
onBack={handleBack} onBack={handleBack}
onNext={handleNext2} onNext={handleNext2}

View file

@ -34,6 +34,7 @@ export interface WizardStep2Props {
onClearColumns: () => void onClearColumns: () => void
onToggleColumn: (col: string) => void onToggleColumn: (col: string) => void
onToggleAllColumns: (all: boolean) => void onToggleAllColumns: (all: boolean) => void
onTenantChange: (isTenant: boolean) => void
// Navigation // Navigation
translate: (key: string) => string translate: (key: string) => string
onBack: () => void onBack: () => void
@ -61,6 +62,7 @@ const WizardStep2 = ({
onClearColumns, onClearColumns,
onToggleColumn, onToggleColumn,
onToggleAllColumns, onToggleAllColumns,
onTenantChange,
translate, translate,
onBack, onBack,
onNext, onNext,
@ -347,7 +349,18 @@ const WizardStep2 = ({
invalid={!!(errors.isTenant && touched.isTenant)} invalid={!!(errors.isTenant && touched.isTenant)}
errorMessage={errors.isTenant} errorMessage={errors.isTenant}
> >
<Field type="checkbox" autoComplete="off" name="isTenant" component={Checkbox} /> <Field name="isTenant">
{({ field, form }: FieldProps<boolean>) => (
<Checkbox
name={field.name}
checked={Boolean(field.value)}
onChange={(checked) => {
form.setFieldValue(field.name, checked)
onTenantChange(checked)
}}
/>
)}
</Field>
</FormItem> </FormItem>
<FormItem <FormItem

View file

@ -471,9 +471,11 @@ const WizardStep7 = ({
<div className="text-xs font-semibold text-gray-700 dark:text-gray-200"> <div className="text-xs font-semibold text-gray-700 dark:text-gray-200">
{criteria.title || criteria.kind || `Criteria ${index + 1}`} {criteria.title || criteria.kind || `Criteria ${index + 1}`}
</div> </div>
{criteria.kind === 'Compare' && (
<div className="mt-1 text-[11px] text-gray-500 dark:text-gray-400"> <div className="mt-1 text-[11px] text-gray-500 dark:text-gray-400">
{criteria.compareColumn} {criteria.compareOperator} {criteria.compareValue} {criteria.compareColumn} {criteria.compareOperator} {criteria.compareValue}
</div> </div>
)}
<div className="text-[11px] text-gray-500 dark:text-gray-400"> <div className="text-[11px] text-gray-500 dark:text-gray-400">
Approver: {criteria.approver} Approver: {criteria.approver}
</div> </div>