Wizard Permission Group Name düzenlemesi
This commit is contained in:
parent
ec6b35d6d5
commit
9de6b1d05c
12 changed files with 571 additions and 59 deletions
|
|
@ -11,6 +11,9 @@ public interface IListFormWizardAppService
|
|||
Task<WizardSeedFileDto> GetFile(string fileName);
|
||||
Task DeleteFile(string fileName);
|
||||
|
||||
/// <summary>Izin gruplarini iki dilli gorunen adlariyla dondurur.</summary>
|
||||
Task<List<WizardPermissionGroupDto>> GetPermissionGroups();
|
||||
|
||||
/// <summary>Wizard dosyasini ve bagli seed dosyalarini zip olarak dondurur.</summary>
|
||||
Task<IRemoteStreamContent> ExportFile(string fileName);
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,17 @@ public class ListFormWizardDto
|
|||
public string LanguageTextMenuParentTr { get; set; }
|
||||
|
||||
public string PermissionGroupName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Izin grubunun Ingilizce gorunen adi. Grup yeni tanimlaniyorsa grup adiyla ayni olan dil
|
||||
/// anahtarina bu metin yazilir; mevcut bir grup secildiginde bos gelirse sunucu veritabanindaki
|
||||
/// degeri geri yazar, boylece seed dosyasi her durumda iki dilli gorunen adi tasir.
|
||||
/// </summary>
|
||||
public string PermissionGroupDisplayNameEn { get; set; }
|
||||
|
||||
/// <summary>Izin grubunun Turkce gorunen adi; <see cref="PermissionGroupDisplayNameEn"/> ile ayni kurallara tabidir.</summary>
|
||||
public string PermissionGroupDisplayNameTr { get; set; }
|
||||
|
||||
public string MenuParentCode { get; set; }
|
||||
public string MenuParentShortName { get; set; }
|
||||
public string MenuParentIcon { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
namespace Sozsoft.Platform.ListForms;
|
||||
|
||||
/// <summary>
|
||||
/// Wizard izin grubu secim listesi ogesi. Gorunen adlar, grup adiyla ayni olan dil
|
||||
/// anahtarinin metinlerinden okunur; secim yapildiginda forma bu degerler doldurulur.
|
||||
/// </summary>
|
||||
public class WizardPermissionGroupDto
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string DisplayNameEn { get; set; }
|
||||
public string DisplayNameTr { get; set; }
|
||||
}
|
||||
|
|
@ -138,15 +138,7 @@ public class ListFormWizardAppService(
|
|||
? PlatformConsts.AppName
|
||||
: input.PermissionGroupName.Trim();
|
||||
input.PermissionGroupName = groupName;
|
||||
if (!await repoPermGroup.AnyAsync(a => a.Name == groupName))
|
||||
{
|
||||
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);
|
||||
inserted.PermissionGroupNames.Add(groupName);
|
||||
}
|
||||
await ApplyPermissionGroupAsync(input, groupName, inserted);
|
||||
|
||||
// Permission'ları tek seferde kontrol et ve oluştur
|
||||
var existingPerms = await repoPerm.GetListAsync(a => a.GroupName == groupName);
|
||||
|
|
@ -676,6 +668,33 @@ public class ListFormWizardAppService(
|
|||
return routePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Izin gruplarini iki dilli gorunen adlariyla dondurur. Gorunen ad, grup adiyla ayni olan
|
||||
/// dil anahtarinin metnidir; wizard formu secim yapildiginda bu degerleri doldurur.
|
||||
/// </summary>
|
||||
public async Task<List<WizardPermissionGroupDto>> GetPermissionGroups()
|
||||
{
|
||||
var res = PlatformConsts.AppName;
|
||||
var groups = await repoPermGroup.GetListAsync();
|
||||
var names = groups.Where(g => g.Name != null).Select(g => g.Name!).ToList();
|
||||
|
||||
var texts = await repoLangText.GetListAsync(a => a.ResourceName == res && names.Contains(a.Key));
|
||||
var textsByKey = texts.Where(t => t.Key != null).GroupBy(t => t.Key!).ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
return [.. groups
|
||||
.OrderBy(g => g.Name)
|
||||
.Select(g =>
|
||||
{
|
||||
textsByKey.TryGetValue(g.Name, out var groupTexts);
|
||||
return new WizardPermissionGroupDto
|
||||
{
|
||||
Name = g.Name,
|
||||
DisplayNameEn = groupTexts?.FirstOrDefault(t => t.CultureName == cultureNameDefault)?.Value ?? g.DisplayName,
|
||||
DisplayNameTr = groupTexts?.FirstOrDefault(t => t.CultureName == LanguageCodes.Tr)?.Value ?? g.DisplayName
|
||||
};
|
||||
})];
|
||||
}
|
||||
|
||||
public async Task<List<WizardFileInfoDto>> GetFiles()
|
||||
{
|
||||
var outputPath = ResolveWizardSeedOutputPath();
|
||||
|
|
@ -1575,6 +1594,70 @@ public class ListFormWizardAppService(
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Izin grubunu ve iki dilli gorunen adini hazirlar.
|
||||
/// <para>
|
||||
/// Grup yeniyse kaydi ve grup adiyla ayni olan dil anahtarini uretir; gorunen ad
|
||||
/// girilmediyse grup adina duser. Grup zaten varsa veritabani metinlerine dokunulmaz,
|
||||
/// yalnizca kullanici acikca farkli bir metin girdiyse guncellenir. Her durumda
|
||||
/// <paramref name="input"/> uzerindeki gorunen adlar doldurulur; seed dosyasi mevcut bir
|
||||
/// grup secildiginde de iki dilli gorunen adi tasimalidir.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
private async Task ApplyPermissionGroupAsync(ListFormWizardDto input, string groupName, WizardInsertedRecordsDto inserted)
|
||||
{
|
||||
var displayEn = input.PermissionGroupDisplayNameEn?.Trim();
|
||||
var displayTr = input.PermissionGroupDisplayNameTr?.Trim();
|
||||
|
||||
if (!await repoPermGroup.AnyAsync(a => a.Name == groupName))
|
||||
{
|
||||
await repoPermGroup.InsertAsync(new PermissionGroupDefinitionRecord(GuidGenerator.Create(), groupName, groupName), autoSave: false);
|
||||
|
||||
// Grup adi ust menu koduyla ayniysa dil anahtari menu metinleriyle zaten uretilir;
|
||||
// burada uzerine yazmak menu adini bozar.
|
||||
if (string.Equals(groupName, input.MenuParentCode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
await EnsureLangKey(groupName, inserted);
|
||||
displayEn = string.IsNullOrWhiteSpace(displayEn) ? input.LanguageTextMenuParentEn?.Trim() : displayEn;
|
||||
displayTr = string.IsNullOrWhiteSpace(displayTr) ? input.LanguageTextMenuParentTr?.Trim() : displayTr;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayEn = string.IsNullOrWhiteSpace(displayEn) ? groupName : displayEn;
|
||||
displayTr = string.IsNullOrWhiteSpace(displayTr) ? groupName : displayTr;
|
||||
await CreateLangKey(groupName, displayEn, displayTr, inserted);
|
||||
}
|
||||
|
||||
inserted.PermissionGroupNames.Add(groupName);
|
||||
}
|
||||
else
|
||||
{
|
||||
var (existingEn, existingTr) = await GetLangTextsAsync(groupName);
|
||||
|
||||
// Mevcut grubun metinleri yalnizca kullanici bilerek degistirdiginde guncellenir.
|
||||
var changed = (!string.IsNullOrWhiteSpace(displayEn) && displayEn != existingEn)
|
||||
|| (!string.IsNullOrWhiteSpace(displayTr) && displayTr != existingTr);
|
||||
|
||||
displayEn = string.IsNullOrWhiteSpace(displayEn) ? (existingEn ?? groupName) : displayEn;
|
||||
displayTr = string.IsNullOrWhiteSpace(displayTr) ? (existingTr ?? groupName) : displayTr;
|
||||
|
||||
if (changed)
|
||||
await CreateLangKey(groupName, displayEn, displayTr, inserted);
|
||||
}
|
||||
|
||||
input.PermissionGroupDisplayNameEn = string.IsNullOrWhiteSpace(displayEn) ? groupName : displayEn;
|
||||
input.PermissionGroupDisplayNameTr = string.IsNullOrWhiteSpace(displayTr) ? groupName : displayTr;
|
||||
}
|
||||
|
||||
/// <summary>Bir dil anahtarinin Ingilizce/Turkce metinlerini dondurur; yoksa null.</summary>
|
||||
private async Task<(string? En, string? Tr)> GetLangTextsAsync(string key)
|
||||
{
|
||||
var res = PlatformConsts.AppName;
|
||||
var texts = await repoLangText.GetListAsync(a => a.ResourceName == res && a.Key == key);
|
||||
return (texts.FirstOrDefault(a => a.CultureName == cultureNameDefault)?.Value,
|
||||
texts.FirstOrDefault(a => a.CultureName == LanguageCodes.Tr)?.Value);
|
||||
}
|
||||
|
||||
private async Task<LanguageKey> CreateLangKey(string key, string textEn, string textTr, WizardInsertedRecordsDto inserted = null)
|
||||
{
|
||||
var res = PlatformConsts.AppName;
|
||||
|
|
|
|||
|
|
@ -16290,6 +16290,48 @@
|
|||
"en": "Permission Group Name",
|
||||
"tr": "İzin Grubu Adı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupDefine",
|
||||
"en": "Define Permission Group",
|
||||
"tr": "İzin Grubu Tanımla"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupDisplayName",
|
||||
"en": "Permission Group Display Name",
|
||||
"tr": "İzin Grubu Görünen Adı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupDisplayNameRequired",
|
||||
"en": "Define the display names of the permission group",
|
||||
"tr": "İzin grubunun görünen adlarını tanımlayın"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupNewHint",
|
||||
"en": "The group will be created on deploy with these display names.",
|
||||
"tr": "Grup, deploy sırasında bu görünen adlarla oluşturulur."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupExistsHint",
|
||||
"en": "This group already exists; changing the display names updates its texts on deploy.",
|
||||
"tr": "Bu grup zaten var; görünen adları değiştirmek deploy sırasında metinlerini günceller."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupDisplayNameEn",
|
||||
"en": "Permission Group Display Name (English)",
|
||||
"tr": "İzin Grubu Görünen Adı (İngilizce)"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.PermissionGroupDisplayNameTr",
|
||||
"en": "Permission Group Display Name (Turkish)",
|
||||
"tr": "İzin Grubu Görünen Adı (Türkçe)"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.WizardStep1.NoMenusAvailable",
|
||||
|
|
|
|||
|
|
@ -192,12 +192,15 @@ public class WizardDataSeeder : IDataSeedContributor, ITransientDependency
|
|||
{
|
||||
await _repoPermGroup.InsertAsync(
|
||||
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);
|
||||
}
|
||||
|
||||
// Grup adi ust menu koduyla ayniysa dil anahtari menu metinleriyle uretilir; aksi halde
|
||||
// gorunen adlar yazilir. CreateLangKeyAsync mevcut metinlerin uzerine yazmaz.
|
||||
if (string.Equals(groupName, input.MenuParentCode, StringComparison.OrdinalIgnoreCase))
|
||||
await EnsureLangKeyAsync(groupName);
|
||||
else
|
||||
await CreateLangKeyAsync(groupName, input.PermissionGroupDisplayNameEn?.Trim(), input.PermissionGroupDisplayNameTr?.Trim());
|
||||
|
||||
// Permissions - tek seferde mevcut permission'ları çek, sonra her birini kontrol et
|
||||
var permQueryable = await _repoPerm.GetQueryableAsync();
|
||||
var existingPerms = permQueryable.Where(a => a.GroupName == groupName).ToList();
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
"LanguageTextMenuParentEn": "Sample",
|
||||
"LanguageTextMenuParentTr": "Sample",
|
||||
"PermissionGroupName": "App.Wizard.Sample",
|
||||
"PermissionGroupDisplayNameEn": "Sample",
|
||||
"PermissionGroupDisplayNameTr": "Sample",
|
||||
"MenuParentCode": "App.Wizard.Sample",
|
||||
"MenuParentShortName": "Sam",
|
||||
"MenuParentIcon": "FcBookmark",
|
||||
|
|
|
|||
|
|
@ -84,6 +84,10 @@ export interface ListFormWizardDto {
|
|||
languageTextMenuParentEn: string
|
||||
languageTextMenuParentTr: string
|
||||
permissionGroupName: string
|
||||
/** Izin grubunun Ingilizce gorunen adi; grup adiyla ayni olan dil anahtarina yazilir. */
|
||||
permissionGroupDisplayNameEn: string
|
||||
/** Izin grubunun Turkce gorunen adi. */
|
||||
permissionGroupDisplayNameTr: string
|
||||
menuParentCode: string
|
||||
menuParentShortName?: string
|
||||
menuParentIcon?: string
|
||||
|
|
@ -106,6 +110,13 @@ export interface ListFormWizardDto {
|
|||
widgets?: WidgetEditDto[]
|
||||
}
|
||||
|
||||
/** Izin grubu secim listesi ogesi; gorunen adlar grup adiyla ayni olan dil anahtarindan gelir. */
|
||||
export interface WizardPermissionGroupDto {
|
||||
name: string
|
||||
displayNameEn: string
|
||||
displayNameTr: string
|
||||
}
|
||||
|
||||
export interface WizardFileInfoDto {
|
||||
fileName: string
|
||||
wizardName: string
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
WizardFileInfoDto,
|
||||
WizardImportAnalysisDto,
|
||||
WizardImportApplyResultDto,
|
||||
WizardPermissionGroupDto,
|
||||
WizardSeedFileDto,
|
||||
} from '@/proxy/admin/wizard/models'
|
||||
import apiService from './api.service'
|
||||
|
|
@ -14,6 +15,13 @@ export const postListFormWizard = (input: ListFormWizardDto) =>
|
|||
data: input,
|
||||
})
|
||||
|
||||
/** Izin gruplarini iki dilli gorunen adlariyla getirir. */
|
||||
export const getWizardPermissionGroups = () =>
|
||||
apiService.fetchData<WizardPermissionGroupDto[]>({
|
||||
method: 'GET',
|
||||
url: `/api/app/list-form-wizard/permission-groups`,
|
||||
})
|
||||
|
||||
export const getWizardFiles = () =>
|
||||
apiService.fetchData<WizardFileInfoDto[]>({
|
||||
method: 'GET',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { useLocation, useNavigate } from 'react-router-dom'
|
|||
import * as Yup from 'yup'
|
||||
import { FaFolderOpen } from 'react-icons/fa'
|
||||
import { getMenus } from '@/services/menu.service'
|
||||
import { getPermissions } from '@/services/identity.service'
|
||||
import { getDataSources } from '@/services/data-source.service'
|
||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||
import type { SqlObjectExplorerDto, DatabaseColumnDto } from '@/proxy/sql-query-manager/models'
|
||||
|
|
@ -35,7 +34,13 @@ import WizardStepDeploy from './WizardStepDeploy'
|
|||
import { Container } from '@/components/shared'
|
||||
import { sqlDataTypeToDbType } from '../edit/options'
|
||||
import { useStoreActions } from '@/store/store'
|
||||
import { getWizardFile, getWizardFiles, postListFormWizard } from '@/services/wizard.service'
|
||||
import { useStoreState } from '@/store'
|
||||
import {
|
||||
getWizardFile,
|
||||
getWizardFiles,
|
||||
getWizardPermissionGroups,
|
||||
postListFormWizard,
|
||||
} from '@/services/wizard.service'
|
||||
import { ListFormWizardDto, WizardComponentKindEnum } from '@/proxy/admin/wizard/models'
|
||||
import WizardStepComponent from './WizardStepComponent'
|
||||
import WizardStepCustomComponent from './WizardStepCustomComponent'
|
||||
|
|
@ -158,6 +163,8 @@ const initialValues: ListFormWizardDto = {
|
|||
languageTextMenuParentEn: '',
|
||||
languageTextMenuParentTr: '',
|
||||
permissionGroupName: '',
|
||||
permissionGroupDisplayNameEn: '',
|
||||
permissionGroupDisplayNameTr: '',
|
||||
menuParentCode: '',
|
||||
menuParentShortName: '',
|
||||
menuParentIcon: '',
|
||||
|
|
@ -186,6 +193,9 @@ const step1ValidationSchema = Yup.object().shape({
|
|||
createMenu: Yup.boolean(),
|
||||
// İzin grubu menüden bağımsızdır: menüsüz wizard'da da izinler üretilir ve bir gruba yazılır.
|
||||
permissionGroupName: Yup.string().required(),
|
||||
// Grup adi ile birlikte iki dilli gorunen ad da seed dosyasina yazilir; bos birakilamaz.
|
||||
permissionGroupDisplayNameEn: Yup.string().required(),
|
||||
permissionGroupDisplayNameTr: Yup.string().required(),
|
||||
languageTextMenuEn: Yup.string().required(),
|
||||
languageTextMenuTr: Yup.string().required(),
|
||||
})
|
||||
|
|
@ -542,7 +552,17 @@ const Wizard = () => {
|
|||
const [isLoadingMenu, setIsLoadingMenu] = useState(false)
|
||||
const [menuTree, setMenuTree] = useState<MenuTreeNode[]>([])
|
||||
const [rawMenuItems, setRawMenuItems] = useState<(MenuItem & { id?: string })[]>([])
|
||||
const { translate } = useLocalization()
|
||||
const { translate, cultureName } = useLocalization()
|
||||
// Dil secimi store'da tutulur; abpConfig'teki kultur, secim sonrasi config yenilenene
|
||||
// kadar eski degeri tasiyabildigi icin once store okunur.
|
||||
const currentLang = useStoreState((state) => state.locale.currentLang)
|
||||
/** Izin grubu etiketi, uygulamanin acik olan dilinde gosterilir. */
|
||||
const isTurkishUi = (currentLang || cultureName || '').toLowerCase().startsWith('tr')
|
||||
const permissionGroupLabel = (group: {
|
||||
name: string
|
||||
displayNameEn: string
|
||||
displayNameTr: string
|
||||
}) => (isTurkishUi ? group.displayNameTr : group.displayNameEn) || group.name
|
||||
const getMenuList = async () => {
|
||||
setIsLoadingMenu(true)
|
||||
const response = await getMenus()
|
||||
|
|
@ -558,17 +578,83 @@ const Wizard = () => {
|
|||
// ── Permission Groups ──
|
||||
const [isLoadingPermissionGroup, setIsLoadingPermissionGroup] = useState(false)
|
||||
const [permissionGroupList, setPermissionGroupList] = useState<SelectBoxOption[]>([])
|
||||
// Secilen grubun iki dilli gorunen adini forma doldurmak icin ad -> metin esleme.
|
||||
const permissionGroupTextsRef = useRef<Record<string, { en: string; tr: string }>>({})
|
||||
const getPermissionGroupList = async () => {
|
||||
setIsLoadingPermissionGroup(true)
|
||||
const response = await getPermissions('R', '')
|
||||
if (response.data?.groups) {
|
||||
setPermissionGroupList(
|
||||
response.data.groups.map((item: any) => ({ value: item.name, label: item.displayName })),
|
||||
)
|
||||
}
|
||||
const response = await getWizardPermissionGroups()
|
||||
const groups = response.data ?? []
|
||||
permissionGroupTextsRef.current = groups.reduce(
|
||||
(acc, item) => ({
|
||||
...acc,
|
||||
[item.name]: { en: item.displayNameEn ?? '', tr: item.displayNameTr ?? '' },
|
||||
}),
|
||||
{} as Record<string, { en: string; tr: string }>,
|
||||
)
|
||||
setPermissionGroupList(
|
||||
groups.map((item) => ({ value: item.name, label: permissionGroupLabel(item) })),
|
||||
)
|
||||
setIsLoadingPermissionGroup(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Izin grubu secimi/olusturulmasi. Mevcut bir grup secildiginde gorunen adlar veritabanindaki
|
||||
* degerlerle doldurulur; yeni bir ad yazildiginda grup adi ilk deger olarak onerilir. Her iki
|
||||
* durumda da alanlar dolu kalir, cunku seed dosyasi iki dilli gorunen adi tasimak zorundadir.
|
||||
*/
|
||||
const handlePermissionGroupChange = (
|
||||
groupName: string,
|
||||
/** Grup mevcut degilse kullanilacak metinler; yeni olusturulan menu henuz listede yoktur. */
|
||||
fallbackTexts?: { en: string; tr: string },
|
||||
) => {
|
||||
const formik = formikRef.current
|
||||
formik?.setFieldValue('permissionGroupName', groupName)
|
||||
if (!groupName) {
|
||||
formik?.setFieldValue('permissionGroupDisplayNameEn', '')
|
||||
formik?.setFieldValue('permissionGroupDisplayNameTr', '')
|
||||
return
|
||||
}
|
||||
// Sirasiyla: mevcut grubun metinleri, cagiranin verdigi metinler, ayni koda sahip menunun
|
||||
// metinleri. Grup adi kod oldugu icin en son care olarak kullanilir.
|
||||
const texts = permissionGroupTextsRef.current[groupName]
|
||||
const menu = rawMenuItems.find((item) => item.code === groupName)
|
||||
formik?.setFieldValue(
|
||||
'permissionGroupDisplayNameEn',
|
||||
texts?.en || fallbackTexts?.en || menu?.menuTextEn || groupName,
|
||||
)
|
||||
formik?.setFieldValue(
|
||||
'permissionGroupDisplayNameTr',
|
||||
texts?.tr || fallbackTexts?.tr || menu?.menuTextTr || groupName,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Dialogda tanimlanan grup. Kayit veritabanina yazilmaz; deploy adiminda grup yoksa uretilir,
|
||||
* varsa metinler yalnizca burada degistirildiginde guncellenir. Yeni ad, secim listesine de
|
||||
* eklenir ki kullanici adimlar arasinda gidip gelince secim kaybolmasin.
|
||||
*/
|
||||
const handlePermissionGroupDefine = (group: {
|
||||
name: string
|
||||
displayNameEn: string
|
||||
displayNameTr: string
|
||||
}) => {
|
||||
const formik = formikRef.current
|
||||
permissionGroupTextsRef.current[group.name] = {
|
||||
en: group.displayNameEn,
|
||||
tr: group.displayNameTr,
|
||||
}
|
||||
setPermissionGroupList((prev) =>
|
||||
prev.some((o) => o.value === group.name)
|
||||
? prev.map((o) =>
|
||||
o.value === group.name ? { ...o, label: permissionGroupLabel(group) } : o,
|
||||
)
|
||||
: [...prev, { value: group.name, label: permissionGroupLabel(group) }],
|
||||
)
|
||||
formik?.setFieldValue('permissionGroupName', group.name)
|
||||
formik?.setFieldValue('permissionGroupDisplayNameEn', group.displayNameEn)
|
||||
formik?.setFieldValue('permissionGroupDisplayNameTr', group.displayNameTr)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getDataSourceList()
|
||||
getMenuList()
|
||||
|
|
@ -646,6 +732,8 @@ const Wizard = () => {
|
|||
languageTextMenuParentEn: w.languageTextMenuParentEn ?? '',
|
||||
languageTextMenuParentTr: w.languageTextMenuParentTr ?? '',
|
||||
permissionGroupName: w.permissionGroupName ?? '',
|
||||
permissionGroupDisplayNameEn: w.permissionGroupDisplayNameEn ?? '',
|
||||
permissionGroupDisplayNameTr: w.permissionGroupDisplayNameTr ?? '',
|
||||
menuParentCode: w.menuParentCode ?? '',
|
||||
menuParentShortName: w.menuParentShortName ?? '',
|
||||
menuParentIcon: w.menuParentIcon ?? '',
|
||||
|
|
@ -810,19 +898,23 @@ const Wizard = () => {
|
|||
return null
|
||||
}
|
||||
|
||||
const applyPermissionGroupFromRoot = (rootCode: string) => {
|
||||
const applyPermissionGroupFromRoot = (
|
||||
rootCode: string,
|
||||
/** Kok menu heniz listede degilse (yeni eklendi) gorunen ad olarak kullanilacak metinler. */
|
||||
fallbackTexts?: { en: string; tr: string },
|
||||
) => {
|
||||
const rootItem = rawMenuItems.find((i) => i.code === rootCode)
|
||||
|
||||
// 1. Use group field if set
|
||||
if (rootItem?.group) {
|
||||
formikRef.current?.setFieldValue('permissionGroupName', rootItem.group)
|
||||
handlePermissionGroupChange(rootItem.group)
|
||||
return
|
||||
}
|
||||
|
||||
// 2. Match root code exactly against permission group names (e.g. "App.Saas" -> "App.Saas")
|
||||
const exactMatch = permissionGroupList.find((g) => g.value === rootCode)
|
||||
if (exactMatch) {
|
||||
formikRef.current?.setFieldValue('permissionGroupName', exactMatch.value)
|
||||
handlePermissionGroupChange(exactMatch.value ?? '')
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -833,13 +925,53 @@ const Wizard = () => {
|
|||
g.value?.toLowerCase().includes(lastSegment),
|
||||
)
|
||||
if (partialMatch) {
|
||||
formikRef.current?.setFieldValue('permissionGroupName', partialMatch.value)
|
||||
handlePermissionGroupChange(partialMatch.value ?? '')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Fallback: set rootCode as a new creatable value (SelectBox supports free input)
|
||||
formikRef.current?.setFieldValue('permissionGroupName', rootCode)
|
||||
handlePermissionGroupChange(rootCode, fallbackTexts)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ust menu secimi kaldirilir. Izin grubu yalnizca kaldirilan menuden turetilmisse
|
||||
* (grup adi menunun kendisi ya da kok kodu ile ayni) temizlenir; kullanici baska bir grup
|
||||
* sectiyse secimi korunur.
|
||||
*/
|
||||
const handleClearMenuParent = () => {
|
||||
const formik = formikRef.current
|
||||
const parentCode = formik?.values.menuParentCode ?? ''
|
||||
const group = (formik?.values.permissionGroupName ?? '').toLowerCase()
|
||||
const derivedFromParent =
|
||||
!!group &&
|
||||
(group === parentCode.toLowerCase() ||
|
||||
group === findRootCode(rawMenuItems, parentCode).toLowerCase())
|
||||
|
||||
formik?.setFieldValue('menuParentCode', '')
|
||||
formik?.setFieldValue('menuParentShortName', '')
|
||||
formik?.setFieldValue('menuParentIcon', '')
|
||||
formik?.setFieldValue('languageTextMenuParentEn', '')
|
||||
formik?.setFieldValue('languageTextMenuParentTr', '')
|
||||
if (derivedFromParent) handlePermissionGroupChange('')
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu agacindan bir menu silindiginde, o koda bagli secimler formda kalmamalidir:
|
||||
* secili ust menu ve ayni koda sahip izin grubu temizlenir.
|
||||
*/
|
||||
const handleMenuDeleted = (code: string) => {
|
||||
const formik = formikRef.current
|
||||
const deleted = code.toLowerCase()
|
||||
if ((formik?.values.permissionGroupName ?? '').toLowerCase() === deleted)
|
||||
handlePermissionGroupChange('')
|
||||
if ((formik?.values.menuParentCode ?? '').toLowerCase() === deleted) {
|
||||
formik?.setFieldValue('menuParentCode', '')
|
||||
formik?.setFieldValue('menuParentShortName', '')
|
||||
formik?.setFieldValue('menuParentIcon', '')
|
||||
formik?.setFieldValue('languageTextMenuParentEn', '')
|
||||
formik?.setFieldValue('languageTextMenuParentTr', '')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -908,7 +1040,12 @@ const Wizard = () => {
|
|||
'menuParentShortName',
|
||||
menu.parentCode ? (existingRoot?.shortName ?? '') : (menu.shortName ?? ''),
|
||||
)
|
||||
applyPermissionGroupFromRoot(rootCode)
|
||||
// Yeni menu kok seviyedeyse izin grubu ondan turetilir; gorunen adlar da menunun
|
||||
// dialogda girilen TR/EN metinleridir (menu heniz listede olmadigi icin buradan gecilir).
|
||||
applyPermissionGroupFromRoot(
|
||||
rootCode,
|
||||
menu.parentCode ? undefined : { en: menu.menuTextEn, tr: menu.menuTextTr },
|
||||
)
|
||||
|
||||
await getMenuList()
|
||||
}
|
||||
|
|
@ -1210,15 +1347,14 @@ const Wizard = () => {
|
|||
isLoadingMenu={isLoadingMenu}
|
||||
onMenuParentChange={handleMenuParentChange}
|
||||
onCreateMenuChange={handleCreateMenuChange}
|
||||
onClearMenuParent={() => {
|
||||
formikRef.current?.setFieldValue('menuParentCode', '')
|
||||
formikRef.current?.setFieldValue('menuParentShortName', '')
|
||||
formikRef.current?.setFieldValue('menuParentIcon', '')
|
||||
}}
|
||||
onClearMenuParent={handleClearMenuParent}
|
||||
onMenuDeleted={handleMenuDeleted}
|
||||
onMenuCreated={handleMenuCreated}
|
||||
onReloadMenu={getMenuList}
|
||||
permissionGroupList={permissionGroupList}
|
||||
isLoadingPermissionGroup={isLoadingPermissionGroup}
|
||||
onPermissionGroupChange={handlePermissionGroupChange}
|
||||
onPermissionGroupDefine={handlePermissionGroupDefine}
|
||||
onBack={() =>
|
||||
setCurrentStep(
|
||||
values.componentKind === WizardComponentKindEnum.Custom
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Button } from '@/components/ui'
|
||||
import { Button } from '@/components/ui'
|
||||
import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import {
|
||||
|
|
@ -92,6 +92,7 @@ function buildLogSteps(
|
|||
label: translate('::App.Step4Log.ConfiguringPermission', {
|
||||
0: values.permissionGroupName,
|
||||
}),
|
||||
detail: `EN: ${values.permissionGroupDisplayNameEn} / TR: ${values.permissionGroupDisplayNameTr}`,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
|
|
@ -122,6 +123,7 @@ function buildLogSteps(
|
|||
label: translate('::App.Step4Log.ConfiguringPermission', {
|
||||
0: values.permissionGroupName,
|
||||
}),
|
||||
detail: `EN: ${values.permissionGroupDisplayNameEn} / TR: ${values.permissionGroupDisplayNameTr}`,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
|
|
@ -320,6 +322,14 @@ const WizardStepDeploy = ({
|
|||
label={translate('::App.WizardStep4.PermissionGroup')}
|
||||
value={values.permissionGroupName}
|
||||
/>
|
||||
<Row
|
||||
label={translate('::App.WizardStep1.PermissionGroupDisplayNameTr')}
|
||||
value={values.permissionGroupDisplayNameTr}
|
||||
/>
|
||||
<Row
|
||||
label={translate('::App.WizardStep1.PermissionGroupDisplayNameEn')}
|
||||
value={values.permissionGroupDisplayNameEn}
|
||||
/>
|
||||
<Row label={translate('::App.Listform.ListformField.Icon')} value={values.menuIcon} />
|
||||
<Row label={translate('::App.WizardStep4.MenuTr')} value={values.languageTextMenuTr} />
|
||||
<Row label={translate('::App.WizardStep4.MenuEn')} value={values.languageTextMenuEn} />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
import { Button, FormItem, Input, Notification, Select, Switcher, toast } from '@/components/ui'
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
FormItem,
|
||||
Input,
|
||||
Notification,
|
||||
Select,
|
||||
Switcher,
|
||||
toast,
|
||||
} from '@/components/ui'
|
||||
import classNames from 'classnames'
|
||||
import { SelectBoxOption } from '@/types/shared'
|
||||
import { useNavigationIcons } from '@/proxy/menus/navigation-icon.config'
|
||||
|
|
@ -246,6 +255,8 @@ interface MenuTreeInlineProps {
|
|||
isLoading: boolean
|
||||
invalid?: boolean
|
||||
onReload: () => void
|
||||
/** Silinen menünün kodu; forma yazılmış bağlı seçimleri temizlemek için. */
|
||||
onDeleted: (code: string) => void
|
||||
/** Düzenleme dialogunu ilgili menü ile açar. */
|
||||
onEditMenu: (node: MenuTreeNode & { id?: string }) => void
|
||||
initialExpanded?: Set<string>
|
||||
|
|
@ -259,6 +270,7 @@ function MenuTreeInline({
|
|||
isLoading,
|
||||
invalid,
|
||||
onReload,
|
||||
onDeleted,
|
||||
onEditMenu,
|
||||
initialExpanded,
|
||||
}: MenuTreeInlineProps) {
|
||||
|
|
@ -295,6 +307,7 @@ function MenuTreeInline({
|
|||
setSaving(true)
|
||||
try {
|
||||
await menuService.delete(node.id)
|
||||
onDeleted(node.code)
|
||||
onReload()
|
||||
} catch (e: any) {
|
||||
toast.push(<Notification title={e.message} type="danger" />, {
|
||||
|
|
@ -353,6 +366,146 @@ function MenuTreeInline({
|
|||
)
|
||||
}
|
||||
|
||||
// ─── PermissionGroupDialog ───────────────────────────────────────────────────
|
||||
|
||||
export interface PermissionGroupDefinition {
|
||||
name: string
|
||||
displayNameEn: string
|
||||
displayNameTr: string
|
||||
}
|
||||
|
||||
interface PermissionGroupDialogProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
/** Dialog acilirken forma yazilmis degerler; yeni tanimda bos gelir. */
|
||||
initialValue: PermissionGroupDefinition
|
||||
/** Mevcut izin gruplarinin adlari; girilen ad bunlardan biriyse uyari gosterilir. */
|
||||
existingNames: string[]
|
||||
onSave: (group: PermissionGroupDefinition) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Izin grubu tanimlama dialogu. AbpPermissionGroups'ta Name ve DisplayName ayni yazilir,
|
||||
* gorunen ad dil anahtarindan cozulur; bu yuzden burada Name ile birlikte iki dilli gorunen
|
||||
* ad alinir. Kayit yalnizca wizard formuna yazilir, veritabani kaydi deploy adiminda uretilir.
|
||||
*/
|
||||
function PermissionGroupDialog({
|
||||
isOpen,
|
||||
onClose,
|
||||
initialValue,
|
||||
existingNames,
|
||||
onSave,
|
||||
}: PermissionGroupDialogProps) {
|
||||
const { translate } = useLocalization()
|
||||
const [form, setForm] = useState<PermissionGroupDefinition>(initialValue)
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) setForm(initialValue)
|
||||
}, [isOpen, initialValue])
|
||||
|
||||
const name = form.name.trim()
|
||||
const isExisting = existingNames.some((n) => n.toLowerCase() === name.toLowerCase())
|
||||
const canSave = !!name && !!form.displayNameEn.trim() && !!form.displayNameTr.trim()
|
||||
|
||||
const fieldCls =
|
||||
'h-9 px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-200 outline-none focus:border-indigo-400 w-full'
|
||||
const labelCls = 'text-xs font-medium text-gray-500 dark:text-gray-400 mb-1'
|
||||
|
||||
return (
|
||||
<Dialog isOpen={isOpen} width={620} onClose={onClose} onRequestClose={onClose}>
|
||||
<div className="flex flex-col gap-5 p-1">
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-2 pb-1 border-b border-gray-100 dark:border-gray-700">
|
||||
{isExisting ? (
|
||||
<FaEdit className="text-indigo-500 text-sm" />
|
||||
) : (
|
||||
<FaPlus className="text-green-500 text-sm" />
|
||||
)}
|
||||
<h5 className="text-base font-semibold text-gray-800 dark:text-gray-100">
|
||||
{translate('::App.WizardStep1.PermissionGroupDefine')}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
{/* Name */}
|
||||
<div className="flex flex-col">
|
||||
<label className={labelCls}>
|
||||
{translate('::App.WizardStep1.PermissionGroupName')}{' '}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
unstyle
|
||||
autoFocus
|
||||
className={`${fieldCls} font-mono`}
|
||||
placeholder="App.Wizard.MyGroup"
|
||||
value={form.name}
|
||||
onChange={(e) => setForm((p) => ({ ...p, name: e.target.value }))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Display names */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="flex flex-col">
|
||||
<label className={labelCls}>
|
||||
{translate('::App.WizardStep1.PermissionGroupDisplayNameTr')}{' '}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
unstyle
|
||||
className={fieldCls}
|
||||
value={form.displayNameTr}
|
||||
onChange={(e) => setForm((p) => ({ ...p, displayNameTr: e.target.value }))}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<label className={labelCls}>
|
||||
{translate('::App.WizardStep1.PermissionGroupDisplayNameEn')}{' '}
|
||||
<span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
unstyle
|
||||
className={fieldCls}
|
||||
value={form.displayNameEn}
|
||||
onChange={(e) => setForm((p) => ({ ...p, displayNameEn: e.target.value }))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Ad mevcut bir gruba denk geliyorsa deploy o grubun metinlerini gunceller. */}
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||
{translate(
|
||||
isExisting
|
||||
? '::App.WizardStep1.PermissionGroupExistsHint'
|
||||
: '::App.WizardStep1.PermissionGroupNewHint',
|
||||
)}
|
||||
</p>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="flex justify-end gap-2 pt-1 border-t border-gray-100 dark:border-gray-700">
|
||||
<Button type="button" size="sm" variant="plain" onClick={onClose}>
|
||||
{translate('::App.Platform.Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="solid"
|
||||
disabled={!canSave}
|
||||
onClick={() => {
|
||||
onSave({
|
||||
name,
|
||||
displayNameEn: form.displayNameEn.trim(),
|
||||
displayNameTr: form.displayNameTr.trim(),
|
||||
})
|
||||
onClose()
|
||||
}}
|
||||
>
|
||||
{translate('::App.Platform.Save')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
// ─── WizardStepMenu ──────────────────────────────────────────────────────────────
|
||||
|
||||
export interface WizardStepMenuProps {
|
||||
|
|
@ -369,7 +522,10 @@ export interface WizardStepMenuProps {
|
|||
onMenuParentChange: (code: string) => void
|
||||
/** Menuye eklenip eklenmeyecegi; false iken menuye ozel alanlar hic sorulmaz. */
|
||||
onCreateMenuChange: (createMenu: boolean) => void
|
||||
/** Ust menu secimini ve ona bagli olarak turetilen izin grubunu temizler. */
|
||||
onClearMenuParent: () => void
|
||||
/** Menu agacindan bir menu silindiginde cagrilir; koda bagli secimler temizlenir. */
|
||||
onMenuDeleted: (code: string) => void
|
||||
onMenuCreated: (menu: {
|
||||
code: string
|
||||
parentCode?: string
|
||||
|
|
@ -381,6 +537,10 @@ export interface WizardStepMenuProps {
|
|||
onReloadMenu: () => void
|
||||
permissionGroupList: SelectBoxOption[]
|
||||
isLoadingPermissionGroup: boolean
|
||||
/** Listeden grup secildiginde iki dilli gorunen ad alanlarini da doldurur. */
|
||||
onPermissionGroupChange: (groupName: string) => void
|
||||
/** Dialogda tanimlanan grup adi ve iki dilli gorunen adi forma yazar. */
|
||||
onPermissionGroupDefine: (group: PermissionGroupDefinition) => void
|
||||
onBack: () => void
|
||||
onNext: () => void
|
||||
translate: (key: string) => string
|
||||
|
|
@ -404,15 +564,19 @@ const WizardStepMenu = ({
|
|||
onMenuParentChange,
|
||||
onCreateMenuChange,
|
||||
onClearMenuParent,
|
||||
onMenuDeleted,
|
||||
onMenuCreated,
|
||||
onReloadMenu,
|
||||
permissionGroupList,
|
||||
isLoadingPermissionGroup,
|
||||
onPermissionGroupChange,
|
||||
onPermissionGroupDefine,
|
||||
onBack,
|
||||
onNext,
|
||||
translate,
|
||||
}: WizardStepMenuProps) => {
|
||||
const [menuDialogOpen, setMenuDialogOpen] = useState(false)
|
||||
const [permissionGroupDialogOpen, setPermissionGroupDialogOpen] = useState(false)
|
||||
const [menuDialogParentCode, setMenuDialogParentCode] = useState('')
|
||||
// Dolu ise dialog düzenleme modunda açılır.
|
||||
const [menuBeingEdited, setMenuBeingEdited] = useState<(MenuItem & { id?: string }) | null>(null)
|
||||
|
|
@ -463,6 +627,10 @@ const WizardStepMenu = ({
|
|||
// burada kontrol edilmezse "Next" aktif görünüp sessizce çalışmıyordu.
|
||||
createMenu && !(Number(values.menuOrder) >= 1) && translate('::App.WizardStep1.MenuOrder'),
|
||||
!values.permissionGroupName && translate('::App.WizardStep1.PermissionGroupName'),
|
||||
!values.permissionGroupDisplayNameEn &&
|
||||
translate('::App.WizardStep1.PermissionGroupDisplayNameEn'),
|
||||
!values.permissionGroupDisplayNameTr &&
|
||||
translate('::App.WizardStep1.PermissionGroupDisplayNameTr'),
|
||||
!values.languageTextMenuEn && translate('::App.WizardStep4.MenuEn'),
|
||||
!values.languageTextMenuTr && translate('::App.WizardStep4.MenuTr'),
|
||||
createMenu && !values.menuIcon && translate('::App.WizardStep4.MenuIcon'),
|
||||
|
|
@ -590,6 +758,7 @@ const WizardStepMenu = ({
|
|||
isLoading={isLoadingMenu}
|
||||
invalid={false}
|
||||
onReload={onReloadMenu}
|
||||
onDeleted={onMenuDeleted}
|
||||
onEditMenu={handleEditMenu}
|
||||
initialExpanded={
|
||||
values.menuParentCode
|
||||
|
|
@ -661,32 +830,54 @@ const WizardStepMenu = ({
|
|||
errorMessage={errors.permissionGroupName}
|
||||
asterisk={true}
|
||||
>
|
||||
<Field type="text" autoComplete="off" name="permissionGroupName">
|
||||
{({ field, form }: FieldProps<string>) => (
|
||||
<Select
|
||||
componentAs={CreatableSelect}
|
||||
field={field}
|
||||
form={form}
|
||||
placeholder={translate('::App.WizardStep1.PermissionGroupName')}
|
||||
isClearable={true}
|
||||
isLoading={isLoadingPermissionGroup}
|
||||
options={permissionGroupList}
|
||||
value={
|
||||
values.permissionGroupName
|
||||
? (permissionGroupList?.find(
|
||||
(o) => o.value === values.permissionGroupName,
|
||||
) ?? {
|
||||
label: values.permissionGroupName,
|
||||
value: values.permissionGroupName,
|
||||
})
|
||||
: null
|
||||
}
|
||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1">
|
||||
<Field type="text" autoComplete="off" name="permissionGroupName">
|
||||
{({ field, form }: FieldProps<string>) => (
|
||||
<Select
|
||||
field={field}
|
||||
form={form}
|
||||
placeholder={translate('::App.WizardStep1.PermissionGroupName')}
|
||||
isLoading={isLoadingPermissionGroup}
|
||||
options={permissionGroupList}
|
||||
value={
|
||||
values.permissionGroupName
|
||||
? (permissionGroupList?.find(
|
||||
(o) => o.value === values.permissionGroupName,
|
||||
) ?? {
|
||||
label: values.permissionGroupName,
|
||||
value: values.permissionGroupName,
|
||||
})
|
||||
: null
|
||||
}
|
||||
onChange={(option) => onPermissionGroupChange(option?.value ?? '')}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
</div>
|
||||
{/* Gorunen adlar dialogda tanimlanir; listeden secilen grupta da duzenlenebilir. */}
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
icon={values.permissionGroupName ? <FaEdit /> : <FaPlus />}
|
||||
title={translate('::App.WizardStep1.PermissionGroupDefine')}
|
||||
onClick={() => setPermissionGroupDialogOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
</FormItem>
|
||||
|
||||
<PermissionGroupDialog
|
||||
isOpen={permissionGroupDialogOpen}
|
||||
existingNames={permissionGroupList.map((o) => o.value ?? '')}
|
||||
initialValue={{
|
||||
name: values.permissionGroupName ?? '',
|
||||
displayNameEn: values.permissionGroupDisplayNameEn ?? '',
|
||||
displayNameTr: values.permissionGroupDisplayNameTr ?? '',
|
||||
}}
|
||||
onClose={() => setPermissionGroupDialogOpen(false)}
|
||||
onSave={onPermissionGroupDefine}
|
||||
/>
|
||||
|
||||
{createMenu && (
|
||||
<>
|
||||
{/* Menu Icon */}
|
||||
|
|
|
|||
Loading…
Reference in a new issue